一、霍夫变换基本原理

霍夫变换的核心思想是:将笛卡尔坐标系中的边缘像素点,映射到霍夫空间中,通过“投票机制”寻找局部最大值,从而提取出几何形状如直线、圆。

以最基础的直线检测为例:

1、在图像空间中,一条直线的方程可以写成极坐标形式: 。

2、图像空间中的一个点 代入上述方程后,在参数空间 中就变成了一条正弦曲线。

3、如果图像空间中有多个点共线,那么这多个点在参数空间中对应的多条正弦曲线,必然会相交于同一点。

4、算法会在参数空间中建立一个二维数组。曲线每经过一个点,该点的计数值加 1。最后寻找计数值最高的峰值点将其反代回图像空间,就得到了直线的方程。

二、检测圆形的基本原理

圆的解析方程为: ,其中有圆心坐标 (a,b) 和半径 𝑟。

当圆的半径 r 已知时,对于图像中通过边缘检测器(如Canny)提取出的每一个边缘点,由于r已知,它在参数空间(a,b)中对应的方程为: ,这在参数空间中也是一个圆,也就是说,图像空间中属于同一个真实圆的边缘点,它们在参数空间中画出的所有圆,都会相交于一点,这个交点就是真实圆的圆心。

当圆的半径 r 未知时,此时参数空间变成了三维 (a,b,r)。图像空间中的一个边缘点,在三维参数空间中对应的是一个圆锥面。计算所有边缘点的圆锥面相交点,计算量极其巨大,极其耗时。

为了解决计算量问题,MATLAB和OpenCV等图像库实际上使用的是优化的“霍夫梯度法”,分为两步:

找圆心: 对于图像上的每个边缘点,计算其梯度方向。几何学上,圆的法线一定经过圆心。因此,沿着边缘点的梯度方向在二维累加器中“画线”投票,这些线相交最多的地方就是圆心。

定半径: 找到圆心后,计算边缘图上的非零像素点到圆心的距离。出现频率最高的那几个距离,就被判定为该圆的半径。

三、代码示例

MATLAB 提供了内置函数 imfindcircles 来实现基于霍夫变换的圆检测。以下是一段可以直接运行的完整示例代码,使用了MATLAB自带的硬币图像:

% 使用 MATLAB 自带的测试图像 coins.png

I = imread('coins.png');

if size(I, 3) == 3

    gray_img = rgb2gray(I);

else

    gray_img = I;

end

% 观察硬币图,大致估算半径在 15 到 30 像素之间

Rmin = 15;

Rmax = 30;

% 使用霍夫变换(imfindcircles)寻找圆

% 'ObjectPolarity', 'bright':表示我们要找的圆(硬币)比背景亮

% 'Sensitivity':灵敏度(0到1),值越大越容易检测出圆,但设得太高容易产生误检(假圆)

[centers, radii, metric] = imfindcircles(gray_img, [Rmin Rmax], ...

                                         'ObjectPolarity', 'bright', ...

                                         'Sensitivity', 0.90);

% 可视化结果

figure;

imshow(I); % 显示原图

title('霍夫变换检测圆形结果');

hold on;

% 在原图上绘制检测到的圆边界(蓝色)

viscircles(centers, radii, 'EdgeColor', 'b');

% 在圆心位置画红色的十字

plot(centers(:,1), centers(:,2), 'r+', 'MarkerSize', 10, 'LineWidth', 2);

hold off;

 

Logo

CANN开发者社区旨在汇聚广大开发者,围绕CANN架构重构、算子开发、部署应用优化等核心方向,展开深度交流与思想碰撞,携手共同促进CANN开放生态突破!

更多推荐