How to save *automatically* into a XY.txt the coordinates of all the outlines in Analyze Particles?

Hi all, I have a large dataset of binary images. Each image represents a foam, so that I have white images with black bubbles inside. I need, for each image, to save all the coordinates of all the bubble outlines generated with Analyze Particles, i.e. the couples (x_i,y_i) of the points of the bubbles boundary (possibly preserving the indexing of ImageJ for each bubble). I know how to do it manually, but it is infeasible to do it in this way. How can I do it automatically?

Add the outlines to the roiManager and save them as zip file. The ‘.zip’ extension is essential. A snippet of code:

path = getDirectory("Choose a Directory");
run("Analyze Particles...", "size=50-700 pixel circularity=0.20-1.00 show=Nothing exclude clear include add");
roiManager("deselect"); 
roiManager("save", path+ "Particles.zip") ;//will be zip file containing all ROIs

Load the zip file, do roiManager(“select”,roiN); to activate a roi and perform getSelectionCoordinates(cx,cy) to access the coordinates of that ROI. run(“Interpolate”, “interval=1”); first if you need to obtain every pixel that is covered by the ROI.

1 Like

Good day Francesco,

here is an ImageJ demo-macro that does what you are looking for:

run("Blobs (25K)");
setBatchMode(true);
run("Invert LUT");
setAutoThreshold("Default dark");
setOption("BlackBackground", false);
run("Convert to Mask");
str = split(getTitle(), ".");
str = str[0]+"_roi-";
run("Analyze Particles...", "exclude add");
run("Clear Results");
n = roiManager("count");
for ( i=0; i<n; i++ ) { 
	roiManager("select", i);
	outline2results(str+(i+1));
}
setBatchMode(false);
exit();
function outline2results(lbl) {
	nR = nResults;
	Roi.getCoordinates(x, y);
	for (i=0; i<x.length; i++) {
		setResult("Label", i+nR, lbl);
		setResult("X", i+nR, x[i]);
		setResult("Y", i+nR, y[i]);
	}
}

Paste the above macro code to an empty macro window (Plugins >> New >> Macro) and run it.
(You need an open internet connection to load the demo image.)

Regards

Herbie

1 Like

Thank you for the reply. Following this snippet I get an error from the ROI manager: “The selection list is empty”. How can I solve it?

This is great! I can run it on Blobs (25K), but since I am not so proficient with macros, how can I modify it in order to use it on a particular set of images (e.g. contained in “/my/path/img_i.jpg”) and save the results in another directory (e.g. “/my/results/…”)?

Francesco,

before you do the opening of images from a directory and later saving the corresponding results—a mechanism that was explained on this forum again and again—you should make sure that your images are suited for the analysis by “Analyze Particles…”

If you have your binarized images stored in a directory you may omit the first lines of my macro code, i.e. start with

setBatchMode(true);
str = split(getTitle(), ".");
str = str[0]+"_roi-";
run("Clear Results");
n = roiManager("count");
for ( i=0; i<n; i++ ) { 
	roiManager("select", i);
	outline2results(str+(i+1));
}
setBatchMode(false);
exit();
//etc.

Please learn how to write ImageJ-macros which is really easy:
https://imagej.nih.gov/ij/developer/macro/macros.html
https://imagej.nih.gov/ij/developer/macro/functions.html

Regards

Herbie

1 Like

Thank you for the answer. I noticed I problem: the script works on all the images in a folder, and it collects correctly the coordinates of every bubble in the first image. The problem is that in all the remaining images, the boundary of a single bubble is divided into more labels (e.g., bubble 1 -> label 1-2-3, bubble 2 -> label 4-5-6-7 …). The csv produced is of the type:


,Label,X,Y
1,1-roi1,182,18
2,1-roi1,191,18


and the anomalous term is “1-roi1”. Why does it behaves like this? In the all the other particle analysis it behaves correctly.

Furthermore: it “divide” the label of a single particle/bubble boundary as the image index increases (the last image has 700+ bubbles boundary labels, while actually it has only 30-40 bubbles).

Good day Francesco,

without seeing the corresponding images we can’t help.

Furthermore, I have no idea what you are exactly doing and which code you are using.

Regards

Herbie

Problem found, solution not yet. I apply this function to all the images:

function action_coord(input,output,filename,index) {
    index = index + 1;
    open(input +"/"+filename);
    run("Invert LUT");
    setAutoThreshold("Default");
    str = split(getTitle(), ".");
    str = str[0]+"-roi";
    run("Analyze Particles...", "size=1-Infinity exclude add");
    run("Clear Results");
    n = roiManager("count");
    for ( i=0; i<n; i++ ) { 
    	roiManager("select", i);
    	outline2results(str+(i+1));
    }
    saveAs("Results", directory+index+".csv");
    run("Close");
} 

and I apply it to all the images with a for-loop:

for (i = 0; i < list.length; i++) {
   action_coord(input,outputCoord,d2s(i+1,0)+".jpg",i);
}

Where input is a directory, and outputCoord too. Basically it superimpose/include/consider all the bubbles outlines of the previous images. How can I say to ROI manager to discard them?

You may either close the ROI-Manager

close("ROI-Manager");

or delete its ROI-list

roiManager("deselect");
roiManager("delete");

or bracket the code by setBatchMode() again.

HTH

Herbie

1 Like

Thank you, now it works fine!

Dear Herbie,

I’ve implemented your snippet (thank you very much!) for my binary outlines. Am I right that whenever the outline is horizontal (vertical) fiji’s roi would skip pixels? Below is the figure of imported xy of one outline. You can see that there is a blank patch of 20 pixels. I am wondering how can I modify your macro to fill that patch.

Thank you.

untitled

After you have the outline active, perform this command in the macro:

run("Interpolate", "interval=1");
1 Like

That worked, thank you very much, @eljonco! You saved me hours of fitting a spine into the outline.