imagej / ImageJ

Public domain software for processing and analyzing scientific images
http://imagej.org
Other
542 stars 221 forks source link

trueEdmHeight #60

Closed ggirelli closed 6 years ago

ggirelli commented 6 years ago

Hello! I have been reading the MaximumFinder code for some inspiration, and found the trueEdmHeight function (I also report it below for convenience). I was wondering if someone could provide a bit of insight on the rationale behind it, especially these bits:

For simplicity, we don't care about the Sqrt(5) distance here although this would be more accurate
float trueH = v + 0.5f*SQRT2;           //true height can never by higher than this
if (v>=v1 && v>=v2) {
    ridgeOrMax = true;
    h = (v1 + v2)/2;
} else {
    h = Math.min(v1, v2);
}
h += (d%2==0) ? 1 : SQRT2;          //in diagonal directions, distance is sqrt2

Also, I do not understand why the value is changed if the point of interest is a ridge or max in any direction, but its value is replaced by the largest trueH, which might be from a direction where the point is not a ridge/max. Or maybe this scenario is actually not possible and I am missing the whole point?

Sorry for the naive question(s). I am particularly interested in understanding this as it looks like a great improvement when using float EDM (the number of local maxima is nicely reduced, at least in my study cases).

Well, many thanks in advance! Cheers :)


   /** Get estimated "true" height of a maximum or saddle point of a Euclidian Distance Map.
     * This is needed since the point sampled is not necessarily at the highest position.
     * For simplicity, we don't care about the Sqrt(5) distance here although this would be more accurate
     * @param x     x-position of the point
     * @param y     y-position of the point
     * @param ip    the EDM (FloatProcessor)
     * @return      estimated height
     */
    float trueEdmHeight(int x, int y, ImageProcessor ip) {
        int xmax = width - 1;
        int ymax = ip.getHeight() - 1;
        float[] pixels = (float[])ip.getPixels();
        int offset = x + y*width;
        float v =  pixels[offset];
        if (x==0 || y==0 || x==xmax || y==ymax || v==0) {
            return v;                               //don't recalculate for edge pixels or background
        } else {
            float trueH = v + 0.5f*SQRT2;           //true height can never by higher than this
            boolean ridgeOrMax = false;
            for (int d=0; d<4; d++) {               //for all directions halfway around:
                int d2 = (d+4)%8;                   //get the opposite direction and neighbors
                float v1 = pixels[offset+dirOffset[d]];
                float v2 = pixels[offset+dirOffset[d2]];
                float h;
                if (v>=v1 && v>=v2) {
                    ridgeOrMax = true;
                    h = (v1 + v2)/2;
                } else {
                    h = Math.min(v1, v2);
                }
                h += (d%2==0) ? 1 : SQRT2;          //in diagonal directions, distance is sqrt2
                if (trueH > h) trueH = h;
            }
            if (!ridgeOrMax) trueH = v;
            return trueH;
        }
    }
imagejan commented 6 years ago

@ggirelli this is a question rather than an issue report, I suggest that you post this to the Image.sc forum instead, where many more people will see it.

ggirelli commented 6 years ago

@imagejan thanks, I will definitely do that!