其他分享
首页 > 其他分享> > 霍夫线变换

霍夫线变换

作者:互联网

霍夫变换(Hough Transform)是图像处理中的一种特征提取技术,它通过一种投票算法,检测具有特定形状(数学模型+参数)的物体。该过程在(一个)参数空间中通过计算累计结果的局部最大值,得到一个符合该特定形状的集合作为霍夫变换结果。

霍夫变换于1962年由Paul Hough 首次提出[53],后于1972年由Richard Duda和Peter Hart推广使用[54],经典霍夫变换用来检测图像中的直线,后来霍夫变换扩展到任意形状物体的识别,多为圆和椭圆。

霍夫变换运用两个坐标空间之间的变换,将在一个(图像)空间中具有相同形状(数学模型+参数)的曲线或直线,映射到另一个(参数)坐标空间的一个点上形成峰值,从而把检测任意形状的问题转化为统计峰值问题。(上一节中已经介绍了车道的直线特征,本节中介绍hough变换检测直线的原理和检测结果)

我们知道,一条直线在直角(图像)坐标系下可以用y=kx+b表示, 霍夫变换的主要思想是将该方程的参数和变量交换,即用x,y作为(参数、系数),k,b作为(变量),所以直角坐标系下的一个点(x1,y1)在直角坐标系下表示为一条直线:y1=x1·k+b, 其中(k,b)是该直线上的任意点;直角坐标系下的一条直线y=kx+b在参数空间表示为一个点:(k,b),为了计算方便,并解决k(直线的斜率)接近无穷大的问题,使用了一种标准的直线标识法,将参数空间的坐标表示为极坐标下的γ和θ。


上图转换到ρ、Θ空间是通过k、b参数空间转化而来,因为在k、b空间,直线相交一点代表直角坐标系下的斜率和截距,将k、b空间转到ρ、Θ空间,才能够使得Θ空间的曲线交于一点,如果直接从原直角坐标系转到ρ、Θ空间,则很明显可以知道,原直角坐标系下的点不出现在同一个Θ位置。所以其实原直角坐标系到极坐标空间经历了两次变换,变换到极坐标空间的原因是因为k、b空间不能解决k为tan90度时的无穷大等计算量问题。

因为同一条直线上的点对应的参数(k,b)/(γ,θ)是相同的,因此可以先将图片进行边缘检测,然后对图像上每一个非零像素点,在参数坐标下变换为一条直线,那么在直角坐标下属于同一条直线的点便在参数空间形成多条直线并内交于一点,这一点即为对应直线的参数,所有直线在(γ,θ)参数空间中得到一系列对应曲线。因此可用该原理进行直线检测。


Hough变换在计算上的吸引力在于将参数空间进一步分割为所谓的累加器单元,如图9所示。其中(amax,amin)和(bmax,bmin)为参数值的期望范围,一般来说,值的最大范围是-90°<θ<90°和-D<ρ<D,其中D是图像中角点间的距离。 最初,这些单元被设置为0。然后,对于图像平面上的每一个非背景点(xk, yk),令θ等于θ轴上允许的细分值,并通过公式ρ=xkcosθ+yksinθ求出相应的ρ值。然后,将得到的ρ值四 舍五入为最接近的、ρ轴上允许的单元值,相应的累加器单元相加。在这个过程的最后,A(i,j)意味着x-y平面上的Q个点位于线xcosθj+ysinθj=ρi上。ρ-θ平面上的细分数决定了这些点共线的精度。


(1)读取原始图像,并转成灰度图像。
(2)采用小波边缘检测算法对其进行边缘检测,得到二值化的边缘图像。
(3)对此边缘图像做Hough变换。
(4)使用函数houghpeaks 做峰值检测。函数houghpeaks的算法如下:
       ①找到包含有最大值的Hough变换单元,并记下它的位置;
       ②把上步找到的最大值点的领域中的Hough 变换单元设为0;
       ③重复该步骤,直到找到需要的峰值数为止,或者达到一个指定的阈值时为止。
(5)一旦在Hough 变换中识别出了一组候选的峰波,则还要留待确定是否存在与这些峰值相关的线段及它们的起始和终止为止。对每一个峰值来说,第一步是找到图像中影响到峰值的每一个非0 值点的位置。为此,编写函数houghpixls 来实现这一功能。
(6)使用函数houghlines 实现直线边缘连接,函数houghlines的算法如下:
       ①将像素位置旋转90° - θ ,以便它们大概位于一条垂直线上;
       ②按旋转的x值来对这些像素位置排序;
       ③使用函数diff 找到裂口。忽略掉小裂口,这将合并被小空白分离的相邻线段;
       ④返回比最小阈值长的线段的信息。


Opencv版本

  1. void CCVMFCView::OnHoughLines()  
  2. {  
  3.     IplImage* src = 0,*color_dst;  
  4.     CvMemStorage* storage = cvCreateMemStorage(0);  
  5.     CvSeq* lines = 0;  
  6.     int i;  
  7.   
  8.     if (workImg->nChannels==3) {  
  9.         src = cvCreateImage(cvGetSize(workImg), IPL_DEPTH_8U, 1);  
  10.         cvCvtColor(workImg, src, CV_BGR2GRAY);  
  11.     }  
  12.     else {  
  13.         src = cvCloneImage( workImg );  
  14.     }  
  15.   
  16.     dst = cvCreateImage( cvGetSize(src), 8 ,1 );  
  17.     color_dst = cvCreateImage( cvGetSize(src), 8 ,3);  
  18.     cvFlip(src);  
  19.     cvCanny( src, dst, 50, 120, 3 );  
  20.     cvCvtColor(dst,color_dst,CV_GRAY2BGR);  
  21.   
  22.     lines = cvHoughLines2( dst, storage, CV_HOUGH_PROBABILISTIC, 1, CV_PI/180, 20, 20,30 );  
  23.     //lines = cvHoughLines2( dst, storage, CV_HOUGH_PROBABILISTIC, 1,CV_PI/180, 80, 60,30 );  
  24.   
  25.     for( i = 0; i < lines->total; i++ )  
  26.     {  
  27.         CvPoint* line = (CvPoint*)cvGetSeqElem(lines,i);  
  28.         cvLine( color_dst, line[0], line[1], CV_RGB(255,0,0), 3, CV_AA, 0 );  
  29.     }  
  30.   
  31.     cvNamedWindow( "Hough", 1 );  
  32.     cvShowImage( "Hough", color_dst );  
  33.   
  34.     cvWaitKey(0);  
  35.   
  36.     cvReleaseMemStorage(&storage );  
  37.     cvReleaseImage( &src );  
  38.     cvReleaseImage( &dst );  
  39.     cvDestroyWindow( "Hough" );  
  40. }  

☛搬砖渣男 发布了14 篇原创文章 · 获赞 0 · 访问量 814 私信 关注

标签:src,直线,变换,dst,Hough,参数,霍夫线
来源: https://blog.csdn.net/qq_34193345/article/details/104531079