How to fitline on my binary image and find distance
11 views (last 30 days)
Show older comments
Hello,
I have a question about my image processing problem. I have convert the image into binary and now i would like to use fitline on my image. Basically want to smooth the line with the curve. I am a beginner for MATLAB software. Please help me to find the solution. Also i want to find distance of one thin line to thick line (top to bottom).
I am attachng my picture as png. Also my code is there.
0 Comments
Accepted Answer
Image Analyst
on 27 Jun 2020
Your question is very unclear and ambiguous. Like, exactly what does "want to find distance of one thin line to thick line (top to bottom)" mean??? Where are thin lines and where are the thick lines in your image?
Here is another guess at what you might mean. I just find the topmost and bottommost white pixel in the image for each column, and compute the distance (height) between them:
% By Image Analyst
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 = 22;
%--------------------------------------------------------------------------------------------------------
% READ IN IMAGE
folder = pwd;
baseFileName = 'image.jpeg';
% 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);
% ALTERNATE METHOD: Convert it to gray scale by taking only the green channel,
% which in a typical snapshot will be the least noisy channel.
% grayImage = grayImage(:, :, 2); % Take green channel.
end
subplot(2, 2, 1);
imshow(grayImage, []);
impixelinfo;
title('Original Gray Scale Image', 'FontSize', fontSize, 'Interpreter', 'None');
hFig = gcf;
hFig.WindowState = 'maximized'; % May not work in earlier versions of MATLAB.
drawnow;
%--------------------------------------------------------------------------------------------------------
% SEGMENTATION OF IMAGE
% Get a binary image
binaryImage = imbinarize(grayImage);
% Get rid of big white frame around the border of the image.
binaryImage = imclearborder(binaryImage);
subplot(2, 2, 2);
imshow(binaryImage, []);
impixelinfo;
title('Binary Image', 'FontSize', fontSize, 'Interpreter', 'None');
hFig = gcf;
hFig.WindowState = 'maximized'; % May not work in earlier versions of MATLAB.
drawnow;
% Scan image finding the distance from topmost white pixel to bottommost.
topRows = nan(1, columns);
bottomRows = nan(1, columns);
for col = 1 : columns
thisColumn = binaryImage(:, col);
t = find(thisColumn, 1, 'first');
if ~isempty(t)
topRows(col) = t;
bottomRows(col) = find(thisColumn, 1, 'last');
end
end
% Plot top rows and bottom rows.
subplot(2, 2, 3);
x = 1 : columns;
plot(x, topRows, 'b-', 'LineWidth', 2);
grid on;
hold on;
plot(x, bottomRows, 'r-', 'LineWidth', 2);
title('Top and Bottom Rows', 'FontSize', fontSize);
xlabel('Column', 'FontSize', fontSize);
ylabel('Row', 'FontSize', fontSize);
legend('Top Rows', 'Bottom Rows');
% Plot heights.
heights = bottomRows - topRows;
subplot(2, 2, 4);
x = 1 : columns;
plot(x, heights, 'b-', 'LineWidth', 2);
grid on;
title('Heights', 'FontSize', fontSize);
xlabel('Column', 'FontSize', fontSize);
ylabel('Height in Rows', 'FontSize', fontSize);
0 Comments
More Answers (3)
Image Analyst
on 27 Jun 2020
Did you try polyfit() to fit a line to the pixels?
% By Image Analyst
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 = 22;
%--------------------------------------------------------------------------------------------------------
% READ IN IMAGE
folder = pwd;
baseFileName = 'image.jpeg';
% 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);
% ALTERNATE METHOD: Convert it to gray scale by taking only the green channel,
% which in a typical snapshot will be the least noisy channel.
% grayImage = grayImage(:, :, 2); % Take green channel.
end
subplot(2, 1, 1);
imshow(grayImage, []);
impixelinfo;
title('Original Gray Scale Image', 'FontSize', fontSize, 'Interpreter', 'None');
hFig = gcf;
hFig.WindowState = 'maximized'; % May not work in earlier versions of MATLAB.
drawnow;
%--------------------------------------------------------------------------------------------------------
% SEGMENTATION OF IMAGE
% Get a binary image
binaryImage = imbinarize(grayImage);
% Get rid of big white frame around the border of the image.
binaryImage = imclearborder(binaryImage);
subplot(2, 1, 2);
imshow(binaryImage, []);
impixelinfo;
title('Binary Image', 'FontSize', fontSize, 'Interpreter', 'None');
hFig = gcf;
hFig.WindowState = 'maximized'; % May not work in earlier versions of MATLAB.
drawnow;
% Get all coordinates
[y, x] = find(binaryImage);
% Fit a line through them
coefficients = polyfit(x, y, 1)
% Get a fitted line
xFit = 1 : columns;
yFit = polyval(coefficients, xFit);
% Plot the line in red over the image.
hold on;
plot(xFit, yFit, 'r-', 'LineWidth', 2);
% Put the equation up
txt = sprintf('y = (%f) * x + (%f)', coefficients(1), coefficients(2));
text(100, 200, txt, 'Color', 'r', 'FontSize', 15, 'FontWeight', 'bold');
19 Comments
Image Analyst
on 16 Jul 2020
Try scanning column by column. If there are exactly two regions, go from the top or center of the first region to the top of the second region. Or you could just measure the height of the black gap between them. It just depends on what your definition of distance is.
clc; % Clear the command window.
fprintf('Beginning to run %s.m ...\n', mfilename);
close all; % Close all figures (except those of imtool.)
imtool close all; % Close all imtool figures.
clear; % Erase all existing variables.
workspace; % Make sure the workspace panel is showing
fontSize = 15;
mask = imread('image.bmp');
mask = mask(:, :, 1) > 0;
hFig = figure;
subplot(2, 1, 1);
imshow(mask);
hold on;
hFig.WindowState = 'maximized';
[rows, columns] = size(mask)
distances = zeros(1, columns);
distances2 = zeros(1, columns);
for col = 1 : columns
thisColumn = mask(:, col);
props = regionprops(thisColumn, 'Centroid', 'PixelList');
if length(props) == 2
% Only two regions which is what we need.
% Get the center of the thick top line.
yCentroid = props(1).Centroid(2);
yTop = props(1).PixelList(1,2);
% Get the top of the bottom region.
yTop2 = props(2).PixelList(1,2);
distances(col) = abs(yTop2 - yCentroid);
distances2(col) = abs(yTop2 - yTop);
line([col, col], [yTop, yTop2], 'Color', 'r');
end
end
subplot(2, 1, 2);
plot(distances, 'b-', 'LineWidth', 2);
hold on;
plot(distances2, 'r-', 'LineWidth', 2);
xlim([1, columns]);
grid on;
xlabel('Column', 'FontSize', fontSize);
ylabel('Distance', 'FontSize', fontSize);
legend('Distance from Centroid', 'Distance between tops');
Prashant
on 16 Jul 2020
Edited: Prashant
on 16 Jul 2020
1 Comment
Image Analyst
on 16 Jul 2020
You need to clear that border with imclearborder. My code looks for exactly 2 regions but if you have that white border all around, then the columns with the two regions are not the places you want. They'll be the placed with no blob and just the places with the white frame. Why is there a white frame around your image anyway?
Prashant
on 16 Jul 2020
39 Comments
Image Analyst
on 1 Oct 2020
I'd sum the inverted image vertically to get the horizontal profile, and then look for peaks.
horizontalProfile = sum(255 - grayImage);
plot(horizontalProfile, 'b-', 'LineWidth', 2);
grid on;
[peakValues, peakLocations] = findpeaks(horizontalProfile);
plot(peakLocations, peakValues, 'rv', 'MarkerSize', 15, 'LineWidth', 2);
See Also
Categories
Find more on Computer Vision with Simulink in Help Center and File Exchange
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!