Make Binary Foreground/Background Issues

I’m having an issue with a macro I recently wrote and am hoping someone can help. It is a relatively simple macro for detecting the size of a large object based on edge detection, thresholding, and binarization. I got the macro working, but after an update to a newer version of FIJI, the macro no longer works.

The macro was developed and works in FIJI 2.0.0-rc-68/1.52h. One of my users recently updated to FIJI 2.0.0-rc-69/1.52p. The Java versions are the same. I skimmed through the ImageJ release notes and did find a line that may be related:

1.52k 29 January 2019
◦ Thanks to Herbie, fixed a bug that caused the Process>Binary>Make Binary command to incorrectly set the threshold of 8-bit binary images.

This makes me wonder if there was some kind of bug in the 1.52h version I developed my macro in that was corrected in 1.52k, causing the macro to no longer work as it did when originally developed. Alternatively, there may be some default that changed that I am not explicitly calling out in the macro. I imagine I could make it work in the new version, but more importantly, I’d like to understand best practices for this kind of work to make sure that I am making more robust macros in the future that are less likely to break on version changes.

My code and a sample image are below. In 1.52h, this code identifies the area of the large object in the middle of the image. The same code in 1.52p gets the foreground and background reversed so that the erosions, dilations, and fill holes operate oppositely from intended. I tried adding the setThreshold option as mentioned in some posts I found in he forums, but that doesn’t seem to help. I tried changing the BlackBackground option to True, but that not only didn’t help, it seems to cause a difference between binary commands executed from the command editor or from the program menus (for example erosion and dilation has opposite effects depending on where you execute them from).

Adding to the confusion, I notice that the LUT gets inverted in the 1.52h version, but not in the 1.52p version. Again, it doesn’t matter to me what the color is, as long as the foreground/background is identified properly for the binary morphology operations.

Any suggestions would be greatly appreciated.

run("Duplicate...", "title=Thresh");	//create a copy of the image titled "Thresh"
run("8-bit");	//convert to 8-bit grayscale
run("Gray Morphology", "radius=2 type=circle operator=erode");	//gray morphology to smooth dark edgees
run("Find Edges");		//essentially the derivative of pixel intensty vs position - highlights contrast
run("Gray Morphology", "radius=4 type=circle operator=dilate");  // smooth edges to fill in minor gaps
run("Auto Threshold", "method=Li white");
setOption("BlackBackground", false);	//binary conversion setting
//setThreshold(127, 255);
run("Make Binary");		//convert to binary image
run("Options...", "iterations=5 count=1 pad do=Dilate");		//Dilate to fill gaps in edge
run("Fill Holes");	//Fill center of defined perimeter
run("Options...", "iterations=5 count=1 pad do=Erode");			//Erode to undo previous dilation
run("Erode");	//Erode to undo enlarging effect of find edges
run("Open");	//Erode/Dilate to remove remaining small defects (dots) and smooth edges

Hello Tim -

I am running 1.52t.

I can’t comment on what might have changed from 1.52h to
1.52p (to 1.52t), nor on best macro programming practices
(especially concerning relying on and/or running commands
that change option settings that are normally remembered
even after shutting down and relaunching Fiji / ImageJ).

The culprit seems to be these lines:

run("Options...", "iterations=5 count=1 pad do=Dilate");
...
run("Options...", "iterations=5 count=1 pad do=Erode");

If they don’t contain an explicit “black” option, they appear
(at least in 1.52t) to turn off the “Black background” setting
in Process > Binary > Options....

When I change them to:

run("Options...", "iterations=5 count=1 black pad do=Dilate");
...
run("Options...", "iterations=5 count=1 black pad do=Erode");

your macro seems to run correctly.

Here is my complete version of your macro:

