Hi Gabriel,
concerning the bug of doWand at the upper image edge, using the XStart,
YStart:
This problem only occurs in "Legacy mode". It disappears in 8-connected
mode:
doWand(x,y, /*tolerance=*/0, "8-connected");
The problem also disappears if the foreground is thresholded. It is
related to the statement (Wand.java, line 145)
if (legacyMode)
fourConnected = !thresholdMode && !(isLine(x, y));
Where isLine is some heuristics to determine whether there is a blob or
a line. Many years ago, when implementing the tolerance and the 4- and
8-connected mode, since I did not understand the rationale behind it and
I did not want to break anything, I had tried to keep the previous
behavior unchanged. Either I had done this incorrectly or it is a bug
that dates back to the very early days of ImageJ.
Maybe Wayne knows why the wand was switching to 4-connected mode when it
was not a line (and not thresholded mode) in the very old days. It could
be that those days the ParticleAnalyzer was requiring a thresholded
image and did not work with an unthresholded binary image; I do not
remember.
Concerning the performance:
The thing that makes the Wand version so slow is not the wand operation
but the "Clear". There are about 300000 ROIs. Most operations in ImageJ
are optimized for processing large areas and sometimes inefficient for
small ROIs. In your example, the average ROI size is only about 2.5 pixels.
For each "Clear" operation, a LUT is created (in ImageProcessor.process)
and also a mask is created for the ROI, using an algorithm for generic
polygons (not taking into account that it is a traced ROI with only
horizontal and vertical boundaries). Each mask is an ImageProcessor on
its own. So there is quite some overhead.
What I do not understand: The processing time increases in a very
nonlinear way with image size. The number of ROIs is roughly
proportional to image size, and ROIs are very small, so also the masks
are small.
256x256 0.6 s
512x512 2.2 s
1024x1024 11 s (expected about 4x longer, thus ok)
2048x2048 170 s (expected 4x, actually 16x longer)
2048x4096 700 s (expected 2x, actually 4x longer)
There might be some nonlinearity if the largest image does not fit into
the CPU cache, but the ROIs are sorted in y, so only the y region
currently processed needs to be in memory.
Michael
_________________________________________________________________
On 22/03/2024 12:54, Gabriel Landini wrote:
Hello,
Using the doWand to remove binary regions is quite slow compared to the
floodfill method (floodfill is approx 74 times faster in normal macro
mode and approx 260 faster (!) in batch mode in the example below).
But more importantly, I just noted that the doWand method fails to
remove all regions from the image.
Running the macro below you find many remaining regions close the the
top and right borders on the result image 1.
I suspect that the wand is missing some 8-connected pixels that form
part of the boundary of regions touching at the image borders.
- - - - -
newImage("Untitled", "8-bit black", 2048, 2048, 1);
run("Add Noise");
setThreshold(0, 5);
setOption("BlackBackground", true);
run("Convert to Mask");
run("Duplicate...", "title=1");
run("Analyze Particles...", "minimum=1 maximum=999999 bins=20
show=Nothing clear record");
selectImage("1");
t0=getTime();
for (i=0; i<nResults; i++) {
x = getResult('XStart', i);
y = getResult('YStart', i);
doWand(x,y);
run("Clear");
}
print ("Wand: "+getTime()-t0+" ms.");
selectImage("Untitled");
run("Duplicate...", "title=2");
setColor(0);
selectImage("2");
t0=getTime();
for (i=0; i<nResults; i++) {
x = getResult('XStart', i);
y = getResult('YStart', i);
floodFill(x, y, "8-connected");
}
print ("Floodfill: "+getTime()-t0+" ms.");
- - - - -
Regards
Gabriel
On 22/03/2024 00:43, Wayne Rasband wrote:
The “Record starts” checkbox has been replaced by “Overlay” but macros
that use the ‘record’ keyword continue to work.
Here is an updated version of the CircularParticles macro linked to in
the ImageJ User Guide that uses ‘overlay’ instead of ‘record’:
// This macro demonstrates how to erase non-circular objects
run("Blobs (25K)");
setThreshold(125, 248);
run("Set Measurements...", "area perimeter circularity decimal=3");
run("Analyze Particles...", "clear overlay");
for (i=0; i<nResults; i++) {
circularity = getResult('Circ.', i);
if (circularity<0.85) {
Overlay.activateSelection(i);
run("Clear");
}
}
run("Select None");
exit;
// Original version that uses "Record starts"
run("Select None");
requires("1.29n");
run("Blobs (25K)");
setThreshold(125, 248);
run("Set Measurements...", "area perimeter circularity decimal=3");
run("Analyze Particles...", "minimum=1 maximum=999999 bins=20
show=Nothing clear record");
for (i=0; i<nResults; i++) {
x = getResult('XStart', i);
y = getResult('YStart', i);
circularity = getResult('Circ.', i);
if (circularity<0.85) {
doWand(x,y);
run("Clear");
}
}
run("Select None");
--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html
--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html
--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html