How to use imfill() function to fill the interior of the boundary surface using Matlab?

Hi dear community members,
i am using flood fill operation to fill the interior. i have closed the boundary surface. There are no holes on the boundary surface but still, the interior cannot be filled.
I am using the following code. Please guide me where i am making mistake. The matrix A as a text file is already attached.
Regards.
interior_filled = imfill(A,'holes')

1 Kommentar

Is the imfill() function is not capable to fill the interior region? How come, boundary surface is closed and imfill() function is not applicable?

Melden Sie sich an, um zu kommentieren.

 Akzeptierte Antwort

@M.S. Khan, try this:
% Demo by Image Analyst, March, 2021.
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
clearvars;
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 16;
fprintf('Beginning to run %s.m ...\n', mfilename);
grayImage = importdata('Boundary_closed_1s_3s.txt');
subplot(2, 1, 1);
imshow(grayImage, []);
impixelinfo;
axis('on', 'image');
% Create a binary image.
binaryImage = grayImage ~= 0;
% Fill the object by scanning across all columns and
% drawing a line from the top-most pixel to the bottom-most pixel.
[rows, columns] = size(binaryImage);
for col = 1 : columns
% Find the top most pixel.
topRow = find(binaryImage(:, col), 1, 'first');
if ~isempty(topRow)
% If there is a pixel in this column, then find the lowest/bottom one.
bottomRow = find(binaryImage(:, col), 1, 'last');
% Fill from top to bottom.
binaryImage(topRow : bottomRow, col) = true;
end
end
interior_filled = binaryImage;
% interior_filled = imfill(binaryImage, 4, 'holes');
subplot(2, 1, 2);
imshow(binaryImage, []);
axis('on', 'image');
fprintf('Done running %s.m\n', mfilename);

12 Kommentare

