霍夫变换-霍夫直线检测、霍夫圆检测

霍夫直线检测

对于直线检测来说, 所谓的霍夫变换可以理解为一种映射关系,(theta, r)与直线 y = kx + b的映射关系。且这种映射为一对一的映射。

极坐标系下的参数空间

霍夫变换-霍夫直线检测、霍夫圆检测_第1张图片

则对于直线l上任意一点Q而言,我们有:
霍夫变换-霍夫直线检测、霍夫圆检测_第2张图片

联立(1)、(2)式,可求得点Q在极坐标系下的参数空间方程
霍夫变换-霍夫直线检测、霍夫圆检测_第3张图片
这样我们就可以实现极坐标系与参数空间之间的映射
霍夫变换-霍夫直线检测、霍夫圆检测_第4张图片
这样就把在图像空间中检测直线的问题转化为在极坐标参数空间中找通过点(r,θ)的最多正弦曲线数的问题。霍夫空间中,曲线的交点次数越多,所代表的参数越确定,画出的图形越饱满。

霍夫变换直线检测步骤示例霍夫变换-霍夫直线检测、霍夫圆检测_第5张图片

总结使用霍夫变换检测直线具体步骤

  1. 彩色图像->灰度图
  2. 去噪(高斯核)
  3. 边缘提取(梯度算子、拉普拉斯算子、canny、sobel)
  4. 二值化(判断此处是否为边缘点,就看灰度值==255)
  5. 映射到霍夫空间(准备两个容器,一个用来展示hough-space概况,一个数组hough-space用来储存voting的值,因为投票过程往往有某个极大值超过阈值,多达几千,不能直接用灰度图来记录投票信息)
  6. 取局部极大值,设定阈值,过滤干扰直线
  7. 绘制直线、标定角点

相关API实现

(1) 标准霍夫线变换 - HoughLines
HoughLines(
InputArray src, // 输入图像,必须8-bit的灰度图像
OutputArray lines, // 输出的极坐标来表示直线
double rho, // 生成极坐标时候的像素扫描步长,一般取1,极坐标空间 r 的最大值
double theta, //生成极坐标时候的角度步长,一般取值0~180度的角度每次扫描1度就是ni.PI/180
int threshold, // 阈值,只有获得足够交点的极坐标点才被看成是直线
double srn=0;// 是否应用多尺度(图像金字塔)的霍夫变换,如果不是设置0表示经典霍夫变换,默认
double stn=0;//是否应用多尺度的霍夫变换,如果不是设置0表示经典霍夫变换,默认
double min_theta=0; // 表示角度扫描范围 0 ~180之间, 默认即可double max_theta=CV_PI // 表示角度扫描范围 0 ~180之间, 默认
(2) 概率霍夫线变换 - HoughLinesP
这是执行起来效率更高的概率霍夫线变换(probabilistic Hough ),它输出检测到的直线的端点 。
HoughLinesP(
InputArray src, // 输入图像,必须8-bit的灰度图像
OutputArray lines, // 输出的极坐标来表示直线
double rho, // 生成极坐标时候的像素扫描步长,一般取1
double theta, //生成极坐标时候的角度步长,一般取值ni.PI/180
int threshold, // 阈值,只有获得足够交点的极坐标点才被看成是直线,可以写10
double minLineLength=0;// 最小直线长度
double maxLineGap=0;// 两交点间允许的最大间隔,(经canny的梯度可能不连续,间隔调大)
HoughLinesP函数就是利用概率霍夫变换来检测直线的。它的一般步骤为:

  1. 随机抽取图像中的一个特征点,即边缘点,如果该点已经被标定为是某一条直线上的点,则继续在剩下的边缘点中随机抽取一个边缘点,直到所有边缘点都抽取完了为止;
  2. 对该点进行霍夫变换,并进行累加和计算;
  3. 选取在霍夫空间内值最大的点,如果该点大于阈值的,则进行步骤4,否则回到步骤1;
  4. 根据霍夫变换得到的最大值,从该点出发,沿着直线的方向位移,从而找到直线的两个端点;
  5. 计算直线的长度,如果大于某个阈值,则被认为是好的直线输出,回到步骤1。

霍夫圆检测

原理

从平面坐标圆上的点到极坐标转换的三个参数C(x0,y0,r)其中x0,y0是圆心,r 取一固定值时theta扫描360度,x y 跟着变化, 若多个边缘点对应的三维空间曲线交于一点,则他们在共同圆上,在圆心处有累积最大值,也可以用同样的阈值的方法来判断一个圆是否被检测到。
霍夫变换-霍夫直线检测、霍夫圆检测_第6张图片
圆变换的想法和直线变化是一样的,就是把直角坐标系中的圆画在极坐标系中,然后求交点。

霍夫变换圆检测步骤

第一阶段:检测圆心
1.1、对输入图像边缘检测;
1.2、计算图形的梯度,并确定圆周线,其中圆周的梯度就是它的法线;
1.3、在二维霍夫空间内,绘出所有图形的梯度直线,某坐标点上累加和的值越大,说明在该点上直线相交的次数越多,也就是越有可能是圆心;
1.4、在霍夫空间的4邻域内进行非最大值抑制;
1.5、设定一个阈值,霍夫空间内累加和大于该阈值的点就对应于圆心。
第二阶段:检测圆半径
2.1、计算某一个圆心到所有圆周线的距离,这些距离中就有该圆心所对应的圆的半径的值,这些半径值当然是相等的,并且这些圆半径的数量要远远大于其他距离值相等的数量;
2.2、设定两个阈值,定义为最大半径和最小半径,保留距离在这两个半径之间的值,这意味着我们检测的圆不能太大,也不能太小;
2.3、对保留下来的距离进行排序;
2.4、找到距离相同的那些值,并计算相同值的数量;
2.5、设定一个阈值,只有相同值的数量大于该阈值,才认为该值是该圆心对应的圆半径;
2.6、对每一个圆心,完成上面的2.1~2.5步骤,得到所有的圆半径。

相关API - HoughCircles

因为霍夫圆检测对噪声比较敏感,所以首先要对图像做滤波(模糊降噪)。(比如椒盐噪声用中值滤波,其他的也可以用高斯模糊)

基于效率考虑,Opencv中实现的霍夫变换圆检测是基于图像梯度(霍夫梯度法, 也叫2-1霍夫变换(21HT))的实现,分为两步(已封装到HoughCircles):

  1. Canny检测边缘,发现可能的圆心。圆心一定是在圆上的每个点的模向量上, 这些圆上点模向量的交点就是圆心, 霍夫梯度法的第一步就是找到这些圆心, 这样三维的累加平面就又转化为二维累加平面。
  2. 基于第一步的基础上从候选圆心开始计算最佳半径大小。第二步根据所有候选中心的边缘非0像素对其的支持程度来确定半径。

HoughCircles(
InputArray image, // 输入图像 ,必须是8位的单通道灰度图像,8位可以有4个通道,每个通道是8位,可以使RGB。
OutputArray circles, // 输出结果,发现的圆信息(数组)
Int method, // 选梯度方法 - HOUGH_GRADIENT
Double dp, // dp = 1,原图尺度(2的话比原图小一半来寻找,速度快了)
Double mindist, // 10 两个圆心最短距离
Double param1, // canny边缘检测的低阈值canny edge detection low threshold
Double param2, // 中心点累加器阈值
Int minradius, // 圆最小半径
Int maxradius//圆最大半径(范围越大,速度越慢)

你可能感兴趣的:(计算机视觉,图像处理)