標籤:
本文原創,如轉載請註明出處。
Hough Transform 是一種能提取映像中某種特定形狀特徵的方法,可以將其描述成一種把映像空間中的像素轉換成Hough空間中直線或曲線的一種映射函數。通過利用Hough空間的一些性質,我們可以找到並識別一些有共同特性的點(如在同一條直線上)。這樣我們就得到足夠的資訊去畫出這些圖形(如直線)。其輸入映像通常為二值邊緣映像。
1.原理:
映像空間是所有像素所屬於的映像的空間。Hough空間是一種變數混合空間,實際上它與映像相關但是卻不存在物理實質性。
我們可以把映像空間的座標通過下式表達成Hough空間:
X = Ρ·cosΘ
Y = Ρ·sinΘ
where
P = sqrt(x2+y2) , 是座標原點到直線的距離
,是距離與x座標軸的夾角
通常我們寫成如下形式:
通過我們可以更加容易理解上述式子:
經過Hough變換我們將映像空間中的一個點映射到Hough空間,如我們得到了一條正弦曲線。
在這裡正弦曲線的形狀取決於,點到我們所定義原點的距離。通常,距離越大,正弦曲線的振幅越大,反之則會變小。為了使曲線顯示我們把縱座標設定成如上,當然我也可以用π表示。
以同樣的方法我們可以再次映射一個點,而我們知道在映像空間中兩個點總在一條直線上。而在Hough空間中我們可以看到兩條正弦曲線可能會相交如:
在這裡我們可以把每一個交點看成是一次投票,也就是
計算完所有邊緣點後,我們可以設定一個閾值,投票大於這個閾值的點這是我們要找的直線。如下分別為原圖,閾值為30,20時候檢測到的直線。
對於大於閾值的點我們有其Hough space的參數對(p,Θ), 通過逆映射我們可以得到映像空間中的直線:
2.opencv樣本:
步驟如下:
1.載入映像
2.應用canny或其他邊緣檢測運算元得到邊緣的二值映像
3.應用Hough transform(Houghline())
4.在原映像上畫出直線
void HoughLines(InputArray image, OutputArray lines, double rho, double theta, int threshold, double srn=0, double stn=0 )
1 #include "opencv2/highgui/highgui.hpp" 2 #include "opencv2/imgproc/imgproc.hpp" 3 #include <iostream> 4 5 using namespace cv; 6 using namespace std; 7 8 int main() 9 {10 Mat src = imread("building.jpg", 0);11 12 Mat dst, cdst;13 Canny(src, dst, 50, 200, 3); 14 cvtColor(dst, cdst, CV_GRAY2BGR); 15 16 vector<Vec2f> lines;17 // detect lines18 HoughLines(dst, lines, 1, CV_PI/180, 150, 0, 0 );19 20 // draw lines21 for( size_t i = 0; i < lines.size(); i++ )22 {23 float rho = lines[i][0], theta = lines[i][1];24 Point pt1, pt2;25 double a = cos(theta), b = sin(theta);26 double x0 = a*rho, y0 = b*rho;27 pt1.x = cvRound(x0 + 1000*(-b));28 pt1.y = cvRound(y0 + 1000*(a));29 pt2.x = cvRound(x0 - 1000*(-b));30 pt2.y = cvRound(y0 - 1000*(a));31 line( cdst, pt1, pt2, Scalar(0,0,255), 3, CV_AA);32 }33 34 imshow("source", src);35 imshow("detected lines", cdst);36 37 waitKey();38 return 0;39 }
結果:
Hough Transform直線檢測