How to properly detect the edges of the rail surface for cropping?

3 views (last 30 days)
Hi, i have tried to use sobel edge detection and hough transform to detect the lines of the rail image and the cropping it after. However, it does not seem to be detecting the edges that i need. I want it to detect the rail edges of the image only, so i am able to crop it. Please see attached codes and imaged for reference. Please help. Thanks.
clc;
close all;
% Prompt User to get video file
[file,path] = uigetfile('*');
if isequal(file,0)
disp('User selected Cancel');
else
disp(['User selected ', fullfile(path,file)]);
end
%Reading of image
Img=imread(fullfile(path,file));
grayscale=rgb2gray(Img);
grayscale2=histeq(grayscale);
%Sobel Edge detection & filter weak edges.
DetectedEdges = edge(grayscale2,'sobel','horizontal');
FilteredImage = bwareaopen(DetectedEdges,60);
%Hough Transformation with Peak & Lines identification.
[H,theta,rho] = hough(DetectedEdges);
Peaks = houghpeaks(H,5,'threshold',ceil(0.6*max(H(:))));
Lines = houghlines(DetectedEdges,theta,rho,Peaks,'FillGap',10,'MinLength',100);
%Display Filtered Weak Edges & Draw Detected Lines on Grayscaled Frame.
figure('Name','Filtered Weak Edges & Lines Detection','NumberTitle','off');
subplot(2,1,1), imshow(FilteredImage);
subplot(2,1,2), imshow(grayscale2), hold on
%Identify Frame dimensions & line coordinates in both upper & lower rail edge.
[size_x,size_y] = size(grayscale2);
min_y = size_y;
max_y = 0;
%Set condition to determine upper & lower edge.
for k = 1:length(Lines)
xy = [Lines(k).point1;Lines(k).point2];
if xy(1,2) <= min_y
min_y = xy(1,2);
min_y_line = xy;
end
if xy(1,2) >= max_y
max_y = xy(1,2);
max_y_line = xy;
end
end
%Use straight line formula to determine y-intercepts & gradients.
min_y_gradient = (min_y_line(2,2) - min_y_line(1,2)) / (min_y_line(1,2) - min_y_line(1,1));
min_y_intercept = min_y_line(1,2) - min_y_gradient*min_y_line(1,1);
plot(min_y_line(:,1),min_y_line(:,2),'LineWidth',2,'Color','green');
max_y_gradient = (max_y_line(2,2) - max_y_line(1,2)) / (max_y_line(1,2) - max_y_line(1,1));
max_y_intercept = max_y_line(1,2) - max_y_gradient*max_y_line(1,1);
plot(max_y_line(:,1),max_y_line(:,2),'LineWidth',2,'Color','red');
hold off
%Note that 'hold on' in Line 45 retains plots in the current axes.
%Identify coordinates & crop out the area of interest.
topRow = min(min_y_line(:,2));
bottomRow = max(max_y_line(:,2));
croppedImage = grayscale2(topRow:bottomRow,:);
figure, imshow(croppedImage);
  2 Comments
Jun Han Tan
Jun Han Tan on 18 Oct 2021
Hi, thanks for the reply, yes the contrast is inconsistence which is why the threshold for the edge detection has to be change everytime i use a different frame. I have attached a few more images for reference. Yes i feel that fixed window for now is the best option, but im looking for a solution that can be flexible cropped according to where the rail surface is.

Sign in to comment.

Accepted Answer

Prachi Kulkarni
Prachi Kulkarni on 21 Oct 2021
Hi,
As I mentioned before, there are indeed many different approaches that can be taken to find the edges. Using the color information in the HSV color space was one approach. However, you can also detect the edges using Sobel edge detection.
Using the edge function with the Sobel method gives a binary image containing 1s where the function finds edges and 0s elsewhere. You can observe that there is a marked increase in the number of 1s near the required edges. This can be used to detect the edges as follows.
[file,path] = uigetfile('*');
if isequal(file,0)
disp('User selected Cancel');
else
disp(['User selected ', fullfile(path,file)]);
end
I=imread(fullfile(path,file));
figure, imshow(I);
BW = edge(rgb2gray(I),'Sobel');
profile = sum(BW,2)/size(I,2);
figure, plot(profile);
rows = find(profile > 0.11);
rows = rows([1 end]);
Icrop = I(rows(1):rows(2),:,:);
figure, imshow(Icrop);
This seems to work for all the images you have attached.
  2 Comments
Prachi Kulkarni
Prachi Kulkarni on 26 Oct 2021
Hi,
The vector profile contains the proportion of edge pixels in each row of the image. Currently, the threshold for profile is set to 0.11. This means that the first row where profile is above 0.11 is the top edge and the last row where profile is above 0.11 is the bottom edge. This is shown in the code as follows.
rows = find(profile > 0.11);
You can change the threshold value of 0.11 to make it suitable for all the images you have.

Sign in to comment.

More Answers (1)

Prachi Kulkarni
Prachi Kulkarni on 20 Oct 2021
Hi,
There can be many possible approaches to identifying the edges. One possible way would be to look at the image in HSV color space. The saturation values of the image show a significant increase near the required edges.
Here is a sample code to plot the sum of saturation values for each row in the image. The plot shows the required edges are near the peaks in the plot.
[file,path] = uigetfile('*');
if isequal(file,0)
disp('User selected Cancel');
else
disp(['User selected ', fullfile(path,file)]);
end
I=imread(fullfile(path,file));
figure, imshow(I);
Ihsv = rgb2hsv(I);
saturation = Ihsv(:,:,2);
figure, imshow(saturation);
saturationProfile = sum(saturation,2);
figure, plot(saturationProfile);
For more information about color spaces, please refer to the following documentation.
  2 Comments
Jun Han Tan
Jun Han Tan on 21 Oct 2021
Hi Prachi,
Thanks for the assist. But may i know whats the next step after changing to HSV colour space. After getting the plot and the saturated image, i tried to use sobel and hough to get the cropping but it still doesnt detect the edges. Is there an another way to do it?

Sign in to comment.

Community Treasure Hunt

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

Start Hunting!