您的位置首页生活百科

霍夫变换

霍夫变换

霍夫变换是一种 ,被广泛应用在 、 以及 。 霍夫变换是用来辨别找出物件中的特征,例如:线条。他的 流程大致如下,给定一个物件、要辨别的形状的种类,算法会在 中执行投票来决定物体的形状,而这是由累加空间(accumulator space)里的 来决定。

经典的霍夫变换用于检测图像中的直线,原理是利用坐标空间变换将两个坐标进行相应的转化,或通过直线映射到另一坐标空间的点形成的峰值,从而把检测任意形状的问题转化为统计峰值的问题。经典的霍夫变换的突出优点是分割结果的鲁棒性,其缺点是要求知道物体边界线的解析方程。学习一下霍夫变换的基本原理。

以直线检测为例,每个像素坐标点经过空间变换都变成对直线特质有贡献的统一度量。对于二维图像数据f(x,y),平面坐标为(x,y)极坐标(r,θ),如图所示:

图像中的一条直线就是图像中一系列离散像素点的集合,直线由平面坐标转换为极坐标方程为:

将笛卡尔坐标系转换到极坐霍夫变换空间,这种点到曲线的映射变换就被称为霍夫变换。

霍夫变换是基于图像二值化的变换,利用二值化图像中的点集来确定候选直线的集合。在图像的边界处可以用方程f(x,p) = 0表示任意的曲线,其中p为曲线的参数向量,那么利用霍夫变换进行line检测的算法步骤如下:

1. 在参数p的范围内量化参数空间,将霍夫空间坐标(r,θ)初始化为0

2. 在阈值化后的梯度图像中,对每个图像点(i,j)进行遍历,对于满足参数p,累计所有的f(x,p) = 0即S(p) = S(p)+△p.

3. 计算当前霍夫变换空间的S(p)的局部最大值,对应曲线f(x,p)=0 的解析实现。

在opencv中霍夫变换算法,可以使用HoughLines调用标准霍夫变换(SHT),多尺度霍夫变换(MSHT),MSHT为SHT在多尺度下的一个变种。而统计概率霍夫变换(PPHT)则使用HoughLinesP调用,PPHT是在一定范围内统计峰值,而不是整个平面,这样就减少了计算量。

PPHT是使用cv::HoughLinesP实现。其中HoughLinesP函数原型如下:

void cv :: HoughLinesP ( InputArray image , OutputArrat Lines , double rho , double theta , int threshold , double minLineLength = 0 , double maxLineGap = 0 )

参数说明:

image : 二值化的图像即单通道8bit的图像

lines : 输出线向量,每个线向量由(r,θ),r表示距离原点的距离,θ为角度。

rho : 以像素为单位的距离精度,直线搜索时的尺寸的单位半径。

theta : 弧度的精度,直线搜索时的尺寸的单位角度

threshold : 表示检测一条直线所需最少的交点。

minLength: 最小的直线长度

maxLineGap : 同一行点与点连接起来的最大距离

SHT和MSHT都是使用cv::HoughLines() ,函数原型如下:

void cv :: HoughLines ( InputArray Image , OutputArray lines , double rho , double theta , int threshold , double srn = 0 , double stn = 0 )

参数说明:

image : 二值化的图像即单通道8bit的图像

lines : 输出线向量,每个线向量由(ρ,θ),ρ表示距离原点的距离,θ为角度。

rho : 以像素为单位的距离精度,直线搜索时的尺寸的单位半径。

theta : 弧度的精度,直线搜索时的尺寸的单位角度

threshold : 表示检测一条直线所需最少的交点。

srn: 多尺度霍夫变换参数,距离分辨ρ因子

stn : 多尺度霍夫变换参数,距离分辨θ因子

代码示例如下:

#include #include #include int main ( int argc , char ** argv ) { cv :: Mat srcImage = cv :: imread ( argv [ 1 ]); if ( ! srcImage . data ) { std :: cout << "fail to load image" << std :: endl ; return - 1 ; }

cv :: Mat edgeMat , houghMatP , houghMat ; //边缘检测,转化为二值图像 cv :: Canny ( srcImage , edgeMat , 50 , 200 , 3 ); cv :: cvtColor ( edgeMat , houghMatP , cv :: COLOR_GRAY2BGR ); cv :: cvtColor ( edgeMat , houghMat , cv :: COLOR_GRAY2BGR ); if ( false ) { // std :: vector < cv :: Vec2f > lines2f ; cv :: HoughLines ( edgeMat , houghMat , 1 , CV_PI / 180 , 100 , 0 , 0 ); for ( int j = 0 ; j < lines2f . size (); ++ j ) { float rho = lines2f [ j ][ 0 ]; float theta = lines2f [ j ][ 1 ]; cv :: Point pt1 , pt2 ; double x0 = rho * cos ( theta ), y0 = rho * sin ( theta ); pt1 . x = cvRound ( x0 + 1000 * ( - sin ( theta ))); pt1 . y = cvRound ( y0 + 1000 * cos ( theta )); pt2 . x = cvRound ( x0 - 1000 * ( - sin ( theta ))); pt2 . y = cvRound ( y0 - 1000 * cos ( theta )); cv :: line ( houghMat , pt1 , pt2 , cv :: Scalar ( 0 , 0 , 255 ), 3 , cv :: LINE_AA ); cv :: imshow ( "houghLine" , houghMat ); }

}

else { //进行霍夫变换 std :: vector < cv :: Vec4i > lines ; cv :: HoughLinesP ( edgeMat , lines , 1 , CV_PI / 180 , 50 , 50 , 10 ); for ( int i = 0 ; i < lines . size (); ++ i ) { cv :: Vec4i l = lines [ i ]; cv :: line ( houghMatP , cv :: Point ( l [ 0 ], l [ 1 ]), cv :: Point ( l [ 2 ], l [ 3 ]), cv :: Scalar ( 0 , 0 , 255 ), 3 , cv :: LINE_AA ); }

cv :: imshow ( "houghlineP" , houghMatP ); }

cv :: imshow ( "srcImage" , srcImage ); cv :: waitKey ( 0 ); cv :: destroyAllWindows (); return 0 ; }

结果如图: