How to distinguish touching and merging shapes on a binary image

I need to detect quasi-round or quasi-elliptical shapes on binary images, see attached image.
To do that I am using "bwlabel":
[labeledImage, numberOfRegions] = bwlabel(binaryImage);
It works well if shapes are isolated from each other. But as soon as they touch or partially merge, they are detected already as one shape. Is there any possibility to distinguish them?
Completely merged in one shape pattern which would be good to treate as one shape looks like that:
Any help is greatly appreciated. Especially in case of partially merged patterns.

2 commentaires

I believe watershed function will do that kind of task. Could you upload your binary image so that many experts here can try that ?

Connectez-vous pour commenter.

 Réponse acceptée

Hi Dzmitry-san,
Thank you for sharing your data, and sorry for my late response.
Though I tried the watershed function first, I found that it does not work well (-> it separates the region into 4 segments...). So I tried another method. Here is my try.
I confirmed that this code works well up to 'binaryImage_merged.mat,' but need more trick to address the 'binaryImage_merged_completely.mat.' But anyway, I hope this code would be some help for your research !!
% Read your image
%load('binaryImage_touch.mat');
load('binaryImage_merged.mat');
% Fill the hole
filledBinaryImg = imfill(binaryImage,'holes');
% Calculate surrounding area of 'necks'
CH = bwconvhull(filledBinaryImg);
BW2 = CH & ~filledBinaryImg;
% Delete small regions from the area
se = strel('disk',5);
BW2 = imopen(BW2, se);
BW2 = bwperim(BW2);
% Calculate shortest length between the two regions
labeledBW2 = bwlabel(BW2);
nLabels = max(labeledBW2(:));
distT = array2table(zeros(nLabels*(nLabels-1)/2,7));
distT.Properties.VariableNames =...
{'label1','label2','dist','r1','c1','r2','c2'};
n = 1;
for kk1 = 1:nLabels
[row1,col1] = find(labeledBW2 == kk1);
for kk2 = kk1+1:nLabels;
[row2,col2] = find(labeledBW2 == kk2);
dist = pdist2([row1,col1],[row2,col2]);
[~,idx] = min(dist(:));
[r,c] = ind2sub(size(dist),idx);
distT.label1(n) = kk1;
distT.label2(n) = kk2;
distT.dist(n) = dist(idx);
distT{n,{'r1','c1','r2','c2'}} = [row1(r),col1(r),row2(c),col2(c)];
n = n+1;
end
end
distT = sortrows(distT,'dist');
% Cut the region using 2 shortest paths
BWcutter = false(size(binaryImage));
for kk = 1:2
[cx,cy,~] = improfile(BWcutter,...
distT{kk,{'r1','r2'}},...
distT{kk,{'c1','c2'}});
idx = sub2ind(size(BWcutter),round(cx),round(cy));
BWcutter(idx) = true;
end
BWcutter = imdilate(BWcutter,strel('disk',2));
filledBinaryImg(BWcutter) = false;
% Show the result
labeledImage = bwlabel(filledBinaryImg);
imshow(label2rgb(labeledImage,'jet','k'))

Plus de réponses (0)

Community Treasure Hunt

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

Start Hunting!

Translated by