Save "ordered" outlines from stack

I have a stack of images with one irregularly shaped particle per frame. I have already segmented and binarized each frame and I am interested in saving the outline from each frame as x,y coordinates (hopefully in an automated way) for plotting and analysis elsewhere.

I’ve attempted a few times to construct a macro that will save the outlines (either from wand selection or the binary --> outline command) as XY coordinates, but from what I can find, it seems that, unlike “File --> Save As… --> XY coordinates”, the command available in the macro language collects the outline in a rastering-like way. As such, “connecting the dots” outside ImageJ/FIJI would require manual correction of each frame’s outline. In other words, the available command works like “Analyze --> Tools --> Save XY coordinates.”

Is there any existing plugin or command that can save the XY coordinates as a true “ordered” outline? Or any way to construct a macro to perform such a task?

save the XY coordinates as a true “ordered” outline?

What exactly do you mean by this?

XY-coordinates are necessarily pairs of numbers and as such they are always discrete, like what you get from the mentioned ImageJ-menu commands or their macro counterparts.

So what is it that you’re after. Do you think of spline curves?

Regards

Herbie

By “ordered,” I just hope to save the coordinates in one “direction” around the shape (i.e. like clockwise or counterclockwise), rather than saving the coordinates in an order that scans down it (i.e. sorted by y). I don’t mean some sort of vector or fitted curve.

If I save the coordinates in the “File–> Save As… --> XY coordinates” manner, I get what I hope for, which is a single-direction outline and if I “connect the dots” in that order it reproduces the outline. However, the XY coordinate save that I can find in the macro language saves them in an order that scans down the outline, so if I connect the dots in that order it makes a “zig-zag.” In principle I suppose I can get to the “real” outline from that zig-zag order, but I imagine it would take more manual effort than saving all the “single direction” coordinates from each frame without a script.

I believe that what you are after is called the Freeman’s “chain code” i.e. it stores the outline as if one were walking along the coastline, starting from the XStart, YStart pixel and visiting all the consecutive boundary pixels. See:

Herbert Freeman, “Computer Processing of Line-Drawing Images,” ACM Computing Surveys, vol. 6, no. 1, pp. 57–97, 1974

Please explain what you want to do. I wrote an encoder/decoder long time ago, but it does not output the coordinates (it generates the chain code).

Hi @jwsmith,

If I understood correctly, you a trying to get the (x,y) pairs of the perimeter of a ROI in an ordered fashion.

but […] the command available in the macro language collects the outline in a rastering-like way.

I’m unsure of the command you are referring to, but the one that you should be using is getSelectionCoordinates(xpoints, ypoints), as in the following example:

// ROI should be already selected
getSelectionCoordinates(xpoints, ypoints); //gets the coordinates as two arrays

//example code to list the coordinates in a way similar 
//to the output of File > Save As...> XY coordinates
print("\\Clear");
for (i=0; i<xpoints.length; i++){
	print(xpoints[i], ypoints[i]);
	}

Cheers!
Nico

Good day,

and thanks for detailing the problem.

Here is an approach that works for me:

First safe the selection in question (please use a demo image of size 256x256) by using:

saveAs("XY Coordinates", "yourPathToTextFile.txt");

Then try this demo macro to create a new image canvas of size 256x256 and draw the outline according to the saved coordinates:

str=File.openAsString("");
rows=split(str,"\n");
n=rows.length;
setForegroundColor(255, 255, 255);
newImage("Outline", "8-bit black", 256, 256, 1);
for ( i=1; i<n; i++ ) { 
   cS=split(rows[i-1],"\t");
   cE=split(rows[i],"\t");
   drawLine(cS[0], cS[1], cE[0], cE[1]);
}

HTH

Herbie

saveAs WY Coordinates, however does a run-length encoding of the boundary coordinates. That is, for any sized rectangle it will output the coordinates of the 4 corners, similarly for more irregular shaped regions, the corners of the boundary polygon.
The chain code, strictly encodes one pixel advancing at a time, so they are not exactly the same thing (a large rectangle has more links in the chain than a small one). That is why I asked what the OP wanted to do.

Good day Gabriel,

my impression from what the OP explained more recently is that he was unhappy with the order of the xy-coordinates that some ImageJ operations produce—but I may be wrong.

saveAs("XY Coordinates", "yourPathToTextFile.txt");

should work in this case but as you mention, it doesn’t provide a chain-code.

BTW, did you ever meet Freeman?
He was a very nice person and I remember him well. I visited him in 1984.

Best

Herbie

Hi Herbie,
No never had the pleasure to meet him. A large number of these algorithms were developed very early, way before computers became a “common” thing.