如何实现基于梯度的霍夫变换

信息处理 图像处理 边缘检测
2021-12-27 13:33:13

我正在尝试使用霍夫变换进行边缘检测,并希望使用渐变图像作为基础。

到目前为止,我所做的,给定I大小的图像[M,N]及其偏导数gxgy,是计算每个像素中的梯度角为thetas = atan(gy(x,y) ./ gx同样,我将梯度幅度计算为magnitudes = sqrt(gx.^2+gy.^2)

为了构建霍夫变换,我使用以下 MATLAB 代码:

max_rho = ceil(sqrt(M^2 + N^2));
hough = zeros(2*max_rho, 101);
for x=1:M
    for y=1:N
        theta = thetas(x,y);
        rho = x*cos(theta) + y*sin(theta);

        rho_idx = round(rho)+max_rho;
        theta_idx = floor((theta + pi/2) / pi * 100) + 1;
        hough(rho_idx, theta_idx) = hough(rho_idx, theta_idx) + magnitudes(x,y);
    end
end

生成的霍夫变换看起来是合理的(参见http://i.stack.imgur.com/hC9mP.png),但是当我尝试使用它的最大值作为原始图像中的边缘参数时,结果看起来或多或少是随机的。我在构造霍夫变换时做错了什么吗?

更新:我的代码中有一个愚蠢的错误:rho计算为x*cos(theta)+y*cos(theta)而不是x*cos(theta)+y*sin(theta). 也就是说,我使用了两个余弦而不是余弦和正弦。我已经编辑了上面的代码,新的结果图像在下面。不过,这并没有带来更好的优势。

hough@endolith:要绘制一条边,给定 -matrix at的最大值rho_idx, theta_idx,我将索引转换为rho,theta值:

theta = (theta_idx -1) / 100 * pi - pi / 2;
rho = rho_idx - max_rho;

最后我将边缘绘制为y= (rho - x*cos(theta)) / sin(theta).

新结果

2个回答

我不知道这是否是一个问题,但由于象限模糊,atan() 只能给你从 -90 到 +90 度的角度。要获得完整的渐变角度(从 -180 到 180),您需要使用 atan2()。

我对你的问题有点困惑。霍夫变换用于检测线条,而不是边缘。

如果你想要的只是一个边缘图,你应该简单地阈值梯度幅度,或者使用像 Canny 边缘检测器这样更花哨的东西。

如果要检测直线,最好从边缘图开始,然后使用hough图像处理工具箱中的功能,如果您可以访问它。对梯度进行霍夫变换的问题是形成直线的边缘像素可能具有相反的梯度方向。例如,考虑一个棋盘图案。两排正方形之间的边会翻转方向,具体取决于您上方是黑色正方形,下方是白色正方形,还是相反。

至于你的实现,我认为问题在于你的霍夫矩阵中的箱子太小了。本质上,rho 维度中的 bin 大小为 1,而 theta 维度中的 bin 大小小于 2 度。这意味着梯度方向必须非常精确地下降以形成一条线,这在实践中很少发生。如果您计算 rho_idx 和 theta_idx 以使 bin 更大,这将使您的线路检测器更能容忍错误,并且您可能会得到更好的线路。