run("Duplicate...", "title=Thresh");	//create a copy of the image titled "Thresh"
run("8-bit");	//convert to 8-bit grayscale
run("Gray Morphology", "radius=2 type=circle operator=erode");	//gray morphology to smooth dark edgees
run("Find Edges");		//essentially the derivative of pixel intensty vs position - highlights contrast
run("Gray Morphology", "radius=4 type=circle operator=dilate");  // smooth edges to fill in minor gaps
run("Auto Threshold", "method=Li white");
run("Make Binary");		//convert to binary image
run("Options...", "iterations=5 count=1 black pad do=Dilate");		//Dilate to fill gaps in edge
run("Fill Holes");	//Fill center of defined perimeter
run("Options...", "iterations=5 count=1 black pad do=Erode");			//Erode to undo previous dilation
run("Erode");	//Erode to undo enlarging effect of find edges
run("Open");	//Erode/Dilate to remove remaining small defects (dots) and smooth edges

Here is the result of running it on your image:

Thresh

Thanks, mm

2 Likes

Excellent find, mountain_man. It hadn’t occurred to me that run Options would have it’s own default if not set. I’ll give this a try when back on my work computer tomorrow to see if it works in both versions.

I’m still curious if anyone has thoughts on what might have changed between versions.

Thanks,
Tim

Maybe the default seetings in
Process > Binary > Options...
have been changed during the update.

I was able to play with today and managed to get it working properly in both versions. Mountain_man hit on the crux of it. Apparently when I used the Record Macro, I did some of my binary morphology operations directly from the Binary Options window using the “Do” dropdown because I thought this was the only way to multiple operations at once. I now see that the iterations option is maintained as a setting and I was unnecessarily changing all my binary options on the two lines that call Run Options. This also explains the odd behavior I saw regarding these lines operating differently than running them through the menu dropdowns (since I was comparing the code running them from the options menu with the menu running the morphology directly). While something clearly changed between the two versions to impact the way the macro runs, I now see that I wasn’t using these commands appropriately. Once I recognized the persistence of the commands in the Run Options command, I decoupled it from the binary operations, which simplified my code and made it work correctly in both versions of Fiji.

Thanks very much to mountain_man and phaub for the input. I’m going to mark as solved for now, but still open to other thoughts suggestions if anyone has any. Here is my final code:

run("Duplicate...", "title=Thresh");	//create a copy of the image titled "Thresh"
run("8-bit");	//convert to 8-bit grayscale
run("Gray Morphology", "radius=2 type=circle operator=erode");	//gray morphology to smooth dark edgees
run("Find Edges");		//essentially the derivative of pixel intensty vs position - highlights contrast
run("Gray Morphology", "radius=4 type=circle operator=dilate");  // smooth edges to fill in minor gaps
run("Auto Threshold", "method=Li white");
run("Options...", "iterations=5 count=1 black pad do=Nothing");  // binary settings
run("Make Binary");		//convert to binary image
run("Dilate");		//Dilate to fill gaps in edge
run("Fill Holes");	//Fill center of defined perimeter
run("Erode");			//Erode to undo previous dilation
run("Erode");	//Erode to undo enlarging effect of find edges
run("Open");	//Erode/Dilate to remove remaining small defects (dots) and smooth edges

Hi
@PolymerTim

I’m going to mark as solved for now, but still open to other thoughts suggestions if anyone has any.

I allow myself to deposit this code which can be used for others:

macro "Make Binary Foreground/Background "
{
requires("1.52t");
setBackgroundColor(0,0,0);
setOption("BlackBackground",true);
img=getImageID();
// Start batch mode
setBatchMode(true);
selectImage(img);
run("Duplicate...", "title=1");
close("\\Others");
run("Duplicate...", "title=2");
run("Find Edges");
setAutoThreshold("Triangle dark");
//run("Threshold...");
//setThreshold(25, 255);
run("Convert to Mask");
run("Fill Holes");
run("Set Measurements...", "area add redirect=None decimal=2");
run("Analyze Particles...", "size=200-Infinity circularity=0.00-1 display exclude include add");
roiManager("Show All without labels");
n=roiManager("Count");
a=Array.getSequence(n);
roiManager("Select",a);
roiManager("Combine");
wait(1000);
roiManager("Add");
roiManager("Delete");
roiManager("Select", 0);
selectImage("1");
run("Restore Selection");
roiManager("Set Color", "red");
roiManager("Set Line Width", 2);
// End of batch mode
setBatchMode(false);
exit("All is done !");
}

Greetings