霍夫變換概述
霍夫變換(Hough Transform)是圖像處理中的一種特征提取技術(shù),該過(guò)程在一個(gè)參數(shù)空間中通過(guò)計(jì)算累計(jì)結(jié)果的局部最大值得到一個(gè)符合該特征的集合作為霍夫變換的結(jié)果。
霍夫線檢測(cè)
霍夫線變換是一種尋找直線的方法,在尋找霍夫變換之前,要對(duì)圖像進(jìn)行邊緣檢測(cè),即霍夫線的輸入為二值圖像。
原理介紹:
1、對(duì)于直角坐標(biāo)系中的任意一點(diǎn)A(x0,y0),經(jīng)過(guò)點(diǎn)A的直線滿足Y0=k*X0+b.(k是斜率,b是截距)
2、那么在X-Y平面過(guò)點(diǎn)A(x0,y0)的直線簇可以用Y0=k*X0+b表示,但對(duì)于垂直于X軸的直線斜率是無(wú)窮大的則無(wú)法表示。因此將直角坐標(biāo)系轉(zhuǎn)換到極坐標(biāo)系就能解決該特殊情況。
3、在極坐標(biāo)系中表示直線的方程為ρ=xCosθ+ySinθ(ρ為原點(diǎn)到直線的距離),如圖所示:
4、如上圖,假定在一個(gè)8*8的平面像素中有一條直線,并且從左上角(1,8)像素點(diǎn)開(kāi)始分別計(jì)算θ為0°、45°、90°、135°、180°時(shí)的ρ,圖中可以看出ρ分別為1、(9√2)/2、8、(7√2)/2、-1,并給這5個(gè)值分別記一票,同理計(jì)算像素點(diǎn)(3,6)點(diǎn)θ為0°、45°、90°、135°、180°時(shí)的ρ,再給計(jì)算出來(lái)的5個(gè)ρ值分別記一票,此時(shí)就會(huì)發(fā)現(xiàn)ρ = (9√2)/2的這個(gè)值已經(jīng)記了兩票了,以此類(lèi)推,遍歷完整個(gè)8*8的像素空間的時(shí)候ρ = (9√2)/2就記了5票, 別的ρ值的票數(shù)均小于5票,所以得到該直線在這個(gè)8*8的像素坐標(biāo)中的極坐標(biāo)方程為 (9√2)/2=x*Cos45°+y*Sin45°,到此該直線方程就求出來(lái)了。(PS:但實(shí)際中θ的取值不會(huì)跨度這么大,一般是PI/180)。
霍夫變換檢測(cè)直線算法
1.如何知道這些正弦曲線公共交點(diǎn)呢,我們可以將rho,theta這兩個(gè)參數(shù)取值范圍等分成m,n分,用一個(gè)二維數(shù)組來(lái)裝。
2.對(duì)于圖像邊緣中的每一點(diǎn)看成直線系映射到極坐標(biāo)成為正弦曲線,然后用一個(gè)變量比如theta,求出每個(gè)取值后對(duì)應(yīng)的rho,然后落入的二維數(shù)組的分組中加1,以此類(lèi)推。
3.當(dāng)遍歷所有的點(diǎn)后,二維數(shù)組最高的值或過(guò)閾值的值,其數(shù)組的坐標(biāo)即為直角坐標(biāo)檢測(cè)出的直線。
4.m、n劃分越細(xì)越精確,但運(yùn)算量大。反之亦然。
霍夫變換檢測(cè)直線實(shí)現(xiàn)
#include “opencv2/opencv.hpp”
using namespace cv;
using namespace std;
int main()
{
Mat image = imread(“D:\\亂\\1.jpg”);
Mat result;
cvtColor(image,result,CV_BGR2GRAY);
Mat contours;
Canny(result, contours, 125, 350);
vector《Vec2f》 lines;
HoughLines(contours, lines, 1, CV_PI / 180, 100);
vector《Vec2f》::const_iterator it = lines.begin();
cout 《《 lines.size() 《《 endl;
printf(“OK”);
while (it != lines.end())
{
printf(“OK”);
float r = (*it)[0];
float theta = (*it)[1];
double a = cos(theta), b = sin(theta);
double x0 = a*r, y0 = b*r;
Point pt1(cvRound(x0 + 1000 * (-b)),
cvRound(y0 + 1000 * (a)));
Point pt2(cvRound(x0 - 1000 * (-b)),
cvRound(y0 - 1000 * (a)));
line(image, pt1, pt2, Scalar(0, 0, 255), 3, 8);
it++;
}
printf(“OK”);
namedWindow(“houghline”);
imshow(“houghline”, image);
waitKey(0);
Opencv實(shí)現(xiàn)直線檢測(cè):
1、Opencv1.0版本:
?。踓pp] view plain copy print?
#include《cv.h》
#include《highgui.h》
int main()
{
IplImage* pImgSrc = NULL; //源圖像
IplImage* pImg8u = NULL; //灰度圖
IplImage* pImgCanny = NULL; //邊緣檢測(cè)后的圖
IplImage* pImgDst = NULL; //在圖像上畫(huà)上檢測(cè)到的直線后的圖像
CvSeq* lines = NULL;
CvMemStorage* storage = NULL;
/*邊緣檢測(cè)*/
pImgSrc = cvLoadImage(“。\\res\\street.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);
/*檢測(cè)直線*/
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上畫(huà)出檢測(cè)到的直線*/
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;
}
2、Opencv2.4.9版本:
?。踓pp] view plain copy print?
#include《opencv2\imgproc\imgproc.hpp》
#include《opencv2\opencv.hpp》
#include《opencv2\highgui\highgui.hpp》
using namespace std;
using namespace cv;
int main()
{
Mat Image = imread(“。//res//street.jpg”, 0);
Mat CannyImg;
Canny(Image, CannyImg, 140, 250, 3);
imshow(“CannyImg”, CannyImg);
Mat DstImg;
cvtColor(Image, DstImg, CV_GRAY2BGR);
vector《Vec4i》 Lines;
HoughLinesP(CannyImg, Lines, 1, CV_PI / 360, 170,30,15);
for (size_t i = 0; i 《 Lines.size(); i++)
{
line(DstImg, Point(Lines[i][0], Lines[i][1]), Point(Lines[i][2], Lines[i][3]), Scalar(0, 0, 255), 2, 8);
}
imshow(“HoughLines_Detect”, DstImg);
imwrite(“。//res//HoughLines_Detect.jpg”, DstImg);
waitKey(0);
return 0;
}
評(píng)論
查看更多