How to fitline on my binary image and find distance

11 views (last 30 days)
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.

Accepted Answer

Image Analyst
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);

More Answers (3)

Image Analyst
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
Prashant
Prashant on 16 Jul 2020
Edited: Prashant on 16 Jul 2020
Hello Image Analyst,
I have one more problem in the different image. Could you please have a look. I am attaching the image name carlight.jpg
I want to measure the distance automatically as shown in fig, i want to find the distance from the laser light and the curve or as shown in fig. could you please help me how to write code.
thank you.
Image Analyst
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');

Sign in to comment.


Prashant
Prashant on 16 Jul 2020
Edited: Prashant on 16 Jul 2020
Hello Image Analyst,
Thank you for your answer.
I have tried your code but i can not get the result which i have shown in fig. Also by using mask my image is become inaccurate for example the edge of the image surface is blurred.
I want to find the distance in cm or whatever the unit. But i don't know that how can i select that particular region.
Could you please write code for me with the explaination. the image is in attached name binary.jpg.
  1 Comment
Image Analyst
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?

Sign in to comment.


Prashant
Prashant on 16 Jul 2020
As you know that this image is from Headlight. I have made a photo with my camera and it is look like this in attched image name ''DSC_2637.png ''. So i have convert the image in binary then i got the image like attached image called ''binary.jpg ''.
Now i want to see that how can i get that distance of that marked region.
could you please write that code for me?
  39 Comments
Prashant
Prashant on 1 Oct 2020
Edited: Prashant on 1 Oct 2020
Hi image analyst,
I need any two vertical line (one near to other) and the rest i do not want. I need the distance between those two line so i can use it for my calibration code which can measure my object with reference to this two line distance measurement. so that is why i need this distance value in pixel. I know the real world distance is 100 cm between two vertical line. for example you gave me a code for counting number of pixels of square block in checkerboard like tha same way i want to find for this image.
this image is original one that i posted.
Image Analyst
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);

Sign in to comment.

Community Treasure Hunt

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

Start Hunting!