Convert contiguous point array to ROI

Hi ImageJ/FIJI programming experts

How can I create an outline (ROI or selection) of an array of points with x and y coordinates (points occupy a contiguous area on the image) using jython script or java commands. See exemplary image below


Any help would be much appreciated

Thank you in advance!!

In Java the command is e.g. like

Roi roi = new PolygonRoi(xcoord, ycoord, n, roiType);

It should be similar in jython.

More information can be found in Functions.java.
There the function makeSelection() implements the macro function
makeSelection(type, xpoints, ypoints).

Thank you so much for responding.

I meant smth different though.

I have an array of points (e.g. cell) that aren’t the outline of an area but rather constitute the area (see image below)

if I use makeSelection or PolygonRoi – what I get is the dots connected by segments.

Instead I want to get an outline of the area in the form of selection or Roi.

Any advise?

and here is the macro code to play with commands:

newImage(“Untitled”, “16-bit black”, 500, 500, 1);
a=newArray(321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,316,316,316,316,316,316,316,316,316,325,325,325,325,325,325,325,325,325,325,325,325,325,325,325,325,325,325,325,314,324,314,314,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,329,324,329,324,328,329,324,328,329,328,329,329,328,329,328,329,328,329,329,328,329,329,315,328,329,326,315,328,326,317,326,328,315,317,326,328,326,315,328,317,326,315,328,326,317,315,326,317,326,326,326,317,319,317,326,323,319,322,326,318,317,326,323,322,318,319,317,326,322,318,327,323,319,317,326,327,322,326,319,318,323,317,327,327,319,322,323,318,319,327,322,323,318,323,327,322,319,318,323,327,319,322,318,327,323,322,319,327,318,322,323,319,323,327,318,322,319,323,327,319,322,318,323,322,327,319,318,322,323,327,330,319,323,322,327,318,330,319,327,318,322,323,330,319,318,327,330,322,323,319,330,322,323,322,330,323,330,323,330,330,330,330,330,331,331,331,331,331,331,331,331,331,331,331,332,332,332,332,332,332,332,332,332,332,332,333,333,333,333,333,333,333,333,333,334,334,334,334,335,334,335,334,335,335,334,335,334,335,335,335,336,336,336,336,336,336,336,337,337,337,337,337,337,338,338,338);
b=newArray(120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,123,124,125,126,127,128,129,130,131,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,126,122,127,128,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,124,139,125,140,124,126,141,125,127,126,128,129,127,130,128,131,129,132,133,130,134,135,125,132,136,123,126,133,124,122,125,134,127,123,126,135,127,128,136,124,128,129,137,129,125,130,130,126,131,132,133,127,120,128,134,121,121,121,135,121,129,136,122,122,122,122,130,137,123,123,123,123,123,131,138,124,124,139,124,124,124,132,125,126,125,125,125,125,126,127,126,126,126,127,128,127,127,127,128,129,128,128,128,130,129,129,129,131,129,130,130,130,131,132,130,131,131,132,133,132,132,131,133,133,134,133,132,134,134,135,125,134,135,135,136,133,126,135,137,134,136,136,127,136,135,138,128,137,137,137,129,138,138,139,130,139,131,140,132,133,134,135,136,125,126,127,128,129,130,131,132,133,134,135,125,126,127,128,129,130,131,132,133,134,135,126,127,128,129,130,131,132,133,134,127,128,129,130,127,131,128,132,129,130,133,131,134,132,133,134,128,129,130,131,132,133,134,128,129,130,131,132,133,127,128,129);
makeSelection(“polygon”, a, b)

Hello Yury -

You can do this by taking the convex hull.

Starting with Peter’s code (tweaked to be jython):

roi = PolygonRoi (xcoord, ycoord, n, Roi.POLYGON)
roicvx = PolygonRoi (roi.getFloatConvexHull(), Roi.POLYGON)

roicvx will now be the convex hull of your xcoord, ycoord points.

If you have an active image with your “points” Roi set, you could
also execute IJ.run ('Convex Hull'). This corresponds to the
Edit > Selection > Convex Hull menu command.

Thanks, mm

2 Likes

Dear MM (sorry don’t know your name)

Thank you so much – I tried it. It does work but significantly lacks in precision. Obviously because it is trying to be convex. Is there any way I could do it with Wand class and command? (see image below for the convex hull results).

Yury

Hello Yury -

Okay, I think I see what you might be asking for.

Let me assume that your points always lie on a square array
(the integer lattice), and that you want neighboring points to
be treated as contiguous.

