Clear Filters
Clear Filters

Connect edges in image Matlab

47 views (last 30 days)
Chapz82
Chapz82 on 21 Mar 2023
Edited: DGM on 23 Mar 2023
I have the following image
As I want to find the edges I use the 'edge' function as so (A is the above image)
BW = edge(A, 'sobel');
And I get the following image
But when I zoom I see that not all edges are connected. What can I do to connect all of them?
I have tried using
b = bwmorph(BW, 'bridge')
but it doens't connect all of them.
Thank you.
PS: The problem description is aks to find the isolated members. The isolated members (in this example) are the ones with a edges length equal to 403 +- 18. The solution to this specific case is 1 member, but I got 0. There are other examples (images) where the criterion to be an isolated member also change.

Answers (3)

Cris LaPierre
Cris LaPierre on 22 Mar 2023
Edited: Cris LaPierre on 22 Mar 2023
bwmorph with the 'bridge' option only closes gaps that are 1 pixel wide.
Consider turning your grayscale image into a binary image before using edge. This will give you the highest gradients at your edges, making the results clearer.
There is a rendering difference when I run the code online. The results are the same, but they look different, so I'll add images of the desktop results.
A = imread("image.png");
BW = imbinarize(A);
BW = edge(BW, 'sobel');
imshow(BW)
You could then perform multiple morph operations to ensure any remaniing gaps are closed and isolated pixels are removed.
BW2 = bwmorph(BW,'thicken'); % adding pixels to the exterior of objects until doing so would result in previously unconnected objects being 8-connected.
BW2 = bwmorph(BW,'bridge'); % Bridge unconnected pixels
BW2 = bwmorph(BW2,'close'); % dilation followed by erosion
BW2 = bwmorph(BW2,'shrink'); % shrink objects to points by removing pixels from the boundaries of objects
BW2 = bwmorph(BW2,'spur'); % Remove spur pixels
BW2 = bwmorph(BW2,'clean'); % Remove isolated pixels
figure
imshow(BW2)
  3 Comments
Cris LaPierre
Cris LaPierre on 22 Mar 2023
Edited: Cris LaPierre on 23 Mar 2023
It seems we do not have enough details to help you meet the requirements of this assignment.
Chapz82
Chapz82 on 23 Mar 2023
Hello,
I added a PS message with what is supposed to do in this assignment. I don't know what more details I can give to you, but feel free to ask. I have tried regionprops and can't make it work to all examples

Sign in to comment.


DGM
DGM on 23 Mar 2023
Edited: DGM on 23 Mar 2023
Let's start with what the assignment apparently expected you to do. We can see that the isolated spade will be blob #2, so what is its perimeter?
A = imread('https://www.mathworks.com/matlabcentral/answers/uploaded_files/1332410/image.png');
% binarize
BW = imbinarize(A); % objects are in the background
% find the perimeter of the original image's background
P = bwperim(BW,4);
P = imclearborder(P); % necessary because image is wrong polarity
% show the objects (6 objects)
imshow(label2rgb(bwlabel(P),lines(7)))
% get the area of the perimeters in terms of area of the blobs in P
S = regionprops(P,'area');
S.Area
ans = 612
ans = 403
ans = 1787
ans = 27
ans = 1028
ans = 7
This gets a lot more sensible if you just deal with everything as a binary image where the spades are in the foreground. If you do that, you don't need to get rid of edge effects at the image border, and you actually have more than one object to start with. Note that because we're calculating the perimeter of the spades instead of the holes in the white background, the result is slightly different by a few pixels. That said, it's still within the requirements.
A = imread('https://www.mathworks.com/matlabcentral/answers/uploaded_files/1332410/image.png');
% binarize
BW = ~imbinarize(A); % objects in the foreground
P = bwperim(BW,4);
% get the area of the perimeters in terms of area of the blobs in P
S = regionprops(P,'area');
S.Area
ans = 609
ans = 399
ans = 1786
ans = 31
ans = 1028
ans = 12
Alternatively, since we're dealing with a positive image now, we could just ask regionprops() for the object perimeters. This wouldn't have worked with the image inverted, since all the spades would be holes belonging to one object.
Bear in mind though that this calculates the perimeter by a different method (see regionprops()), so it won't match the expectations given.
A = imread('https://www.mathworks.com/matlabcentral/answers/uploaded_files/1332410/image.png');
% binarize
BW = ~imbinarize(A); % objects in the foreground
% get the perimeter as calculated by regionprops()
S = regionprops(BW,'perimeter');
S.Perimeter
ans = 678.7950
ans = 450.6040
ans = 2.0002e+03
ans = 1.1716e+03
  2 Comments
