MATLAB: Filling the objects found by canny edge

image segmentation

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.

Best Answer

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.