霍夫直線變換介紹
Hough Line Transform用來做直線檢測
前提條件 – 邊緣檢測已經完成
平面空間到極坐標空間轉換
霍夫線變換的原理
眾所周知, 一條直線在圖像二維空間可由兩個變量表示. 如:
<1>在笛卡爾坐標系: 可由參數: 斜率和截距(m,b)表示。
<2>在極坐標系: 可由參數: 極徑和極角(r, θ)表示。
可以用極坐標系來表示直線. 因此, 直線的表達式可為:
化簡便可得到:
OpenCV中的霍夫線變換
霍夫線變換是一種用來尋找直線的方法. 在使用霍夫線變換之前, 首先要對圖像進行邊緣檢測的處理,也即霍夫線變換的直接輸入只能是邊緣二值圖像.
OpenCV支持三種不同的霍夫線變換,它們分別是:
標准霍夫變換(Standard Hough Transform,SHT),
多尺度霍夫變換(Multi-Scale Hough Transform,MSHT),
累計概率霍夫變換(Progressive Probabilistic Hough Transform ,PPHT)。
其中,多尺度霍夫變換(MSHT)為經典霍夫變換(SHT)在多尺度下的一個變種。累計概率霍夫變換(PPHT)算法是標准霍夫變換(SHT)算法的一個改進,它在一定的范圍內進行霍夫變換,計算單獨線段的方向以及范圍,從而減少計算量,縮短計算時間。之所以稱PPHT為“概率”的,是因為並不將累加器平面內的所有可能的點累加,而只是累加其中的一部分,該想法是如果峰值如果足夠高,只用一小部分時間去尋找它就夠了。這樣猜想的話,可以實質性地減少計算時間。
在OpenCV中,我們可以用HoughLines函數來調用標准霍夫變換SHT和多尺度霍夫變換MSHT。
而HoughLinesP函數用於調用累計概率霍夫變換PPHT。累計概率霍夫變換執行效率很高,所有相比於HoughLines函數,我們更傾向於使用HoughLinesP函數。
總結一下,OpenCV中的霍夫線變換有如下三種:
<1>標准霍夫變換(StandardHough Transform,SHT),由HoughLines函數調用。
<2>多尺度霍夫變換(Multi-ScaleHough Transform,MSHT),由HoughLines函數調用。
<3>累計概率霍夫變換(ProgressiveProbabilistic Hough Transform,PPHT),由HoughLinesP函數調用。
相關的API介紹
1. HoughLines( )函數詳解
標准的霍夫變換 cv::HoughLines從平面坐標轉換到霍夫空間,最終輸出是 (θ,rθ)表示極坐標空間
void HoughLines(InputArray image, OutputArray lines, double rho, double theta, int threshold, double srn=0, double stn=0 )
說明:
1 cv::HoughLines( 2 InputArray src, // 輸入圖像,必須8-bit的灰度圖像
3 OutputArray lines, // 輸出的極坐標來表示直線,經過調用HoughLines函數后儲存了霍夫線變換檢測到線條的輸出矢量。每一條線由具有兩個元素的矢量(ρ,θ)表示,其中,ρ是離坐標原點((0,0)(也就是圖像的左上角)的距離。 θ是弧度線條旋轉角度(0~ 垂直線,π/2~水平線)。
4 double rho, // 生成極坐標時候的像素掃描步長,一般取值為 1 ,不要大於圖像尺寸的一半
5 double theta, //生成極坐標時候的角度步長,一般取值CV_PI/180,即表示一度
6 int threshold, // 閾值,只有獲得足夠交點的極坐標點才被看成是直線
7 double srn=0;// 是否應用多尺度的霍夫變換,如果不是設置0表示經典霍夫變換,多尺度表示的是使用圖像金字塔,即多尺度圖上進行霍夫變換
8 double stn=0;//是否應用多尺度的霍夫變換,如果不是設置0表示經典霍夫變換
9 double min_theta=0; // 表示角度掃描范圍 0 ~180之間, 默認即可
10 double max_theta=CV_PI 11 ) // 一般情況是有經驗的開發者使用,需要自己反變換到平面空間
2. HoughLinesP( )函數詳解
此函數在HoughLines的基礎上末尾加了一個代表Probabilistic(概率)的P,表明它可以采用累計概率霍夫變換(PPHT)來找出二值圖像中的直線。
霍夫變換直線概率 cv::HoughLinesP最終輸出是直線的兩個點
void HoughLinesP(InputArray image, OutputArray lines, double rho, double theta, int threshold, double minLineLength=0, double maxLineGap=0 )
說明:
1 cv::HoughLinesP( 2 InputArray src, // 輸入圖像,必須8-bit的灰度圖像
3 OutputArray lines, // 輸出的極坐標來表示直線,經過調用HoughLinesP函數后后存儲了檢測到的線條的輸出矢量,每一條線由具有四個元素的矢量(x_1,y_1, x_2, y_2) 表示,其中,(x_1, y_1)和(x_2, y_2) 是是每個檢測到的線段的結束點。
4 double rho, // 生成極坐標時候的像素掃描步長,一般取值為 1
5 double theta, //生成極坐標時候的角度步長,一般取值CV_PI/180,即表示一度
6 int threshold, // 閾值,只有獲得足夠交點的極坐標點才被看成是直線
7 double minLineLength=0;// 最小直線長度,有默認值0,表示最低線段的長度,比這個設定參數短的線段就不能被顯現出來。
8 double maxLineGap=0;// 最大間隔,有默認值0,允許將同一行點與點之間連接起來的最大的距離。
9 )
程序代碼:
1 #include<opencv2/opencv.hpp>
2 #include<iostream>
3
4 using namespace std; 5 using namespace cv; 6
7 void main(int argc, char** argv) 8 { 9 //1. 讀取圖像
10 Mat src, canny, dst; 11 src = imread("E:/Experiment/OpenCV/Pictures/LineTest.jpg"); 12 imshow("src", src); 13
14 //2. 獲取邊緣
15 Canny(src, canny, 100, 200); 16 imshow("canny", canny); 17 //3. 轉成灰度圖像
18 cvtColor(canny, dst, CV_GRAY2BGR);//將二值圖轉換為RGB圖顏色空間,這里重新創建一張空Mat也行 19 //4. 霍夫變換檢測
20 vector<Vec4f> plines;//保存霍夫變換檢測到的直線
21 HoughLinesP(canny, plines, 1, CV_PI / 180, 10, 0, 10);//提取邊緣時,會造成有些點不連續,所以maxLineGap設大點 22 //5. 顯示檢測到的直線
23 Scalar color = Scalar(0, 0, 255);//設置顏色
24 for (size_t i = 0; i < plines.size(); i++) 25 { 26 Vec4f hline = plines[i]; 27 line(dst, Point(hline[0], hline[1]), Point(hline[2], hline[3]), color, 3, LINE_AA);//繪制直線
28 } 29 imshow("plines", dst); 30
31 waitKey(0); 32 }
運行截圖