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

Reply via email to