问题描述
我正在尝试使用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
.因此,在索引(ii
,jj
)上找到峰值之后,
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);
请注意,霍夫变换处理的是线的方向,而不是线的方向.您可以使用theta
或theta+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:霍夫变换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!