Chapz82
Chapz82 on 23 Mar 2023
Edited: Chapz82 on 23 Mar 2023
Hello, thank you for your answer.
So, the best results I got was in your option 2
A = imread('https://www.mathworks.com/matlabcentral/answers/uploaded_files/1332410/image.png');
% binarize
BW = ~imbinarize(A); % objects in the foreground
P = bwperim(BW,4);
% get the area of the perimeters in terms of area of the blobs in P
S = regionprops(P,'area');
S.Area
But, in 10 examples that I tried, I got 3 wrong.
I can add them here
The criteria for each to be an isolated member are the following, respectivly:
403 +-15 (Answer: 6) - I got 5
460 +-14 (Answer: 7) - I got 3
460 +-13 (Answer: 4) - I got 2
DGM
DGM on 23 Mar 2023
Edited: DGM on 23 Mar 2023
I honestly have no idea why they want you to do this by edgefinding in the first place. It's unnecessary and it will be horribly dependent on how the edgefinding is performed. Because the images are noisy, it's also sensitive to tiny differences in how the image is binarized. Unless you know how they did both, it's unlikely you're going to get results that exactly match the ranges given over a varied set of images.
A sane person would throw out those numbers, as they're an artifact of a specific methodology which has apparently not been disclosed. You would then find an expected value based on observations using whatever method you're actually using and whatever images you actually have.
Better yet, you wouldn't even use edgefinding at all. That would be simpler, less senstive to the noise, and you wouldn't need to guess which one of numerous ways was used for calculating the perimeters. It also avoids the complication that an object with a hole has more than one edge.
A = imread('https://www.mathworks.com/matlabcentral/answers/uploaded_files/1334345/image.png');
% binarize
BW = ~imbinarize(A); % objects are in the background
% get the area of the objects
S = regionprops(BW,'area');
area = vertcat(S.Area)
area = 8×1
7543 7541 7539 7545 36382 7537 14973 7542
% which ones are isolated?
limits = [7510 7570]; % pick limits that suit the method
match = area>=limits(1) & area<=limits(2);
nnz(match) % how many?
ans = 6
% there's already a function to select blobs by area
isolated = bwareafilt(BW,limits);
imshow(isolated)
A = imread('https://www.mathworks.com/matlabcentral/answers/uploaded_files/1334350/image.png');
% binarize
BW = ~imbinarize(A); % objects are in the background
% get the area of the objects
S = regionprops(BW,'area');
area = vertcat(S.Area)
area = 8×1
7170 7180 7181 7185 21157 7185 7182 7185
% which ones match the specified range?
limits = [7150 7210];
match = area>=limits(1) & area<=limits(2);
nnz(match) % how many?
ans = 7
isolated = bwareafilt(BW,limits);
imshow(isolated)
A = imread('https://www.mathworks.com/matlabcentral/answers/uploaded_files/1334355/image.png');
% binarize
BW = ~imbinarize(A); % objects are in the background
% get the area of the objects
S = regionprops(BW,'area');
area = vertcat(S.Area)
area = 7×1
7180 7178 13983 22153 7188 19615 7176
% which ones match the specified range?
limits = [7150 7210];
match = area>=limits(1) & area<=limits(2);
nnz(match) % how many?
ans = 4
isolated = bwareafilt(BW,limits);
imshow(isolated)
Note how tightly grouped those areas are, and how distinct they are from those of undesired blobs. Consider the case of the two images with the isolated clubs. The perimeters of those clubs vary by more than 7% of the mean perimeter. On the other hand, the areas of those same blobs vary by only 0.2% of the mean area.
So that's what I would do, but if we're stuck trying to make the perimeters match some predefined result from an unknown process, we'd have to keep guessing what the intended method is. Apparently my prior guesses weren't close enough to exactly how it had been done prior.
Considering the dispersion of the perimeter metrics using the various methods, I'm almost willing to bet that (e.g.) 403 +-15 is the exact spread of values they observed with whatever code they wrote, with zero margin. Considering the smell of the assignment, I wouldn't doubt it.

Sign in to comment.


Image Analyst
Image Analyst on 23 Mar 2023
As I understand it you want to get internal edges too, and these are very faint/weak. The problem is the image is noisy so the edges just don't exist in some places. If you lower the threshold enough to get those weak edges, you start to pick up noise edges. So it could be likely that there will always be gaps in the edges and you'll have to use edge linking algorithms, which is more complicated. Anyway, this is what I got so far:
% Optional initialization steps
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
clear; % Erase all existing variables. Or clearvars if you want.
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 18;
grayImage=imread("spades.png");
subplot(2, 2, 1);
imshow(grayImage);
title('Original Image', 'FontSize',fontSize);
edgeImage = imgradient(grayImage);
subplot(2, 2, 2);
imshow(edgeImage, []);
impixelinfo;
title('Edge Image', 'FontSize',fontSize);
subplot(2, 2, 3);
histogram(edgeImage, 100);
grid on;
% Interactively and visually set a threshold on a gray scale image.
% https://www.mathworks.com/matlabcentral/fileexchange/29372-thresholding-an-image?s_tid=srchtitle
lowThreshold = 52;
highThreshold = 255;
% [lowThreshold, highThreshold] = threshold(lowThreshold, highThreshold, edgeImage)
mask = edgeImage > lowThreshold;
% Get rid of small particles
mask = bwareaopen(mask, 10);
subplot(2, 2, 4);
imshow(mask, []);
impixelinfo;
title('Mask Image', 'FontSize',fontSize);

Community Treasure Hunt

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

Start Hunting!