How to detect the waist in a BW image?

I am trying to split an abject that is in fact two touching objects. So to split it in two I need to detect the waist (the area with the minimum distance)
. I can;t figure out how to detect the waist.

4 Comments

I managed to segment the two objects using the watershed transform. But will still need to measure that waist for further analysis.
My code is shown below the image. BW_erode is the BW image to the right in the picture above.
Distant_BW = -bwdist(~BW_erode,'chessboard');
mask = imextendedmin(Distant_BW,10);
Distant_BW = imimposemin(Distant_BW,mask);
Distant_BW(~BW_erode) = -Inf;
Watershed_BW = watershed(Distant_BW);
rgb = label2rgb(Watershed_BW,'jet',[.5 .5 .5]);
figure(2)
imshow(rgb)
I think bwdist might be useful. Mind loading the original image so folks here can try out different approaches?
Thanks for your input Ashish. The original image is the top-left image (without the blue and red detected boarders). I will upload it all by itself if it helps. So I apply Wiener filter to smooth the background then use Canny edge detection. Then dilate and erode the detected edges simultaneously while filling the holes to find the border as the perimeter of the two touching objects. Once that is done, I need to detect the waist, split the two objects ad track/match their profile throughout the video. Any ideas or thoughts about doing that in a better/more efficient way is more than welcome.
Thanks a lot
I spent a few minutes, didnt get far (Though stdfilt followed by a threshold helps get close to the mask).
Your watershed image appears to have split the two, isnt that enough? and the waist appear clear,(you could filter the label image with a small summing filter and find areas with a particular sum if you want the 'waist' segment to quantify lenght).

Sign in to comment.

 Accepted Answer

Image Analyst
Image Analyst on 29 Jun 2015
Edited: Image Analyst on 30 Jun 2015
Why not use imdistline() or improfile() to manually specify them. Unless you have hundreds of images and need to do this automatically, that's probably the best way.
Otherwise, first call bwareafilt() to extract the largest blob. Then try to iterate where you call imdilate() followed by bwlabel() to count the number of blobs and quit when you get to two. Then binarize again and call bwmorph() with the "thicken" option to expand the blobs out so that they touch, but will not join/combine them. Then label again and call graycomatrix() to count how many pixels of blob #1 occur next to blob #2.

5 Comments

Thanks a lot for your response. I am not manually specifying the distance because, as you said, this image is one frame of hundreds of a video frames. So I need to automate the process.
As for your suggestion, my understanding is that you are suggesting that I use graycomatrix() to count how many pixels of blob #1 occur next to blob #2. But if I use the watershed transform to segment the blobs, then I will have zero elements between every two touching regions and then I won't be able to count neighboring pixels. Is there a way to ask matlab to count the [1 0 2] pixels (pixels that are shared between region#1 and region#2) instead of [1 2] ?
Who said anything about watershed? I didn't. My algorithm was specifically designed to not have a black line separating the blobs. I suggest you give my algorithm a try instead of the watershed method.
Oh I see. I thought you were commenting on my watershed results. Ok, so I took your suggestion, I actually like the algorithm.
I call bwlabel() and iterate if it detects only one object.
[Lables,num] = bwlabel(BW_erode);
Then call imerode() followed by bwlabel() to count bobs and quit when 2 blobs are detected while increasing the radius of the eroding.
k=0;
while num<2
k=k+1; % Increase eroding thickness
se = strel('square',k);
BW_seg_erode = imerode(BW_erode,se);
BW_seg_erode = bwareaopen(BW_seg_erode, 50); % Remove small pixels
[Lables,num] = bwlabel(BW_seg_erode);
figure(2);imshow(Lables,[]);hold on
plot(Inner_x, Inner_y,'.r');hold off
pause(.1)
end
Here is what I get. (The red line shows the original object perimeter)
I then call bwmorph() with thicken and use the same number of pixels removed in the eroding to thicken blobs exterior. However, the waist is not preserved. Here is what I get:
What do you suggest to resolve this issue?
Can you post your original binary image, or else code to get it from the gray scale image you uploaded? By the way, you can use the boundaries in poly2mask() if you want to mask out stuff outside the red lines.
Mona
Mona on 1 Jul 2015
Edited: Mona on 2 Jul 2015
Yes sure, here is the original BW image.
Ya, you are correct. masking out the extra pixels would work. I actually just multiplied the labeled thickened image by the original binary image shown above and it works just fine! Thanks a lot, your suggestions are very helpful.
Going back to graycomatrix(). Can you please tell me how to use it to find the waist. I used
[glcm,~] = graycomatrix(L_s,'NumLevels',num+1,'G',[])
But it doesn't give me the correct waist length. I found myself writing a hideous code to scan and match for [1 0 2] pixels!

Sign in to comment.

More Answers (1)

Hello. I have the same problem as Mona had. Can someone explain to me what she did because I do not understand the codes completely.

Categories

Find more on Images in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!