Macro: lay outlines of particle analyses over original image

Hello, I would like to automatize the determination of the particle size (via Analyze Particles) using a macro. So far I’ve managed to put together the following:

dir = getDirectory("image");
name = getTitle; 

setOption("BlackBackground", false);
run("Make Binary");
run("Watershed");
run("Analyze Particles...", "size=2-Infinity show=[Bare Outlines] display exclude clear in_situ");
saveAs("Measurements", dir+name+".csv");
saveAs("Tiff", dir+name+"_2");

I would like the makro to export a TIF-image with the bare outlines of the analysis laid over the original image (not as my macro currently does, over the edited - binary and watershed - image).

And another question I have: dir+name+".csv" results in name.tif.csv. How could I remove the file extensions from the original images in the file names of my csv-files?

Ok, I got a bit closer to the solution, but still didn’t figure it out completely. What I now have is:

    dir = getDirectory("image");
    name = getTitle; 

    setOption("BlackBackground", false);
    run("Make Binary");
    run("Watershed");

    run("Analyze Particles...", "  show=Nothing exclude clear add");
    roiManager("Show All without labels");
    run("Flatten");

    saveAs("Measurements", dir+name+".csv");
    saveAs("Tiff", dir+name+"_2");

The problem with this code is, that the ROI will be laid over the edited (i.e. binary and watershed) image instead of the original one.

Any suggestion is appreciated!

Dear @MojoDodo,

you can make Analyze Particles output an Overlay on your binary image by

run("Analyze Particles...", "show=Overlay exclude clear");

that you can copy and paste onto your original image:

Overlay.copy
Copies the overlay on the current image to the overlay clipboard.
Overlay.paste
Copies the overlay on the overlay clipboard to the current image.

Source: https://imagej.nih.gov/ij/developer/macro/functions.html

Best,
Stefan

1 Like

Hi Stefan,
thanks for your reply.

Well, the solution that I came up with is, making a copy of the original image prior to editing and analysing on, which I overlay the ROI with the “flatten”-option:

dir = getDirectory("image");
name = getTitle;
mainTitle=getTitle();
run("Duplicate...", "title=originalimage");

selectWindow(mainTitle);
setOption("BlackBackground", false);
run("Make Binary");
run("Watershed");
run("Analyze Particles...", "  show=Nothing exclude clear add");

selectWindow("originalimage");
roiManager("Show All without labels");
run("Flatten");

saveAs("Measurements", dir+name+".csv");
saveAs("Tiff", dir+name+"_2");

How would you do that with your solution? My problem was that I didn’t have an original image any more, but only the binary watershed image. Would you also make a duplicate (like I did above) and paste the overlay on that? Is there any advantage compared to my option to use “flatten”?

That would be the way to go.

You are basically doing the same thing. The copy & paste is 1) a little more robust with respect to undesired ROIs in the RoiManager and 2) you can save an overlay to a TIFF to restore it later. If your macro does what you set out to do: goal achieved :wink:

Best,
Stefan

Not quite yet…
In my tests I was using TIFF files, but now have to apply the macro to files that have three channels (more precisely .ids files that I successfully managed to open in the macro with the help of @imagejan).

The macro code I’m using is:

input = "/home/user/inputfolder/";
output = "/home/user/outputfolder/";

function action(input, output, filename) {

//for opening TIFF files
//open(input + filename);

//for opening .ids files
run("Bio-Formats Importer", "open=["+ input + filename +"] autoscale color_mode=Custom view=Hyperstack stack_order=XYCZT series_0_channel_0_red=0 series_0_channel_0_green=255 series_0_channel_0_blue=0 series_0_channel_1_red=255 series_0_channel_1_green=0 series_0_channel_1_blue=0 series_0_channel_2_red=0 series_0_channel_2_green=0 series_0_channel_2_blue=255");

run("Arrange Channels...", "new=2");

savename=getTitle();
mainTitle=getTitle();
run("Duplicate...", "title=originalimage");

selectWindow(mainTitle);
setOption("BlackBackground", false);
run("Make Binary");
run("Watershed");
run("Analyze Particles...", "  show=Nothing exclude clear add");

selectWindow("originalimage");
roiManager("Show All without labels");
run("Flatten");

saveAs("Tiff", output + savename + "_ROI");
saveAs("Measurements", output + savename + ".csv");

run("Close");

close();
}

setBatchMode(true); 
list = getFileList(input);
for (i = 0; i < list.length; i++)
action(input, output, list[i]);
setBatchMode(false);

So problem comes up at the point where the macro made the duplicate and selects the originally opened image again to perform the analysis on it. What then happens is that the “Convert Stack to Binary”-window shows up (this happens when convert an image with 3 channels to binary). To my understanding this shouldn’t happen, because with
run("Arrange Channels...", "new=2");
I will not have a stack, but rather a single image. It seems as if
selectWindow(mainTitle);
somehow doesn’t load the image with only one channel. If I remove this line the macro runs without asking for anything (but obviously will lay my ROI over the edited binary image instead of the duplicate)

Do your images have other dimensions in addition to channels, e.g. time or z?

No, as far as I know, only 3 channels with images.
The strange thing is that when I manually open the .ids image and reduce the number of channels to one channel (by Image → Color → Arrange Channels) and then convert the image (i.e. the one channel that is left) to binary (by Process → Binary → Process Binary) it works without ImageJ showing the “Convert Stack to Binary”-window. I have the same behaviour with the macro if I don’t use the selectWindow(mainTitle)
It seems as if changing the window after making the duplicate, somehow changes to the originally opened image with 3 channels instead of the image with only 1 channel left (although I run mainTitle=getTitle() after run(“Arrange Channels…”, “new=2”) )

Could you try to use imageId = getImageID(); and selectImage(imageId); instead of using names/titles? Image titles are not necessarily unique, whereas image IDs are.

Thank you for the hint, but unfortunately the same problem occurs.

I have spent some time on debugging: your issue is actually related to the batch mode. You can confirm that by running you macro on a folder with just one file and removing the calls to setBatchMode(). As far as I can tell, the macro does what it is supposed to do.

The issue is in Thresholder.java#L41. The ImagePlus that is returned by IJ.getImage() differs between batch mode and interactive mode. Here is an MVCE to reproduce the issue:

setBatchMode(true);
run("Fluorescent Cells (400K)");
run("Arrange Channels...", "new=2");
croppedImageID = getImageID();

run("Duplicate...", "title=original");

selectImage(croppedImageID);
run("Make Binary"); // Asks how to handle the stack in batch mode 
                    // although a single image should be selected
setBatchMode(false);

Could you take a look at this @Wayne?

Best,
Stefan

1 Like

Thanks to Stefan’s very helpful MVCE [1], the latest ImageJ daily build (1.51m4) fixes a bug that caused the Arrange Channels command to fail to close the source image in batch mode macros.

[1] http://stackoverflow.com/help/mcve

2 Likes

Thanks for fixing the issue, @Wayne! Works like a charm now :slight_smile:

If you update to the latest daily build of ImageJ (Help > Update ImageJ… and select daily build in the Upgrade To dropdown), your macro should work as expected, @MojoDodo!

Best,
Stefan

Thank you for all the help!

Now, it works like expected with selectWindow(mainTitle); as well as selectImage(imageId);.
Would you generally recommend to use the latter?

IDs are supposed to be (and in general are) unique while you can have two images with the same name. I am not entirely sure how ImageJ handles that case, so I guess it’s best to avoid it.