I like to reproduce this accepted answer from stackexchange in MMA. While I would like to achieve a better segmentation than what I already got, at the moment my main problem is that the background is segmented too. In the question it is asked how to define markers for Watershed in OpenCV. There is an image of white balls which hopefully we can segment. I did not understand the Python code, however, I tried to reproduce it from the explanation.
From the answer:
As an example, first binarize the input image by Otsu and perform a morphological opening for removing small objects. The result of this step is shown below in the left image. Now with the binary image consider applying the distance transform to it, result at right.
This is what I did:
image = Import["https://i.stack.imgur.com/7EU8I.jpg"];
img = ColorConvert[image, "Grayscale"]
img3 = DeleteSmallComponents[Binarize[img, 0.4], Method -> "Mean"]
img4 = DistanceTransform@img3;
ImageAdjust[img4]
The result of the above code that is the binary image is on the left below and its distance transform on the right:
From the answer:
With the distance transform result, we can consider some threshold such that we consider only the regions most distant to the background (left image below). Doing this, we can obtain a marker for each object by labeling the different regions after the earlier threshold. Now, we can also consider the border of a dilated version of the left image above to compose our marker. The complete marker is shown below at right (some markers are too dark to be seen, but each white region in the left image is represented at the right image).
This is what I did:
img5 = Binarize[img4, 6]
edge = EdgeDetect[Dilation[img3, DiskMatrix[5]]]
marker = Plus[ImageMultiply[img5, img], edge]
From the answer:
This marker we have here makes a lot of sense. Each colored water == one marker will start to fill the region, and the watershed transformation will construct dams to impede that the different "colors" merge. If we do the transform, we get the image at left. Considering only the dams by composing them with the original image, we get the result at right.
![]()
This is what I did:
(* Rather than performing the Watershed on the image `img`, I did it on its gradient*)
g = FillingTransform[GradientFilter[img, 1], 0.1, Padding -> 1];
WatershedComponents[g, marker] // Colorize
(*you also could perform the watershed on the color negate of the distance transform of the binary image.
WatershedComponents[ColorNegate[DistanceTransform[img3]],
marker] // Colorize*)
As you can see my result is not as good as what is obtained in the mentioned answer. The main question is How can I prevent the segmentation of the background? For example in Matlab and OpenCV it is possible to mark the background before segmentation.
Also if possible how can I improve the segmentation?
To summarize:
1- I have a gray scale image.
2- I binarized it.
3- I perform distance transform on the binary image.
4- I binarized the distance transformed image to get the what they call seeds
.
5- I detected the edge of my original image and added to what I get in step 4. This is my marker for watershed transform.
6- I applied the GradientFilter to my original gray scale image.
7- I performed watershed transform on the gradient image using the marker.