Dear Image Analyst, thanks for your kind guidance. you have used the loop to fill the interior inside the boundary surface while usually, we are using imfill() function to fill the interior. Can we say, imfill() function is not successful in all cases. Please guide me.
How to apply the same code if we change the shape of the object. Could you please guide me. In case of the attached file, we cannot apply top to bottom filling apprach because the object is apple. The cells below the stems should not be filled as 1s. could we use another if else statement to handle such situation. The file of the apple is attached. i am very thankfull for your kind cooperation, coordination and guidance.
imfill() does not work because there is a big gap in the boundary. You could use bwconvhull() like I showed you before. Or you could use this way which won't change the shape to convex. However this way relies on the gap not being completely open in a column. It works with this one because the gaps "cross" over each other so that there is no column that is completely open at the top.
It makes sense that if the image is different, the algorithm may need to change. One algorithm may not work for all images. You may want to look into "edge linking" to close gaps. I'm attaching two demos.
Thanks for your cooperation and guidance. I am trying to understand these two demos but looking very hard . Also, i have applied bwconvhull() and the colums methods (as above ) to handle the file as attached above but it changed the shape. i am trying to share this problem as a new thread. i may get some more guidance from community members
Regards
Here is a version that fills the interior by doing a convex hull but then erases all the little "bays" around the outside edge that got filled in "accidentally":
% Demo by Image Analyst, March, 2021.
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
clearvars;
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 16;
fprintf('Beginning to run %s.m ...\n', mfilename);
grayImage = importdata('Boundary_closed_1s_3s.txt');
subplot(2, 3, 1);
imshow(grayImage, []);
impixelinfo;
axis('on', 'image');
title('Original Image', 'FontSize', fontSize);
% Create a binary image.
binaryImage = (grayImage ~= 0);
subplot(2, 3, 2);
imshow(binaryImage, []);
axis('on', 'image');
title('Original Binary Image', 'FontSize', fontSize);
% Take the convex hull.
interior_filled = bwconvhull(binaryImage);
% interior_filled = imfill(binaryImage, 4, 'holes');
subplot(2, 3, 3);
imshow(interior_filled, []);
axis('on', 'image');
title('Convex Hull Image', 'FontSize', fontSize);
% Let's see how many blobs there are in the outer "bays".
% That is how many little nooks and crannies got filled in by doing the convex hull.
% But first there are some holes in the binary image that we need to fill (like near the top of the shape).
binaryImage = imfill(binaryImage, 'holes');
% Now find the difference between them.
filledBlobs = xor(interior_filled, binaryImage);
% Get rid of the largest blob - this is the main interior.
% Any small outerblobs, if any, will remain.
filledBlobs = filledBlobs & ~bwareafilt(filledBlobs, 1);
subplot(2, 3, 4);
imshow(filledBlobs, []);
axis('on', 'image');
caption = sprintf('Outer Blobs Mask: blobs between\nOriginal and Convex Hull');
title(caption, 'FontSize', fontSize);
% Count them.
[labeledImage, numBlobs] = bwlabel(filledBlobs);
message = sprintf('There are %d blobs between the convex hull and the binary image.\nNow let us erase them.', numBlobs);
uiwait(msgbox(message));
% Erase all those tiny blobs between the original binary image and the convex hull.
interior_filled(filledBlobs) = false;
subplot(2, 3, 5);
imshow(interior_filled, []);
axis('on', 'image');
title('Final Mask', 'FontSize', fontSize);
g = gcf;
g.WindowState = 'maximized'
fprintf('Done running %s.m\n', mfilename);
Dear image analyst, all the blobs are not removed. Could you please see the attached file. If you apply the code on it, there are extra blobs across the stem of the apple. The Attached file of the coordiantes are here.
How are you producing these perimeters in the first place? Rather than fixing them by edge linking, convex hull, or other tricks which seem to be unique for every new image, why not just produce a closed perimeter to begin with by using the proper segmentation algorithm?
Sorry Dear Image Analyst for the late reply. i was out of station. i am using an algorithm to generate boundary surface. Using the close boundary surface, i want to fill the interior of the boundary surface but i want to fill the interior same like the boundary surface generated. Convex full is ok for cone or sphere but in case of irregular object , it creates problems. How can i use the segmentation algorithm to produce the closed perimeter. Any guidance please
Then I think the best approach is to fix the algorithm that generates the boundary surface so that it does not create breaks in the boundary in the first place (rather than try to fix a broken boundary after it's been created). Can you upload that code?
Using this code, i am generating the closed surface. 'P' is used to fill the gaps along the boundary surface.
Could you please guide me if we change the shape to the traingular or circular, should 'P' be changed
Aorg = load('Matrix_Boundary_fills_1s_only.txt');
gapmax = 40;
[m,n] = size(Aorg);
A = double(Aorg>0);
P=[1 2 3; % used to fill the gaps. It should be readjusted to fill gaps.
8 0 4;
7 6 5];
Apad = zeros(m+2,n+2);
maxattempt = 10;
for niter = 1:maxattempt
Apad(2:end-1,2:end-1) = A>0;
B = zeros(m,n,8);
for k=1:8
[i,j] = find(P==k);
B(:,:,k) = Apad(i-2+(2:end-1),j-2+(2:end-1));
end
As = A>0 & sum(diff(B(:,:,[1:8 1]),1,3)==1,3)<=1;
[y,x] = find(As);
if isempty(x)
break
end
% p = length(x);
xy = [x,y];
xy1 = reshape(xy,1,[],2);
xy2 = reshape(xy,[],1,2);
d = sum(abs(xy1-xy2),3);
d(d==0) = NaN;
i = (1:size(d,1))';
[dmin,j] = min(d,[],2);
keep = dmin <= gapmax;
i = i(keep);
j = j(keep);
for k=1:length(i)
xyi = xy(i(k),:);
xyj = xy(j(k),:);
dxy = xyi-xyj;
if abs(dxy(1)) > abs(dxy(2))
xr = linspace(xyi(1),xyj(1),abs(dxy(1))+1);
yr = round(interp1([xyi(1),xyj(1)],[xyi(2),xyj(2)],xr));
else
yr = linspace(xyi(2),xyj(2),abs(dxy(2))+1);
xr = round(interp1([xyi(2),xyj(2)],[xyi(1),xyj(1)],yr));
end
A(sub2ind(size(A),yr(2:end-1),xr(2:end-1))) = 3;
end
end
end
dlmwrite('Boundary_closed_1s_3s.txt',A);
Hi Dear Image Analyst, could you please share your feedback. I am waiting for your expert point of view. Regards!
i think, the 'P' should be changed with respect to the shape of the object. i am trying how to handle it.

Melden Sie sich an, um zu kommentieren.

Weitere Antworten (0)

Produkte

Version

R2020a

Community Treasure Hunt

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

Start Hunting!

Translated by