Search code examples
matlabimage-processingwatershedmathematical-morphologyimage-morphology

how to Solve the over segmentation in watershed


My input Image is

enter image description here

output image is

enter image description here

Expected output is something like this

enter image description here

it is seen that some of the ellipse like structures are merged with rectangle.Also I'm unable to separate each labels to get the ellipses Algorithm used is watershed

clear; close all;
I = imread('Sub.png');
I = rgb2gray(I);
figure; imshow(I)
I2 = imtophat(I, strel('square', 45));
figure; imshow(I2)
% Alpha=.047;
% h = fspecial('motion', 10, 5);
% w=gausswin(I2,Alpha)  % you'll have to play with N and alpha
% I2 = imfilter(I2,h,'same','symmetric'); % something like these options
level = .047;
BW = im2bw(I2,level);
D = -bwdist(~BW,'chessboard');
D(~BW) = -Inf;

L = watershed(D);
imshow(label2rgb(L,'jet','w'))

ultimate opening code :

ImageSource=imread('cameraman.tif');
ImTmp=ImageSource
ImResidue = zeros(size(ImageSource));
ImIndicator= zeros(size(ImageSource));
ImValues= zeros(size(ImageSource));
For size= 1 : N
se = strel('square',N);
ImOp  = imopen(ImageSource,se);
ImDiff=imabsdiff(ImOp,ImTmp)
if ImResidue < ImDiff then
               ImResidue = ImDiff
               ImIndicator = size
               ImValues = ImOp
end
ImTmp=ImOp
end

Solution

  • You have to use a watershed with markers if you want something accurate, but it's going to be more tricky. By default the basic watershed over segment because it uses each local minima as a marker.

    Therefore, you have to preprocess a little bit your image in order to increase the separation between the objects you want to segment, and then use markers in order to guide your watershed.

    [EDIT according to you EDIT] If you want just the little structures between the vertebras, then I would recommend to perform a small erosion in order to increase the gap between them, followed by an ultimate opening. The structures you want will disappear for small radii, when the vertebras will need bigger ones.

    Don't forget to use the markers on the gradient image.

    [EDIT 2, preliminary results] I was curious about your problem, so I gave it a try. Instead of going to the small regions between the vertebras (the one you want to segment), I tried to first segment the vertebras (what you want being between them).

    Here is what I did:

    1. Small opening (square order 1, square is faster and fine because you patient is well oriented in the image, else disk or hexagon) in order to increase the gap between the vertebras and their neighborhood.
    2. Area Opening (surface 23, but it does not really matter) in order to flatten the different zones, so erase the peaks.
    3. Area Closing (surface 23, but it does not really matter) in order to flatten again the different zones, so fill the holes. See the image result at this point. See, everything looks smoother, but the different boundaries/rims are still intact.
    4. Ultimate opening (UO).
    5. ThresholdingS according to the ultimate opening results (residues, values and indicators). See the vertebras approximation. I haven't the values anymore (I've deleted my code), but you can take a look to the UO results and find them back. However, I still have the UO results if you want.
    6. Opening (disk order 7) in order to erase all the artifacts and false positive (the vertebras being big)
    7. Same operations as 5 in order to approximate the small patterns you want to segment. See the results
    8. Small erosion of result on step 7 in order to have the outer markers (between the vertebras). I complete the outer markers with the boundary of a big dilation (disk order 11) of results of step 6.
    9. Here are the markers I get.
    10. Watershed with the computed markers, here is the preliminary result

    The patterns you want to segment are between the vertebras, so I guess this result narrows down a lot the region of interest.

    Does it work for you?

    I cannot share the code, but I guess that you should find everything in MatLab.

    You can improve this result by detecting the rectangular shapes.