Hough transform incorrectly identifying vertical line segments

17 views (last 30 days)
Hello everyone,
I am trying to measure the lengths of several sequences of vertical line segments. Please see the attached image, "sample_image.jpg," for these sequences. I thought to implement the Hough transform to measure these line segments. The code included at the bottom of this comment contains the implementation. I changed it slightly from the MATLAB reference page regarding the Hough transform, most notably in the way a binary image is generated via edge detection. The fact that these are all 1-pixel lines simplifies the process. However, as seen in the below image, the implementation makes mistakes. The Hough transform incorrectly places lines in midair, and incorrectly assigns multiple lines to just one line.
I am not very experienced with implementing the Hough transform, and am unsure where I'm going wrong. Any assistance would be greatly appreciated!
The code:
fname='sample_image.jpg';
I=imread(fname);
% extremely simple edge finder -- edges are only one pixel wide so all pixels
% with values less than max unit8 value (white) are edges
BW=I<max(I(:));
% Hough transform
[H,theta,rho] = hough(BW);
figure
imshow(imadjust(rescale(H)),[],...
'XData',theta,...
'YData',rho,...
'InitialMagnification','fit');
xlabel('\theta (degrees)')
ylabel('\rho')
axis on
axis normal
hold on
colormap(gca,hot)
%keep max# of peaks overly large to keep script applicable to future images where number of lines is unknown a priori
P = houghpeaks(H,1e6,'threshold',ceil(0.3*max(H(:))));
x = theta(P(:,2));
y = rho(P(:,1));
plot(x,y,'s','color','black');
lines = houghlines(BW,theta,rho,P,'FillGap',2,'MinLength',7); %aggressive fillgap exclusion
figure, imshow(I), hold on
max_len = 0;
for k = 1:length(lines)
xy = [lines(k).point1; lines(k).point2];
plot(xy(:,1),xy(:,2),'LineWidth',2,'Color','green');
% Plot beginnings and ends of lines
plot(xy(1,1),xy(1,2),'x','LineWidth',2,'Color','yellow');
plot(xy(2,1),xy(2,2),'x','LineWidth',2,'Color','red');
% Determine the endpoints of the longest line segment
len = norm(lines(k).point1 - lines(k).point2);
if ( len > max_len)
max_len = len;
xy_long = xy;
end
end
% highlight the longest line segment
plot(xy_long(:,1),xy_long(:,2),'LineWidth',2,'Color','red');

Answers (2)

Constantino Carlos Reyes-Aldasoro
Have you tried inverting the intensities of the image? As it is, white is the main element and that will be difficult to obtain the lines, say that your image i
newimage = max(sample_image(:))- sample_image;
and then apply the hough transform
  1 Comment
Nathaniel Wood
Nathaniel Wood on 17 May 2022
Inverting the binary image intensity,
BW=I<max(I(:));
BW=max(BW(:))-BW; %invert intensity
does indeed makes lines easier to find. In fact, it generates the opposite problem as before. Leaving all other hyperparameters in the code unchanged, save reducing the max# of Hough peaks from 1e6 to 1e3, the Hough transform now incorrectly identifies 11,833 lines.
Having counted the lines manually, there are about 160. Is there something about the way this transform works that I'm not understanding, which would lead to this problem being ill-posed? Is there an alternate means of detecting lines and measuring their lengths besides the Hough transform that would be more appropriate for this application?

Sign in to comment.


Constantino Carlos Reyes-Aldasoro
Ok, 2 things, you are first comparing and then subtracting, which may be counteracting, you could calculate hough directly like this:
[H,T,R] = hough(255-sample_image);
Now, where I think the problem lies is the following line
P = houghpeaks(H,1e6,'threshold',ceil(0.3*max(H(:))));
Second parameter is the number of peaks to be found, you should give a number that is in the range of what you want to see, if there are 8 lines, then 10-20 could be good, you are using 1e6, so actually asking to find a million peaks! Try changing that number and see what happens.
  1 Comment
Nathaniel Wood
Nathaniel Wood on 17 May 2022
The reason I inverted the image with the command
BW=max(BW(:))-BW;
Is because it had already been converted into a binary image of 0s and 1s. This was done in the tutorial via the edge() command, but I accomplished the same effect with a simple logical check due to the simplistic nature of the image contents. Since it's just an image of 0s and 1s, all the above command does is flip which entries are 1 and which are 0. I could have done it even simpler with BW=~BW;, but it didn't occur to me. Is the fact that the image is binary what's causing problems? Even if I kept it in the original uint8 grayscale format, it would still just alternate between min and max values.
Also, I reduced the max peak number from 1000 to 200, giving the command the form
P = houghpeaks(H,2e2,'threshold',ceil(0.3*max(H(:)))); %large max# of peaks for generality
Which yields 200 identified peaks. However, the houghlines() command incorrectly identifies 358 lines. I'm not sure what's going wrong with it
lines = houghlines(BW,theta,rho,P,'FillGap',2,'MinLength',7); %aggressive fillgap exclusion
I set 'FillGap' as 2 because I constructed the lines to be only 1 pixel wide in photoshop. Setting this to the tutorial-default value of 5 didn't fix the issue either.

Sign in to comment.

Products


Release

R2019b

Community Treasure Hunt

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

Start Hunting!