How to smooth rough edges along a binary image
72 views (last 30 days)
Show older comments
Caolan Furey
on 4 Feb 2018
Commented: Manuel Hoffmann
on 18 Jul 2022
Hey, I'm trying to mark out the tips and bases of each finger on the following image
I binarized the image using the following piece of code
a = imread('img235.jpg');
a = rgb2gray(a);
msk = a > 30;
props = regionprops(logical(msk), 'Area');
allAreas = sort([props.Area]);
msk = bwareaopen(msk, 25);
msk = imclearborder(msk);
bw2 = bwareafilt(msk,1);
BW2 = imfill(bw2,'holes');
to obtain this image:
I next formed a boundary around the image using bwboundaries and marked out the peaks and valleys of the fingers, and I'm trying to estimate where the edge of the little finger is located by finding the distance between the tip of the little finger and the valley between the little finger and the valley between the little finger and the ring finger.
My problem is that because the boundary between the little finger tip and the valley is smoother than the boundary on the other side of the little finger, I do not obtain a good estimate for the location of the base of the little finger because the jagged edges on this end of the boundary of the little finger mean there are a greater number of pixels along the boundary and the boundary is overall longer than it should be. My question is how do I smooth out these jags/irregularities along the boundary?
I would ideally like to obtain a smooth boundary across the entire hand, such as along the smooth edge of the little finger shown in the image above.
1 Comment
cliffy
on 3 Oct 2018
Hi, I wonder if you remember how you found the peaks and valleys of the binary image?
Accepted Answer
Image Analyst
on 4 Feb 2018
There are several ways. You could simply blur the image with conv2() and re-threshold
windowSize = 51;
kernel = ones(windowSize) / windowSize ^ 2;
blurryImage = conv2(single(binaryImage), kernel, 'same');
binaryImage = blurryImage > 0.5; % Rethreshold
Or you could use a Savitzky-Golay filter along with bwboundaries() to smooth out the coordinates, then use poly2mask() if you need to turn the coordinates into an image again. See attached demo.
11 Comments
Holden Tranquillo
on 6 Apr 2022
How do I use the provided Savitzky-Golay filter on my traced image? The code provided seems like a demo. Thanks
Manuel Hoffmann
on 18 Jul 2022
I used image analysts code and put it in a loop which works quite well to smooth the edges on binary images. Note that I scale the image up and that the code is very slow as I wanted to prevent features from merging.
sf = 3; %upscaling factor
sz = size(I);
xg = 1:sz(1);
yg = 1:sz(2);
F = griddedInterpolant({xg,yg},double(I));
F.Method = 'cubic';
xq = (1:(1/sf)*(0.53):sz(1))'; %scale to upscaling factor*1px/nm
yq = (1:(1/sf)*(0.53):sz(2))';
I_re = im2bw(uint8(F({xq,yq})),0.5);
I_c = I_re;%To control area changes smoothing
%Below follows an iterative filtering algorithm for this application. The
%edges are continuously blurred and rethreshholded. If particles are
%deleted or merged the code will fail executing.
sz = size(I_re);
L1 = bwlabel(I_re);
N = max(L1,[],'all');
windowSize = 19;% Here some filtering, slight blurring then rethreshold to get rid of edges
for k = 1:10 %k iterations
L1 = bwlabel(I_re);
I_b= zeros(sz);
%The following retrieves each feature and saves it in temp array
for i = 1:N
I_temp = zeros(sz);
I_b1 = I_temp;
for j = 1:sz(1)
for jj = 1:sz(2)
if L1(j,jj) == i
I_temp(j,jj) = I_re(j,jj);
end
end
end
%The following corrects windowsize for small particles
if sum(I_temp(:) >0 ) < 1*(windowSize^2)*pi*sf^2
window = round(windowSize/3);
% disp('window resized')
else
window = windowSize;
end
kernel = ones(window)/window^2;
I_b1 = conv2(I_temp, kernel, 'same'); %Filtering by 2dconvolution
%The following prevents merging of particles or to the edge by adding a zero
for j = 1:sz(1)
for jj = 1:sz(2)
if I_b(j,jj)==0 && I_b1(j,jj) > 0
I_b(j,jj) = I_b1(j,jj);
elseif I_b(j,jj)~=0 && I_b1(j,jj) ~= 0
I_b(j,jj) = 0;
elseif j == sz(1) || jj == sz(2)
I_b(j,jj) = 0;
end
end
end
end
I_re = I_b > 0.5;
end
I_2 = I_re;
%Remove pixels sticking out
I_2 = ~I_2;
I_2 = bwmorph(I_2,'majority');
I_2 = ~I_2;
I_2 = bwmorph(I_2,'majority');
More Answers (0)
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!