GNU Octave:霍夫变换 [英] GNU Octave: Hough Transform

查看:95
本文介绍了GNU Octave:霍夫变换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用hough变换,不幸的是,它似乎并未输出与所绘制的线条相对应的r和theta.我一直在尝试在本网站和其他网站上找到答案,但是到目前为止,我尝试过的所有方法都失败了.

I am attempting to use a hough transform, unfortunately it doesn't seem to be outputting r and theta that correspond with the lines Drawn. I've been trying to find the answer on this site and others but everything I've tried so far has failed.

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)

推荐答案

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

The houghtf function in Octave parameterizes a line as

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

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

The output is an NxM matrix where the first dimension represents r and the second one theta.

r参数上的文档不太清楚.它只表示N = 2*diag_length - 1,图像的对角线长度为diag_length.但是,它甚至都不会告诉您来源.经过一些实验,我发现原点位于(N-1)/2.因此,在索引(iijj)上找到峰值之后,

The documentation is not very clear on the r parameter. All it says is that N = 2*diag_length - 1, with diag_length the diagonal length of the image. But it doesn't even tell you where the origin is. After some experimentation, I found that the origin is at (N-1)/2. Thus, after finding a peak at indices (ii,jj),

r = ii - (size(hough,1)-1)/2;

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

The theta parameter is described much better in the documentation: the bin returned corresponds to the values given in the input. So theta is the index into the array pi*[0:360]/180 that you pass to houghft. You can write:

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

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

Do note that the Hough transform deals with the orientation of the line, not the direction of the line. You can parameterize the same line using theta or theta+180. Thus, the hough image produced by the code above is redundant, with all orientations repeated twice (actually, the result for orientation 0 degrees is repeated twice, at 180 and 360 degrees). Instead, use

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

接下来,简单地对Hough变换进行阈值处理并获取所有像素并不是最佳方法:某些峰会更强,导致领结状的检测,您只想使用最高点即可. bwmorph函数的'shrink'方法是一种快速简便的方法,可将阈值后的检测减少到单个点,但不能保证它位于最高点.还要注意,对于0度的线,领结在图像的边缘处被切成两半,而另一半则以179度角出现.这需要花费额外的精力进行修复.在下面,我通过扩展angles并消除重复的点来对其进行修复.

Next, simply thresholding the Hough transform and getting all pixels is not the best approach: some peaks will be much stronger, leading to bow-tie--shaped detections, of which you'll want to use only the highest point. The 'shrink' method of the bwmorph function is a quick-and-dirty way of reducing the detections after the threshold to a single point, but it's not guaranteed to be on the highest point. Note also that for lines at 0 degrees, the bow-tie is cut in half at the edge of the image, with the other half appearing back at angle 179 degrees. This requires extra effort to fix. Below, I fixed it by extending angles a bit, and then removing duplicate points.

最后,在对线进行参数化时,似乎Octave选择x作为拳头索引,选择y作为图像的第二个索引,这与imshow的操作相反.

Finally, when parameterizing the line, it seems that Octave picks x as the fist index and y as the second index into the image, which is opposite of what imshow does.

将所有内容放在一起,我们得到:

Putting it all together, we get:

% 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!

对角线偏离了一个像素,因为我们检测到它们的方式.我们从不寻找局部最大值的位置,而是将所有像素都超过阈值,然后在中间取点.

The diagonal lines are off by one pixel because the way we detected them. We never looked for the location of the local maximum, we took all pixels above a threshold and picked the point in the middle of that.

这篇关于GNU Octave:霍夫变换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