霍夫变换(Hough Transform)是图像处理中的一种特征提取技术,它通过一种投票算法检测具有特定形状的物体。该过
程在一个参数空间中通过计算累计结果的局部最大值得到一个符合该特定形状的集合作为霍夫变换结果。霍夫变换于
1962年由Paul Hough 首次提出[53],后于1972年由Richard Duda和Peter Hart推广使用[54],经典霍夫变换用来检
测图像中的直线,后来霍夫变换扩展到任意形状物体的识别,多为圆和椭圆。
Hough变换用来在图象中查找直线。它的原理很简单:假设有一条与原点距离为s,方向角为θ的一条直线,如
图7.6所示。
直线上的每一点都满足方程
我们知道,一条直线在直角坐标系下可以用y=kx+b表示, 霍夫变换的主要思想是将该方程的参数和变量交换,即用x,y作为已知量k,b作为变量坐标,所以直角坐标系下的直线y=kx+b在参数空间表示为点(k,b),而一个点(x1,y1)在直角坐标系下表示为一条直线y1=x1·k+b,其中(k,b)是该直线上的任意点。为了计算方便,我们将参数空间的坐标表示为极坐标下的s和θ。因为同一条直线上的点对应的(s,θ)是相同的,因此可以先将图片进行边缘检测,然后对图像上每一个非零像素点,在参数坐标下变换为一条直线,那么在直角坐标下属于同一条直线的点便在参数空间形成多条直线并内交于一点。因此可用该原理进行直线检测。
在Opencv中已经有了利用Hough变换在二值图中找到直线的接口了,这里就直接调用,下面是我的实例:
#include<cv.h> #include<highgui.h> int main() { IplImage* pImgSrc = NULL; //源图像 IplImage* pImg8u = NULL; //灰度图 IplImage* pImgCanny = NULL; //边缘检测后的图 IplImage* pImgDst = NULL; //在图像上画上检测到的直线后的图像 CvSeq* lines = NULL; CvMemStorage* storage = NULL; /*边缘检测*/ pImgSrc = cvLoadImage ("1.jpg", 1); pImg8u = cvCreateImage (cvGetSize(pImgSrc), IPL_DEPTH_8U, 1); pImgCanny = cvCreateImage (cvGetSize(pImgSrc), IPL_DEPTH_8U, 1); pImgDst = cvCreateImage (cvGetSize(pImgSrc), IPL_DEPTH_8U, 1); cvCvtColor (pImgSrc, pImg8u, CV_BGR2GRAY); cvCanny (pImg8u, pImgCanny, 20, 200, 3); /*检测直线*/ storage = cvCreateMemStorage (0); lines = cvHoughLines2 (pImgCanny, storage, CV_HOUGH_PROBABILISTIC, 1, CV_PI/180, 80, 200, 10); pImgDst = cvCreateImage (cvGetSize(pImgSrc), IPL_DEPTH_8U, 3); cvCvtColor (pImg8u, pImgDst, CV_GRAY2BGR); /*在pImgDst上画出检测到的直线*/ for (int i = 0; i < lines->total; i++) { CvPoint* line = (CvPoint*)cvGetSeqElem (lines, i); cvLine (pImgDst, line[0], line[1], CV_RGB(255,0,0), 3, 8); } cvNamedWindow ("src",1); cvNamedWindow ("canny", 1); cvNamedWindow ("hough", 1); cvShowImage ("src", pImgSrc); cvShowImage ("canny", pImgCanny); cvShowImage ("hough", pImgDst); cvWaitKey (0); cvReleaseImage (&pImgSrc); cvReleaseImage (&pImg8u); cvReleaseImage (&pImgCanny); cvReleaseImage (&pImgDst); cvReleaseMemStorage (&storage); return 0; }
源图:
Canny算子进行边缘检测结果:
Hough变换检测直线: