Help with batch processing surface area images

Hey everyone,
I am fairly new to imageJ. I am looking to get the area and standard deviation of hundreds of images. The images contain a 4.7 cm x 4.7 cm tile with a piece of coral attached to it. I am trying to look at the surface area of only the coral and would like to write a little macro to batch process them. I can place the tile on an all black or white (pictured) background to make things easier. It works pretty well to use the wand tool to trace the outline but im not sure if I can make it auto set the tolerance with reasonable accuracy for multiple images. Alternatively, I was thinking about converting to an 8 bit image, using threshold to define object vs background (might be difficult with the pink coralline algae on the tile. See example images). All images will be taken from a fixed tripod under the same lighting conditions. Any help would be greatly appreciated!!

P.S. I picked some of the most difficult images to analysis (they contain a lot of pink coralline algae that imagej often confuses with the coral). If I absolutely have to I will scrape away as much algae as I can to make the distinction more clear.


When you have a look at the histogram of your images, you see that you have 3 modes : the background, the tile and your coral. First thing is to select the tile. To do so, you can threshold the blue component, keep the largest object and make some large opening and hole fill to remove small artefacts. Inside the tile, a triangle threshold on blue component allows to retrieve coral (the biggest object). If you want to refine, you can compute the mean grey value of your objects in the red component (redirect in the Set Measurements…). They differ a lot from coral to coralline algae.


1 Like

Hey Nico,

Thank you so much for you response. It is definitely helping put me on the right track. I am very poor at Imagej so I am struggling with some of the specifics.
Please let me know if this is right
I am converting to RGB stacked (since i cant threshold non-greyscale images)
Threshold the blue component: I am using the threshold tool and playing with the sliders until as much of the background is green and none of the tile is blue (meaning it will be filtered out right?) Is this what you mean by keep the largest object?
I get confused after this because it converts it to a greyscale image that makes the coralline algae indistinguishable from the coral. Sorry I am quite bad at this but I really appreciate the help!

Hi Colin,

instead of RGB stacked, prefer split components.
When you use a threshold, you split the image in two components : the objects of interest (generally in white 255) and the remaining part (generally in black 0). You have a binary image, so it’s normal that you can’t distinguish the coral anymore. this binary image can be used as a mask on the original image to select your object of interest.
You can use the thresholding sliders to perform a manual thresholding. If you find a hard threshold that is ok for every image, it’s ok. But if you have to manually adapt the threshold to every image, you MUST NOT (:)) use it, because you introduce a bias (the choosen threshold will depend on your mood of the day, on your tired…). If your threshold moves, you have to use an automatic adaptative threshold (there is a full list in imageJ).
The macro below should answer some of your questions.

nameImg = "P7230105.JPG";
run("Split Channels"); //you separate the channels
selectImage(nameImg + " (green)"); close();
selectImage(nameImg + " (blue)");
// first you have to select the tile
run("Duplicate...", "title=tile");
setAutoThreshold("Triangle"); //this is done wih an automatic threshold ; the Triangle
setOption("BlackBackground", true);
run("Convert to Mask");
//you remove small artifacts
run("Analyze Particles...", "size=0-10000 exclude clear add");
setForegroundColor(0, 0, 0);
// you fill holes inside the tile and then perform a big opening to remove artifacts linked to the tile
run("Fill Holes");
run("Options...", "iterations=30 count=1 black do=Nothing");
// then you select the only object remaining. if there are severall objects, you have to select the biggest
run("Analyze Particles...", "size=10000 exclude clear add");
roiManager("Select", 0);
// and you apply this selection to the blue componenent
selectImage(nameImg + " (blue)");
run("Restore Selection");
//and segment automaticaly the coral
run("Convert to Mask");
//and remove small artifacts
run("Analyze Particles...", "size=0-5000 exclude clear add");
selectImage("tile"); close();
// the biggest object remaining should be your coral

if you fell that the biggest object is not ok, you may use the mean red value of each objet.

run("Set Measurements...", "area mean redirect=[" + nameImg + " (red)] decimal=2");
run("Analyze Particles...", "size=[] display exclude clear add");

for example on image P7230105, you see that the mean grey value of coral (~75) is very different from algae (~115), so this may help to automatically discriminate them.


1 Like

Hey Nico,

Thank you so much for you help! This clarified so much! I have a few more questions now. When I set the scale (4.7cm is the length of the tile), it often messes up the macro. How can I set the scale so I get the area in cm^2. Every image will be taken from the same distance and zoom so that each image is the exact same resolution. Therefore, the same distance will be the same number of pixels in each image? and I can apply the scale once and it will work for all my image? Also, the brown algae in the second picture is so similar to the coral that it is counting it as the same. Is there anyway to differentiate these or is it easy to just remove the algae?



Or even easier… Since I know the resolution of the image and the pixel/cm^2, could I just convert the area in pixels to cm^2 after the macro gives me area in pixels? Do you know how this would affect the standard deviation? Lastly, how would I set this up so I can use this macro to batch process images? The first part of the code specifies the Imgname so I need to change the name for each image I give it.

Hi Colin.
You can set the scale in Image>Properties. You have to do it for every image (except if you check global option, but be careful if you analyse other images later) but you can do thios inside the macro. For example :

run("Properties...", "channels=1 slices=1 frames=1 unit=cm pixel_width=1.2300 pixel_height=1.7800 voxel_depth=1.0000");

The resulting measurements will be calibrated automatically. If you want to run the Analyse Particle… with still the pixel unit, you have to check the option box. (this will add a pixel option if you record the code).

run("Analyze Particles...", "size=0-5000 pixel exclude clear add");

I think that for the second image, you should mannually remove the algae, it looks (spectrally speaking) really like coral.

To automate, to get image name, you can use

nameImg = getTitle();

to process every image in a directory, you can write some code or, in Process>Batch>Macro… you can paste my few lines (replacing the first one with nameImg = getTitle()) and select an input and output directory.
It will process every image in the input directory and save it in the output directory. You won’t have to bother with getFileList.


Hey Nico,

I am running into a few issues that I have been racking my brain trying to solve. Even if I set the scale manually (line tool -> select the length of the tile -> set scale known distance 4.7 cm) and run the macro I am still getting my area in pixels. I tried playing around with

run(“Properties…”, “channels=1 slices=1 frames=1 unit=cm pixel_width=1.2300 pixel_height=1.7800 voxel_depth=1.0000”);

I changed the width and height to that of all my images (4608x3456) but I still get the area in pixels instead of cm.

The second issue is that when I try to run this macro on more than one image the second image has the error “Redirect image (FileName.jpg (red)) not found. The red image was clearly generated so I tried to include a selectImage(nameImg + " (red)”); but still no luck.

Last, when I try to batch process all of the images I orginally posted it can’t make it through the first one. Error: Particle analyzer: “A thresholded image or 8-bit binary image is required. threshold levels can be set using the Image->Adjust-> Threshold tool.”

Thank you so much for your help



it is pixel width and not the width of your image.

is because somewhere in your macro, you do a Set Measurements… where you ask to make some measurements on the red component. But you didn’t reset this. So at the next analysis of particles, it tries to find the red component that doesn’t exist and so it fails.

Your last error is because it tries to analyse a grey level image.
Are you sure you thresholded it ? Or are you sure you are analysing the good image ? Maybe a selectImage(“nfknfkdf”); just before the Analyse Particles would solve it ?