Octave GNU倍频程:霍夫变换

Octave GNU倍频程:霍夫变换,octave,hough-transform,Octave,Hough Transform,我尝试使用hough变换,不幸的是,它似乎没有输出与绘制的线对应的r和θ。我一直试图在这个网站和其他网站上找到答案,但迄今为止我所尝试的一切都失败了 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(:)

我尝试使用hough变换,不幸的是,它似乎没有输出与绘制的线对应的r和θ。我一直试图在这个网站和其他网站上找到答案,但迄今为止我所尝试的一切都失败了

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)

八度音阶中的
houghtf
函数将线参数化为

r = x*cos(theta) + y*sin(theta)
输出是一个NxM矩阵,其中第一个维度表示
r
,第二个维度表示
theta

关于
r
参数的信息不是很清楚。它所说的就是
N=2*diag_length-1
,其中
diag_length
是图像的对角线长度。但它甚至没有告诉你起源在哪里。经过一些实验,我发现原点位于
(N-1)/2
。因此,在指数(
ii
jj
)处找到峰值后

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

angles = pi*[0:360]/180;
theta = angles(jj);
请注意,Hough变换处理的是直线的方向,而不是直线的方向。您可以使用
theta
theta+180
参数化同一行。因此,由上述代码生成的
hough
图像是冗余的,所有方向重复两次(实际上,方向0度的结果在180度和360度重复两次)。相反,使用

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

最后,当参数化线条时,似乎倍频程选择
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!
%使用一些行创建测试映像
I=零(80,80);
n=1:25时;
I(n+20,n+2)=1;
I(n+1,n*2+17)=1;
I(n+1,n*2+16)=1;
结束
I(34:73,55)=1;
I(60,15:64)=1;
%计算Hough变换
角度=pi*[-10:189]/180;
hough=houghtf(I,“线”,角度);
%在Hough变换中检测最大值——这有点麻烦
检测=霍夫>最大.5*霍夫(:);
detect=bwmorph(detect,'shrink',inf);
[ii,jj]=查找(检测);
r=ii-(尺寸(hough,1)-1)/2;
θ=角度(jj);
%通过删除具有角度的任何点来删除重复点
%在间隔[0180]之外。
dup=θ=π-1e-6;
r(dup)=[];
θ(dup)=[];
%计算线参数(使用倍频程的隐式单态展开)
r=r(:)';
θ=θ(:)';
x=repmat([1;80],1,长度(r));%2xN矩阵,N==长度(r)
y=(r-x.*cos(θ))/sin(θ);%解y的线方程
%当θ==0时,上述错误出现,请修复:
水平=θ<1e-6;
x(:,水平)=r(水平);
y(:,水平)=[1;80];
%密谋
图形
imshow(I)
等等
绘图(y,x,'r-','linewidth',2)%x和y方向相反!


对角线是由一个像素关闭的,因为我们检测到它们的方式。我们从不寻找局部最大值的位置,我们把所有的像素都取在一个阈值之上,并选择中间的点。

@ McLay:不要忘记应该索引<代码> i(y,x)。进入图像。MATLAB和倍频程在第一个索引中索引矩阵行,但它们通常称为
x
水平轴(第二个索引).奇怪,我知道!我不知道为什么你在Hough变换中看到4个点,我不知道你的图像是什么样子。但是如果
find
为每个索引返回两个值,那么只有2个像素高于你的阈值。同样,第二个索引是x,但x仍然是水平的…完全令人困惑,我知道!在任何情况下,垂直线的角度为pi/2。它还有一个3pi/2的角度,因为你可以在同一条线上上下移动。这条线有方向,但没有方向。如果你显示你的
hough
图像,你会看到两半是相同的。你应该只计算一半!设置
angles=pi*[0:179]/180
以防止方向重复。@麦卡利:你说得对。我没有想到
r
参数需要正负值。我做了一些实验,找到了
r
的正确公式。请参阅更新的答案。@麦卡利:我想我发现了问题:x轴和y轴似乎颠倒了。我已将答案修改为also在图像上画线,这样您就可以看到它应该是如何完成的。我对糟糕的文档以及与
hough
函数的不一致性感到惊讶。MATLAB更擅长文档,但它没有
houghtf
函数。:)
% 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!