Watershed: making unwanted splits

Dear all,

I am currently analyzing images from potato tubers, to obtain dimentions of those tubers. As some tubers are touching in the pictures I need to watershed the image as to split them. However there are some tubers that are roughly shaped like a figure 8, although indentations in the middle are fairly small, which are splitted into two tubers. Would there be any way to differentiate between these and tubers touching. Perhaps some sort of threshold as to how deep an indentation needs to be before it is split?

Any tips or tricks are welcome, as I’m just a beginner.

Luuk

Edit: Here is an example of what happends. I changed the image to 8 bit, and set an appropriate threshold. Then I used Erode and Dilate, from the BioVoxxel Toolbox, as to remove some background noise. After that I used watershed, which seperated several potatoes that were touching. However the one in this picture is also splitted, about were I drew the red line. As you can clearly see this is a single tuber, and therefore I would prefer if it doesn’t get split.

Hi @Luuklag

Since you are running the toolbox already, you can actually give the watershed irregular features a try. In its newest version it allows 3 different parameters to tweak the standard watershed towards fewer separations.

1 Like

Hi @biovoxxel, Thanks for the tip. I will definetly have a look. I am also trying some things with KNIME now, would be great to see your plug-in being integrated there as well :wink:

Setting the seperator size to 0 - 50 worked for me. However I tested only on 1 image. More will follow in the future.

@biovoxxel; why is there a erode cycle in your version. I already performed erode and dilate cycles before to get rid of back ground noize. And to what percentage does this erode cycle influence my final results in terms of area measurements?

On the Toolbox page you can find some explanations on how the algorithm works.

Potentially, the following scheme explains best how it works:

3 Likes

@Luuklag There is also the possibility to perform the watershed on an 8-bit grayscale image (instead of binary) if you want, but it doesn’t appear to be available through the ImageJ UI. I do this regularly for my segmentation, it has worked better for me than watershed on binary but I had to utilize existing ImageJ code in my own Java code to do so, so it may be beyond what you are willing to do but thought I would throw it out there as an option.

The relevant class in ImageJ is MaximaFinder.

Here is how I would have used it on your images…

I blur the image of the tubers so that there is a “maxima” in each tuber. I call the MaximaFinder.findMaxima(…) method on the blurred image. This essentially sets the “seed” points for the watershed algorithm within the MaximaFinder object I have instantiated. However, now that the seed pionts are set, you can apply the watershed algorithm to the original tuber image (I find a slightly blurred version to produce smoother segments). The code thankfullly does clever things to avoid segmenting local maxima and minima besides the seed points. The watershed algorithm called this way is guaranteed to produce only one segmented region per maxima. Thus, if there is a 1-to-1 mapping between tubers and maxima, your segmented regions will have a 1-to-1 mapping as well. Blurring just prior to watershedding can cause a little inaccuracy at boundaries (i.e., your tuber boundary might overlap an adjacent tuber a tiny bit but won’t cut directly through your tuber as you have shown.) Here is the code for applying it to a grayscale image. (“this” refers to the MaximaFinder class that I copied into my own code. This code was added to that class.)

    public ByteProcessor segmentImageUsingMaxima(ImageProcessor ip, boolean excludeOnEdges)
    {
        ImageStatistics stats = ImageStatistics.getStatistics(ip, ImageStatistics.MIN_MAX, null);
        ByteProcessor outIp = this.make8bit(ip, this.savedTypeP, false, (long) stats.min, (long) stats.max, 0);
        // if (IJ.debugMode) new ImagePlus("pixel types precleanup",
        // typeP.duplicate()).show();
        this.cleanupMaxima(outIp, this.savedTypeP, this.savedMaxPoints); // eliminate all the small maxima (i.e. those outside MAX_AREA)
        // if (IJ.debugMode) new ImagePlus("pixel types postcleanup",
        // typeP).show();
        // (new ImagePlus("pre-watershed", outIp.duplicate())).show();
        if(!this.watershedSegment(outIp))
        {
            return null; // if user-cancelled, return
        }
        // (new ImagePlus("watershed segment", outIp)).show();
        // if(!isEDM) // Assume ip is not an EDM
        // {
        this.cleanupExtraLines(outIp); // eliminate lines due to local
        // minima
        // }
        // (none in EDM)
        this.watershedPostProcess(outIp); // levels to binary image
        if(excludeOnEdges)
        {
            this.deleteEdgeParticles(outIp, this.savedTypeP);
        }
        
        return outIp;
    }

The watershed algorithm applied to a binary image essentially turns your binary image into grayscale image of distances from boundaries. Here I’m using the intensity as the “distance” metric from the boundary. The particular location of the calculated boundaries using the approach above will be rather “wild” in the large regions between tubers, but that really doesn’t matter, you only care where the boundary is when you get close to the tuber, where the intensity is a good metric of distance and the boundary becomes more predictable. So taking images of your light colored tubers on a dark background would be important. Also, technically this code produces a segmented image. You would have to overlay the segmented lines on your thresholded image of your tubers to come up with a final product.

2 Likes

You might also want to use the Morphological Segmentation plugin: http://fiji.sc/Morphological_Segmentation

It combines watershed with extended minima to avoid the over-segmentation.

2 Likes

Thanks! Looks useful.