Filling the objects found by canny edge
7 views (last 30 days)
Show older comments
Hi, I am trying to find object on the image. I applied some morphological processing and then canny edge function to find the object. However the edge function can only find the boundaries. The probles is how to fill the found objects? Another problem: some object are not fully closed, thus how to close the gaps? Possibly this question has already been answered but I searched the forum and help and I couldnt find solution. To see the image use this link: http://www.uploadup.com/di-HQA6.jpg
I would be grateful for any clues.
0 Comments
Accepted Answer
Sven
on 9 Dec 2011
Kasia, I wrote the following, which does what (I think) you're looking for:
I = imread('di-HQA6.jpg');
BW = bwareaopen(all(I>220,3),10);
cc = bwconncomp(BW);
% As you can see, some connected components are not *closed*:
figure, imagesc(imfill(labelmatrix(cc),'holes')), drawnow
% So, let's try closing them by iterative dilations
BWblank = false(cc.ImageSize);
stats = regionprops(cc,'ConvexImage','EulerNumber');
for i = find([stats.EulerNumber]>0)
distIm = bwdist(~stats(i).ConvexImage);
maxClose = ceil(max(distIm(:)));
BWslice = BWblank;
BWslice(cc.PixelIdxList{i}) = true;
if isinf(maxClose), continue; end;
for dilSz = 2:maxClose
BWnew = imdilate(BWslice,ones(dilSz));
statsNew = regionprops(BWnew,'EulerNumber');
if statsNew.EulerNumber<=0
BWnew = imerode(imfill(BWnew,'holes'),ones(dilSz));
cc.PixelIdxList{i} = find(BWnew);
end
end
end
figure, imagesc(imfill(labelmatrix(cc),'holes')), drawnow
% That got almost all of them. Some are left over where the dilation itself
% filled everything so the euler number stayed at 1. Let's just replace
% those with their convex hull
stats = regionprops(cc,'ConvexImage','EulerNumber','BoundingBox');
for i = find([stats.EulerNumber]>0)
maxClose = ceil(max(distIm(:)));
BWslice = BWblank;
BWslice(cc.PixelIdxList{i}) = true;
distIm = bwdist(~BWslice);
if ~any(distIm(:)>1)
BWnew = BWslice;
bb = ceil(stats(i).BoundingBox);
BWnew((1:bb(4))+bb(2)-1,(1:bb(3))+bb(1)-1) = stats(i).ConvexImage;
cc.PixelIdxList{i} = find(BWnew);
end
end
L = imfill(labelmatrix(cc),'holes');
figure, imagesc(L)
% Now we know that any blobs surrounded by other blobs are actually holes
indsOfHoles = find(arrayfun(@(i)mode(double(L(bwmorph(L==i,'dilate',1)&~(L==i)))),1:cc.NumObjects));
L(ismember(L,indsOfHoles)) = 0;
figure, imagesc(L)
The last variable L is what you're looking for. Luckily components get numbered from the outside in, so an "interior blob" will always have a higher number than it surrounding blob, meaning the imfill commands to the label matrix above don't paint over holes.
More Answers (2)
Image Analyst
on 9 Dec 2011
filledImage = imfill(binaryImage, 'holes');
3 Comments
Image Analyst
on 9 Dec 2011
So do it twice. The first time will fill the donut and leave the interior hole, and the second time will fill the interior hole.
Image Analyst
on 9 Dec 2011
Are you talking about having problem with the blobs that are chopped off by the edge of the image? Is the boundary open at the edge?
Marlene
on 27 Dec 2011
Hello Sven,
You can explain to me what exactly does the line of code bwareaopen BW = (all (I> 220,3), 10)? I did not realize this part all(I> 220,3).
Thank's
1 Comment
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!