使用霍夫变换选择直线

3
问题:使用Hough变换在图像中找到一条不必要的线。

enter image description here

我已经完成了以下工作:

  1. 应用方向滤波器分析12个不同方向,每个方向相对于另一个方向旋转15度。
  2. 应用阈值处理以获取12个二进制图像。

enter image description here

现在,我需要选择标记为黄色的这两个图像之一。因为这两个图像中的线条最突出。
我尝试了以下代码。它似乎没有起作用。
MATLAB 代码
    %   Read 12 images into workspace.
input_images  = {imread('1.png'),imread('2.png'),imread('3.png'),...
    imread('4.png'),imread('5.png'),imread('6.png'),...
    imread('7.png'),imread('8.png'),imread('9.png'),...
    imread('10.png'),imread('11.png'),imread('12.png')};

longest_line = struct('point1',[0 0], 'point2',[0 0], 'theta', 0, 'rho', 0);

for n=1:12
    %Create a binary image.
    binary_image = edge(input_images{n},'canny');

    %Create the Hough transform using the binary image.
    [H,T,R] = hough(binary_image);

    %Find peaks in the Hough transform of the image.
    P  = houghpeaks(H,3,'threshold',ceil(0.3*max(H(:))));

    %Find lines
    hough_lines = houghlines(binary_image,T,R,P,'FillGap',5,'MinLength',7);         
    longest_line = FindTheLongestLine(hough_lines, longest_line);
end


% Highlight the longest line segment by coloring it cyan.
plot(longest_line.point1, longest_line.point2,'LineWidth',2,'Color','cyan');

.

Relevant Source Code

function longest_line = FindTheLongestLine( hough_lines , old_longest_line)
%FINDTHELONGESTLINE Summary of this function goes here
%   Detailed explanation goes here
    longest_line = struct('point1',[0 0] ,'point2',[0 0],'theta', 0, 'rho', 0);

    max_len = 0;

    N = length(hough_lines);

    for i = 1:N
       % Determine the endpoints of the longest line segment
       len = LenthOfLine(hough_lines(i));

       if ( len > max_len)
          max_len = len;
          longest_line = hough_lines(i);
       end
    end

    old_len = LenthOfLine(old_longest_line);
    new_len = LenthOfLine(longest_line);

    if(old_len > new_len)
       longest_line =  old_longest_line;
    end
end

function length = LenthOfLine( linex )
%LENTHOFLINE Summary of this function goes here
%   Detailed explanation goes here

    length = norm(linex.point1 - linex.point2);
end

测试图片

这里有12张图片,drive.google.com/open?id=0B-2FDw63ZNTnRnEzYlNyS0V4YVE


1
你可以解释一下你的代码问题和/或提供的答案吗? - m7913d
@m7913d,我的代码无法选择所需的特定行。我也无法使给出的答案起作用。 - user366312
你的算法输出是什么?您能够分别上传二进制图像吗?与其寻找最长的线,选择霍夫变换值最高的线可能更为有用。 - m7913d
可能是个小问题,我不确定是否只有标题错误,但如果你的角度是 pi/1, pi/2, pi/3, ..., pi/12,那么你并没有旋转15°。相反,你应该使用 pi*(1/12), pi*(2/12), pi*(3/12), ..., pi*(12/12)。此外,“我无法使给定的答案起作用”这句话非常含糊。它似乎正好做到了你想要的,所以请向我们展示你是如何实现它的,以及为什么它不起作用。 - Wolfie
2个回答

1
你可以根据你的具体问题尝试更改Hough函数的参数,这不是一个完美的解决方案,但可能对你有足够好的效果:
img = im2double(rgb2gray(imread('line.jpg')));
% edge image
BW = edge(img,'canny');
% relevant angles (degrees) interval for the line you want
thetaInterval = -80:-70;
% run hough transform and take single peak
[H,T,R] = hough(BW,'Theta',thetaInterval);
npeaks = 1;
P = houghpeaks(H,npeaks);
% generate lines
minLen = 150; % you want the long line which is ~250 pixels long
% merge smaller lines (same direction) within gaps of 30 pixels
fillGap = 30; 
lines = houghlines(BW,T,R,P,'FillGap',fillGap,'MinLength',minLen );
% plot
imshow(img);
hold on
xy = [lines.point1; lines.point2];
plot(xy(:,1),xy(:,2),'g','LineWidth',2);

enter image description here


你能否详细解释一下你的代码?我的意思是,更改参数背后的原理。 - user366312
我使用了霍夫变换,类似于这里,但使用了不同的参数。参数值背后的逻辑在注释中有解释(当然,一些具体值是通过几次试验确定的)。 - user2999345
我认为,这段代码对于不同的图像可能无法正常工作。 - user366312
这些是根据 hough 中角度定义的期望角度。 - user2999345
如果不同的图像具有不同的线方向,那么它肯定不起作用。问题是,您可以通过迭代几个可能的方向来实现,就像您在原始代码中所做的那样。 - user2999345
显示剩余2条评论

1
你的代码问题在于 houghlinesFillGap 属性。你应该允许更大的间隙返回线条,因为搜索到的线条不需要连续,例如 500:
hough_lines = houghlines(binary_image,T,R,P,'FillGap',500,'MinLength',7);

这将找到图像7中最长的线。
可使用以下代码将找到的直线绘制在图像上方。
figure
imshow(input_images{7});
hold on
% Highlight the longest line segment by coloring it cyan.
plot([longest_line.point1(1) longest_line.point2(1)], [longest_line.point1(2) longest_line.point2(2)],'LineWidth',2,'Color','cyan');

enter image description here

在霍夫变换中找到最大峰值

作为替代方案,您可以考虑选择与最大霍夫变换值对应的直线,而不是最长的直线。这可以通过以下方式选择longest_line来完成:

longest_line = ...
largest_H = 0; % init value

for n=1:12
    binary_image = edge(input_images{n},'canny');
    [H,T,R] = hough(binary_image);
    P  = houghpeaks(H,1,'threshold',ceil(0.3*max(H(:))));
    hough_lines = houghlines(binary_image,T,R,P,'FillGap',500,'MinLength',7);         

    if (largest_H < H(P(1, 1), P(1, 2)))
        largest_H = H(P(1, 1), P(1, 2));
        longest_line = hough_lines(1);
        longest_line.image = n;
    end
end

这将选择图像6中的以下行,这是另一个允许的结果:

enter image description here


在第二种情况下,如果我只选择一个峰值,我需要这样做吗?因为如果我只选择一个峰值,最大的峰值会自动被选择。是这样吗?例如,我可以写:peaks_count=1; P = houghpeaks(H, peaks_count, 'threshold', ceil(0.3*max(H(:))));,然后不再搜索最大的霍夫值吗? - user366312
不行,因为你想要在所有图像中找到最大的峰值。 - m7913d
请问您能否把您的第二段代码稍微讲得清楚一些?我已经接近成功了。 - user366312
我还是应该使用 peaks_count=1 吗? - user366312
我扩展了我的第二个方法。peaks_count的值并不重要,但是1足以满足需求,并且可能更有效率。 - m7913d

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接