Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fill area between two connected components in MATLAB

I have a binary image that represents a number in MATLAB:

image description

I'd like to fill all the digits. The desired result is:

enter image description here

The only thing I found was the imfill function, but that wasn't really helpfull since I've lost my inner data (the 9's inner circle for example).

like image 679
user1240792 Avatar asked Jun 18 '12 08:06

user1240792


2 Answers

Another possibility is to use the BWBOUNDARIES function, which:

traces the exterior boundaries of objects, as well as boundaries of holes inside these objects

That information is contained in the fourth output A, an adjacency matrix that represents the parent-child-hole dependencies.

%# read binary image
bw = imread('SUvif.png');

%# find all boundaries
[B,L,N,A] = bwboundaries(bw, 8, 'holes');

%# exclude inner holes
[r,~] = find(A(:,N+1:end));        %# find inner boundaries that enclose stuff
[rr,~] = find(A(:,r));                      %# stuff they enclose
idx = setdiff(1:numel(B), [r(:);rr(:)]);    %# exclude both
bw2 = ismember(L,idx);                      %# filled image

%# compare results
subplot(311), imshow(bw), title('original')
subplot(312), imshow( imfill(bw,'holes') ), title('imfill')
subplot(313), imshow(bw2), title('bwboundaries')

enter image description here

like image 147
Amro Avatar answered Nov 12 '22 16:11

Amro


The problem is how to distinguish the holes from the digits. A possible ad hoc solution is filtering them by the area of the pixels inside.

function SolveSoProblem()

    I = imread('http://i.stack.imgur.com/SUvif.png');

    %Fill all the holes 
    F = imfill(I,'holes');

    %Find all the small ones,and mark their edges in the image
    bw = bwlabel(I);
    rp = regionprops(bw,'FilledArea','PixelIdxList');
    indexesOfHoles = [rp.FilledArea]<150;   
    pixelsNotToFill = vertcat(rp(indexesOfHoles).PixelIdxList); 
    F(pixelsNotToFill) = 0;
    figure;imshow(F);

    %Remove the inner area
    bw1 = bwlabel(F,4);
    rp = regionprops(bw1,'FilledArea','PixelIdxList');
    indexesOfHoles1 = [rp.FilledArea]<150;
    pixelListToRemove = vertcat(rp(indexesOfHoles1).PixelIdxList);
    F(pixelListToRemove) = 0;

    figure;imshow(F);
end

After step(1):

enter image description here

After step(2):

enter image description here

like image 45
Andrey Rubshtein Avatar answered Nov 12 '22 14:11

Andrey Rubshtein