MATLAB Answers

Join disconnected terminal points of components in a binary image

24 views (last 30 days)
Ankit Sahay
Ankit Sahay on 15 Jan 2021
Commented: Ankit Sahay on 25 Feb 2021 at 6:11
HI everybody!
I am working on flame edge detection. What I need is two single loops to depict two different flame edges. I have attached the binary image of my flame edge below:
(Please open the image in a different window to view it properly)
Let's talk about the left half of the image to keep things simple. If you look at the left half of the image, you will see that there isn't a single loop, as the edge touches itself at different points. A magnified image is attached below:
My primary objective is to remove the appropriate cells so that I can have one closed loop. I might have to remove some parts of the origibal edge, but I think that's okay. To accomplish this, I complemented the original binary image, and used the following code to specify the objects that have 4-connectivity (Please correct me here if I am wrong):
complement = imcomplement(fb2); % fb2 is the origibal binary image matrix
BW2 = bwareafilt(complement,3,4);
BW3 = imcomplement(BW2);
imshow(BW3);
fb2 is the binary image matrix file, attached with the question.
One of the problematic areas (from the left half of the above image) is shown below:
Thereafter I used the answer given on this page to remove the cells having 2 neighbours:
numberNeighboringPixels = 2; % Can also be 1 or 3
% Using Lookup Table
lut = makelut(@(x)sum(x(:))==(numberNeighboringPixels+1),3);
BW3_LUT = bwlookup(BW3,lut) & BW3;
%%Plot and show the results are the same figure
% subplot(1,2,1);
% imshow(BW3); title('Original Image');
% subplot(1,2,2);
imshow(BW3_LUT);
BW3_LUT gives me the following image:
Unfortunately, the above code causes discontinuities in the edge. Magnifying the discontinuity inn the left loop of the above figure:
This means that instead of 2 disconnected components (corrsponding to two closed loops) that I want in my image, I have n>2 disconnected components; in this case: 8. I have color code all the components for better visualization:
A magnified version of the color coded discontinuity:
I then thought that if I am able to find the terminal points of the components, I might be able to connect them. I use the following code to find the endpoints (taken from this answer):
BW3_LUT = bwareaopen(BW3_LUT,2); % to remove isolated cells
[L, Num] = bwlabel(BW3_LUT);
for K = 1 : Num
[epr{K}, epc{K}] = find( bwmorph(L == K, 'endpoints') );
end
Although I now have the end points, the components are not labeled according to the sequence I want to join them. Also, I don't know how to join the end points. I can use the Bresenham's Line Algorithm, but I can use that only after I can sequence the components properly (through code), which means "n-th component connects to n+1-th component. I can separate the two halves of the original binary image in order to do this.
In the end, my main objective is to have one single loop for one flame edge. I might be using a wrong approach, but this is what I can think of right now. I am losing some of the "wrinkled" features of the edges, but that is okay as long as I don't lose all of them. Please help me with this issue. Let me know if there are any more clarifications I need to make.

  1 Comment

Ankit Sahay
Ankit Sahay on 16 Jan 2021
I can add a rule that says "I'd like to connect any endpoints that are within a separation of 3 pixels with a line connecting them".

Sign in to comment.

Accepted Answer

Image Analyst
Image Analyst on 16 Jan 2021
What I would try is to draw a white line along the bottom edge only then fill the shapes, and then call bwboundaries()
lastLine = binaryImage(end, :); % Save original last line.
binaryImage(end, :) = true;
binaryImage = imfill(binaryImage, 'holes');
% Restore last line
binaryImage(end, :) = lastLine;
boundaries = bwboundaries(binaryImage);

  3 Comments

Ankit Sahay
Ankit Sahay on 20 Jan 2021
Thank you for the reply. I apologize for the late answer.
Your code works in certaincases, although I face problems when I try to get back a revised binary image. I am using the following code:
binaryImage = fb2;
lastLine = binaryImage(end, :); % Save original last line.
binaryImage(end, :) = true;
binaryImage = imfill(binaryImage, 'holes');
% Restore last line
binaryImage(end, :) = lastLine;
boundaries = bwboundaries(binaryImage);
subplot(1,3,1)
imshow(flipud(fb2))
subplot(1,3,2)
visboundaries(boundaries)
b_l = boundaries{2};
b_r = boundaries{1};
newBinaryImage = zeros(size(fb2));
for k = 1:length(b_l)
newBinaryImage(b_l(k,2),b_l(k,1)) = 1;
end
for k = 1:length(b_r)
newBinaryImage(b_r(k,2),b_r(k,1)) = 1;
end
subplot(1,3,3)
imshow(flipud(newBinaryImage'))
There are issues regarding the size of the newBinaryImage, but I can fix them later. The primary issue is that when I run the above code, I face the following issue:
fb2 is the original data that I have attached with the main question. In the image attached above, the left image is a magnified view of the original binary image, the middle image is obtained by using visboundaries command, and the right image is my attempt to get the revised binary image (newBinaryImage in the code). The yellow-circled region contains an issue that has been resolved, but the blue-circled region is where I cannot regain the revised binary image.
Maybe this is because I don't properly understand the bwboundaries function. The boundaries were traced perfectly, but getting a new binary image is a different problem.
Can you please help me with this? Thank you.
Image Analyst
Image Analyst on 20 Jan 2021
The issue is if you haved a blob that is only touching your main blob at one pixel where that one pixel is touching only at the diagonal tip. This is called "8-connected". The other situation is where the pixel touches along one of the 4 main sides of the square pixel and that is called "4-connected. At the diagonal touching point, the boundaries come to a point so essentially the width of the boundary there is zero and you have to decide if you want to include those 8-connected regions or not. It sounds like you don't want them. So to get rid of them you can use bwareafilt() to get rid of them based on either size, or number. So you could take the largest 4-connected blob:
binaryImage = bwareafilt(binaryImage, 1, 4);
Ankit Sahay
Ankit Sahay on 25 Feb 2021 at 6:11
I apologize for the lalte reply. This worked well. Thank you!

Sign in to comment.

More Answers (0)

Community Treasure Hunt

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

Start Hunting!