Extract the center of the coarse curve of binary image

2 views (last 30 days)
I want to extract the center of a series of curves, as shown in the figure below, which looks roughly like the red line in the figure

Accepted Answer

Image Analyst
Image Analyst on 25 Dec 2020
Try inverting the binary image and then using bwskel(). Demo attached.
  3 Comments
Image Analyst
Image Analyst on 28 Dec 2020
Here's an attempt at it. Continue to refine it (because I can't spend the time to do the whole thing for you).
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 = 15;
fprintf('Beginning to run %s.m ...\n', mfilename);
%--------------------------------------------------------------------------------------------------------
% READ IN IMAGE
folder = pwd;
baseFileName = 'fingerprint.png';
% Get the full filename, with path prepended.
fullFileName = fullfile(folder, baseFileName);
% Check if file exists.
if ~exist(fullFileName, 'file')
% The file doesn't exist -- didn't find it there in that folder.
% Check the entire search path (other folders) for the file by stripping off the folder.
fullFileNameOnSearchPath = baseFileName; % No path this time.
if ~exist(fullFileNameOnSearchPath, 'file')
% Still didn't find it. Alert user.
errorMessage = sprintf('Error: %s does not exist in the search path folders.', fullFileName);
uiwait(warndlg(errorMessage));
return;
end
end
grayImage = imread(fullFileName);
% Get the dimensions of the image.
% numberOfColorChannels should be = 1 for a gray scale image, and 3 for an RGB color image.
[rows, columns, numberOfColorChannels] = size(grayImage);
if numberOfColorChannels > 1
% It's not really gray scale like we expected - it's color.
% Use weighted sum of ALL channels to create a gray scale image.
grayImage = rgb2gray(grayImage);
end
% Display the image.
hFig = figure;
subplot(4, 1, 1);
imshow(grayImage, []);
title('Original Grayscale Image', 'FontSize', fontSize, 'Interpreter', 'None');
impixelinfo;
hFig.WindowState = 'maximized'; % May not work in earlier versions of MATLAB.
drawnow;
%--------------------------------------------------------------------------------------------------------
% Crop the image out of the screenshot
grayImage = grayImage(85:378, 9:1088);
%--------------------------------------------------------------------------------------------------------
% SEGMENTATION
% Binarize the image
binaryImage = grayImage < 128;
% Display the binary image.
subplot(4, 1, 2);
cla;
imshow(binaryImage, []);
title('Binary Image', 'FontSize', fontSize, 'Interpreter', 'None');
axis('on', 'image');
%--------------------------------------------------------------------------------------------------------
% Label the image so we can process each ride individually.
[labeledImage, numRegions] = bwlabel(binaryImage);
for k = 1 : numRegions
fprintf('Processing ridge #%d of %d\n', k, numRegions);
% Get this ridge
thisRidge = ismember(labeledImage, k);
%--------------------------------------------------------------------------------------------------------
% SKELETONIZATION
% Now skeletonize
skelImage = bwskel(thisRidge, 'MinBranchLength', 10); % First guess. Strangely bwskel() doesn't seem to have any short spurs, no matter what MinBranchLength is.
% skelImage = bwmorph(binaryImage, 'skel', inf); % First guess. Will have short spurs. Shouldn't use this, but going to just for the demo.
% Display the original skeleton image, with annoying spurs
subplot(4, 1, 3);
imshow(skelImage, []);
title('Original Skeleton Image', 'FontSize', fontSize, 'Interpreter', 'None');
axis('on', 'image');
drawnow;
% First get the area of the skeleton and take half of it to get the MinBranchLength.
% This should give use the longest spine path only, and get rid of all spurs (at least for THIS demo image).
MinBranchLength = round(sum(skelImage(:))/2)
% Now take the skeleton again using that min branch length we just computed.
skelImage = bwskel(thisRidge, 'MinBranchLength', MinBranchLength);
% Display the skeleton image.
subplot(4, 1, 4);
imshow(skelImage, []);
title('Skeleton Image', 'FontSize', fontSize, 'Interpreter', 'None');
axis('on', 'image');
drawnow;
% Get the coordinates of the skeleton
[r, c] = find(skelImage);
% Save them into a cell array (because they are all different sizes).
x{k} = c;
y{k} = r;
% Overlay the skeleton on the original image.
subplot(4, 1, 1);
imshow(imoverlay(binaryImage, skelImage, 'r'));
hold on;
plot(c, r, 'r.', 'LineWidth', 4);
title('Binary Image with Skeleton Overlaid', 'FontSize', fontSize, 'Interpreter', 'None');
drawnow;
end
% Show final results.
hFig2 = figure;
imshow(grayImage);
title('Final Image', 'FontSize', fontSize, 'Interpreter', 'None');
axis('on', 'image');
drawnow;
hold on;
for k = 1 : numRegions
thisx = x{k};
thisy = y{k};
plot(thisx, thisy, 'r.', 'LineWidth', 4);
end
fprintf('Done running %s.m ...\n', mfilename);
msgbox('Done!');
JH F
JH F on 29 Dec 2020
Ok, I will continue to improve it. Thank you very much for your answer.

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!