Here’s an overkill, but reasonably simple algorithm that I think
will do what you want.

Iterate through all of your points, and find every point that has
both a (+ or -) x neighbor and a (+ or -) y neighbor. Take each
such point and its two neighbors, build from them a triangular
Roi, and add it to the ROI Manager. (A given point could be
the “corner” point for up to four such triangular Rois.) Then run
“OR (Combine)” on the whole set of these triangular Rois to
get your desired Roi.

Note that with this particular scheme, the “hole” in your array
will be preserved. This may or may not be what you want, but
it’s plausible. If you don’t want the hole, you’ll need to build
somewhat larger little Rois to “OR” together, or add some
after-the-fact hole-filling logic.

Thanks, mm

1 Like

Hi @bmyury,

It looks as though those points are actually representing binary pixels (the type of coordinates you’d get by running Roi.getContainedPoints(xpoints, ypoints) in a macro). If that’s the case, the easiest way to get a boundary is actually drawing the points in an auxiliary image and extracting the ROI (via magic wand, or Analyze Particles).

Nico

1 Like

Thanks!! That’s what I think should be used as well. Would you be able to show how to do that with jython or java code?

This is super smart!! But complicated :slight_smile:

Ok, this might not be really elegant, but will get you started:

from ij import IJ
from ij.gui import Roi, PointRoi


xpoints = [321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,316,316,316,316,316,316,316,316,316,325,325,325,325,325,325,325,325,325,325,325,325,325,325,325,325,325,325,325,314,324,314,314,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,329,324,329,324,328,329,324,328,329,328,329,329,328,329,328,329,328,329,329,328,329,329,315,328,329,326,315,328,326,317,326,328,315,317,326,328,326,315,328,317,326,315,328,326,317,315,326,317,326,326,326,317,319,317,326,323,319,322,326,318,317,326,323,322,318,319,317,326,322,318,327,323,319,317,326,327,322,326,319,318,323,317,327,327,319,322,323,318,319,327,322,323,318,323,327,322,319,318,323,327,319,322,318,327,323,322,319,327,318,322,323,319,323,327,318,322,319,323,327,319,322,318,323,322,327,319,318,322,323,327,330,319,323,322,327,318,330,319,327,318,322,323,330,319,318,327,330,322,323,319,330,322,323,322,330,323,330,323,330,330,330,330,330,331,331,331,331,331,331,331,331,331,331,331,332,332,332,332,332,332,332,332,332,332,332,333,333,333,333,333,333,333,333,333,334,334,334,334,335,334,335,334,335,335,334,335,334,335,335,335,336,336,336,336,336,336,336,337,337,337,337,337,337,338,338,338]
ypoints = [120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,123,124,125,126,127,128,129,130,131,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,126,122,127,128,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,124,139,125,140,124,126,141,125,127,126,128,129,127,130,128,131,129,132,133,130,134,135,125,132,136,123,126,133,124,122,125,134,127,123,126,135,127,128,136,124,128,129,137,129,125,130,130,126,131,132,133,127,120,128,134,121,121,121,135,121,129,136,122,122,122,122,130,137,123,123,123,123,123,131,138,124,124,139,124,124,124,132,125,126,125,125,125,125,126,127,126,126,126,127,128,127,127,127,128,129,128,128,128,130,129,129,129,131,129,130,130,130,131,132,130,131,131,132,133,132,132,131,133,133,134,133,132,134,134,135,125,134,135,135,136,133,126,135,137,134,136,136,127,136,135,138,128,137,137,137,129,138,138,139,130,139,131,140,132,133,134,135,136,125,126,127,128,129,130,131,132,133,134,135,125,126,127,128,129,130,131,132,133,134,135,126,127,128,129,130,131,132,133,134,127,128,129,130,127,131,128,132,129,130,133,131,134,132,133,134,128,129,130,131,132,133,134,128,129,130,131,132,133,127,128,129]


imp = IJ.createImage("Temp", "8-bit black", 500, 500, 1)

imp.show()

imp.setRoi(PointRoi(xpoints, ypoints, len(xpoints)))
IJ.setForegroundColor(255, 255, 255)
IJ.run(imp, "Draw", "slice")
IJ.setAutoThreshold(imp, "Default dark")
IJ.run(imp, "Create Selection", "")
IJ.resetThreshold(imp)

newroi = imp.getRoi() # this is the roi containing all the points.
1 Like

Great! That nailed it. Thank you so much, Nicolas!

1 Like