GNU Octave:Hough变换

时间:2018-01-11 00:25:20

标签: octave hough-transform

我试图使用霍夫变换,不幸的是它似乎没有输出与绘制线对应的r和theta。我一直试图在这个网站和其他网站上找到答案,但到目前为止我尝试过的所有内容都失败了。

I=zeros(80, 80);
for n=1:25;
  I(n+20, n+2)=1;
  I(n+1, n*2+17)=1;
  I(n+1, n*2+16)=1;
  end

hough = houghtf(I,"line", pi*[0:360]/180);
threshHough = hough>.9*max(hough(:));
[r, theta] = find(threshHough>0)
%theta = (theta-91)*pi/180
%r=r-size(hough,1)/2

imshow(I)

1 个答案:

答案 0 :(得分:2)

Octave中的houghtf函数将行参数化为

r = x*cos(theta) + y*sin(theta)

输出是NxM矩阵,其中第一个维度代表r,第二个维度代表theta

r参数上的documentation不是很清楚。它只是N = 2*diag_length - 1diag_length图像的对角线长度。但它甚至没有告诉你原点在哪里。经过一些实验,我发现起源位于(N-1)/2。因此,在索引(iijj),

找到峰值后
r = ii - (size(hough,1)-1)/2;

在文档中更好地描述了theta参数:bin返回对应于输入中给出的值。因此theta是您传递给pi*[0:360]/180的数组houghft的索引。你可以写:

angles = pi*[0:360]/180;
theta = angles(jj);

请注意,霍夫变换处理线的方向,而不是线的方向。您可以使用-thetatheta对同一行进行参数化。因此,由上面的代码产生的hough图像是多余的,所有方向重复两次(实际上,方向0度的结果重复两次,在180度和360度)。相反,使用

angles = pi*[0:179]/180;

接下来,简单地对Hough变换进行阈值处理并获得所有像素并不是最好的方法:一些峰会更强,导致蝴蝶结形状的检测,其中您只想使用最高点。 'shrink'函数的bwmorph方法是将阈值之后的检测减少到单个点的快速而肮脏的方法,但不能保证在最高点。另请注意,对于0度的线条,蝴蝶结在图像边缘处被切成两半,另一半以179度角度向后显示。这需要额外的努力来解决。下面,我通过稍微扩展angles来修复它,然后删除重复点。

最后,在对线进行参数化时,似乎Octave选择x作为第一个索引而y作为第二个索引进入图像,这与imshow的作用相反。

总而言之,我们得到:

% Create test image with some lines
I = zeros(80, 80);
for n=1:25;
  I(n+20,n+2) = 1;
  I(n+1,n*2+17) = 1;
  I(n+1,n*2+16) = 1;
end
I(34:73,55) = 1;
I(60,15:64) = 1;

% Compute the Hough transform
angles = pi*[-10:189]/180;
hough = houghtf(I,"line",angles);

% Detect maxima in the Hough transform -- this is a bit of a hack
detect = hough>.5*max(hough(:));
detect = bwmorph(detect,'shrink',inf);
[ii, jj] = find(detect);
r = ii - (size(hough,1)-1)/2;
theta = angles(jj);

% Remove duplicate points by deleting any point with an angle 
% outside of the interval [0,180).
dup = theta<-1e-6 | theta>=pi-1e-6;
r(dup) = [];
theta(dup) = [];

% Compute line parameters (using Octave's implicit singleton expansion)
r = r(:)';
theta = theta(:)';
x = repmat([1;80],1,length(r)); % 2xN matrix, N==length(r)
y = (r - x.*cos(theta))./sin(theta); % solve line equation for y
% The above goes wrong when theta==0, fix that:
horizontal = theta < 1e-6;
x(:,horizontal) = r(horizontal);
y(:,horizontal) = [1;80];

% Plot
figure
imshow(I)
hold on
plot(y,x,'r-','linewidth',2) % note the reversed x and y!

enter image description here

对角线偏离了一个像素,因为我们检测它们的方式。我们从未查找局部最大值的位置,我们将所有像素都置于阈值以上并选择了中间点。