霍夫變換可以用於查找圖片中存在的直線或圓,常用於車道線檢測、路牌檢測等中。其基本理論是二值化圖像上的任何點都有可能是一些候選直線集合的一部分。在平面直角座標系(x-y)中,一條直線可以用下式表示。
y=kx+b
對於直線上一個確定的點(x_0,y_0),有:y_0=kx_0+b
這表示參數平面(k-b)中的一條直線。因此,圖像中的一個點對應參數平面中的一條直線,圖像中的一條直線對應參數平面中的一個點。對圖像上所有的點作霍夫變換,最終所要檢測的直線對應的一定是參數平面中直線相交最多的那個點。這樣就在圖像中檢測出了直線。在實際應用中,直線通常採用參數方程:
opencv中集合了兩種霍夫變換:標準霍夫變換(SHT)和累計概率霍夫變換(PPHT)。函數如下:
CvSeq *cvHounghLines2 (
CvArr* image,
void* line_storage, // 保存結果位置的指針
int method,
double rho,
double theta,
int threshold,
double param1 = 0,
double param2 = 0
);
rho, theta用來設置直線所需的分辨率。rho的單位是像素,theta的單位是弧度。
SHT中沒有使用param1、param2參數。對於PPHT,param1設置爲將要返回的線段的最小長度,param2設置爲一條直線上分離線段不能連成一條直線的分割像素點數。而在多尺度的HT,這兩個參數是用來芝麻應唄計算的直線參數中較高的分辨率。
對於SHT,可以使用下列命令得到返回的檢測直線:
float * line = (float *) cvGetSeqElem(lines,i);
對於PPHT,則有:
CvPoint * line = (CvPoint *) cvGetSeqElem(lines,i);
下面給出完整的霍夫變換檢測直線示例:
#include <stdio.h>
#include <cv.h>
#include "highgui.h"
int main()
{
cvNamedWindow("grayimg",1);
cvNamedWindow("edges",1);
cvNamedWindow("hough",1);
cvMoveWindow("grayimg",0,0);
cvMoveWindow("edges",300,60);
cvMoveWindow("hough",30,120);
IplImage * img = cvLoadImage("e:/3.jpg");
IplImage * gray = NULL,*edges = NULL, *houghimg = NULL;
CvSize size;
size.width = img->width;
size.height = img->height;
CvMemStorage * storage = cvCreateMemStorage(0);
CvSeq *lines = 0;
gray = cvCreateImage(size,img->depth,1);
edges = cvCreateImage(size,img->depth,1);
houghimg = cvCreateImage(cvGetSize(img),img->depth,img->nChannels);
cvCvtColor(img,gray,CV_RGB2GRAY);
cvCanny(gray,edges,50,100,3); //先找出二值圖像的邊緣
cvCopy(img,houghimg);
lines = cvHoughLines2(edges,storage, CV_HOUGH_PROBABILISTIC, 1, CV_PI/180,10,20,10 );
//printf("%d\n",lines->total);
int index; // index 爲直線索引
for (index = 0; index < lines->total; index ++)
{
CvPoint *line = (CvPoint *)cvGetSeqElem(lines,index);
cvLine(houghimg,line[0],line[1],CV_RGB(255,0,0),3,8);
}
cvShowImage("grayimg",gray);
cvShowImage("edges",edges);
cvShowImage("hough",houghimg);
cvWaitKey();
cvDestroyAllWindows();
cvReleaseImage( &gray );
cvReleaseImage(&img);
cvReleaseImage( &edges );
system("pause");
return 0;
}
實驗結果:實驗中的參數將會影響檢測到的直線數量。