OpenCV圖像處理|1.20 霍夫線變換

OpenCV圖像處理|1.20 霍夫線變換

來自專欄 OpenCV圖像處理教程4 人贊了文章

概率霍夫線檢測HoughLinesP()、先提取邊緣再做直線檢測、畫線

1.20.1 霍夫直線變換原理

霍夫變換直線檢測:是一種用來尋找直線的方法(還有霍夫圓檢測)。把圖像上的全部像素點變換到極坐標空間,每一點形成一條曲線,若某些曲線能相交於一點上,則這些像素點就在一條直線上。

原理:屬於同一條直線上點在極坐標空(r, theta)必然在一個點上有最強的信號出現,根據此反算到平面坐標中就可以得到直線上各點的像素坐標,從而得到直線。

前提條件:先完成對圖像的邊緣檢測(輸出是8位單通道),也即霍夫線變換的直接輸入只能是邊緣二值圖像。

平面空間(空域)到極坐標空間(霍夫空間)轉換:一條直線在圖像二維空間可由兩個變數表示。例如:

在笛卡爾坐標系(直角坐標系和斜角坐標系的統稱): 可由參數(m,b)斜率和截距表示.

在極坐標系: 可由參數 (r,o)極徑(r或p)和極角表示:

1)對於霍夫變換, 我們將用極坐標系來表示直線. 因此, 直線的表達式可為:

化簡得:

2)對於點 (x0,y0), 我們可以將通過這個點的一族直線統一定義為:

這就意味著每一對 (r0,o)代表一條通過點 (x0,y0),的直線.

3)如果對於一個給定不變點 (x0,y0),r 隨著 o變化而變化,我們在極坐標對極徑極角平面繪出所有通過它的直線, 將得到一條正弦曲線。例如, 對於給定點 x0=8and y0=6我們可以繪出下圖 (在平面 o-r):(只繪出了滿足下列條件的點 r>0 and 0<o<2pi)

4)我們可以對圖像中所有的點進行上述操作. 如果兩個不同點進行上述操作後得到的曲線在平面 o-r相交, 這就意味著它們通過同一條直線。

例如, 接上面的例子我們繼續對點: : x1=9, y1=4和點 x2=12, y2=3繪圖, 得到下圖: 這三條曲線在o-r平面相交於點(0.925, 9.6), 坐標表示的是參數對 (o,r)或者是說點 (x0,y0)、點 (x1,y1)和點 (x2,y2)組成的平面內的的直線.

5) 一條直線能夠通過在平面 o-r 尋找交於一點的曲線數量來檢測. 越多曲線交於一點也就意味著這個交點表示的直線由更多的點組成(越亮)。霍夫線變換要做的就是追蹤圖像中每個點對應曲線間的交點. 如果交於一點的曲線的數量超過了閾值, 那麼可以認為這個交點所代表的參數對在原圖像中為一條直線。再用公式反算

就可求出直線。

1.20.2 相關API實現

OpenCV實現了以下兩種霍夫線變換:

(1)標準霍夫線變換 - HoughLines

原理在上面的部分已經說明了,它能給我們提供一組參數對 的集合來表示檢測到的直線,從平面坐標轉換到霍夫空間,最終輸出是 ,表示極坐標空間。

這個函數一般情況是有經驗的開發者使用,需要自己反變換到平面空間。

HoughLines(

InputArray src, // 輸入圖像,必須8-bit的灰度圖像

OutputArray lines, // 輸出的極坐標來表示直線

double rho, // 生成極坐標時候的像素掃描步長,一般取1,極坐標空間 r 的最大值

double theta, //生成極坐標時候的角度步長,一般取值0~180度的角度每次掃描1度就是CV_PI/180

int threshold, // 閾值,只有獲得足夠交點的極坐標點才被看成是直線

double srn=0;// 是否應用多尺度(圖像金字塔)的霍夫變換,如果不是設置0表示經典霍夫變換,默認

double stn=0;//是否應用多尺度的霍夫變換,如果不是設置0表示經典霍夫變換,默認

double min_theta=0; // 表示角度掃描範圍 0 ~180之間, 默認即可

double max_theta=CV_PI // 表示角度掃描範圍 0 ~180之間, 默認

)

(2)概率霍夫線變換 - HoughLinesP

這是執行起來效率更高的概率霍夫線變換(probabilistic Hough ),它輸出檢測到的直線的端點 。

HoughLinesP(

InputArray src, // 輸入圖像,必須8-bit的灰度圖像

OutputArray lines, // 輸出的極坐標來表示直線

double rho, // 生成極坐標時候的像素掃描步長,一般取1

double theta, //生成極坐標時候的角度步長,一般取值CV_PI/180

int threshold, // 閾值,只有獲得足夠交點的極坐標點才被看成是直線,可以寫10

double minLineLength=0;// 最小直線長度

double maxLineGap=0;// 兩交點間允許的最大間隔,(經canny的梯度可能不連續,間隔調大)

)

/*直線檢測*/

vector<Vec4f> plines; //定義一個浮點數,二維數組

HoughLinesP(src_gray, plines, 1, CV_PI / 180.0, 10, 30, 10);//概率霍夫線變換直線檢測,灰度輸入,像素步長,角度步長,交點閾值,最短長度,最大間隔(經canny的梯度可能不連續,間隔調大)

應用步驟:

1)Canny提取邊緣 - Canny()

Canny(src, src_gray, 150, 200); //提取邊緣 ,輸入圖像可以是RGB每個通道佔8位就行,輸出8位灰度圖像

2)霍夫直線檢測 - HoughLinesP()

vector<Vec4f> plines; //定義一個浮點數,二維數組

HoughLinesP(src_gray, plines, 1, CV_PI / 180.0, 10, 30, 10);//概率霍夫線變換直線檢測,灰度輸入,像素步長,角度步長,交點閾值,最短長度,最大間隔(經canny的梯度可能不連續,間隔調大)

3)畫直線 - line()

line(dst, Point(hline[0], hline[1]), Point(hline[2], hline[3]), color, 2, LINE_AA); //畫直線,LINE_AA反鋸齒


完整程序:/*1.20 霍夫線變換 繪出檢測到的直線圖像*/#include <opencv2/opencv.hpp>#include <iostream> #include <math.h>using namespace cv;using namespace std;Mat src, dst, src_gray;int main(int argc, char** argv) { src = imread("E:/OpenCV/testimage/test7.jpg"); if (src.empty()) { printf("could not load image...
"); return -1; } char input_title[] = "input image"; namedWindow(input_title, CV_WINDOW_AUTOSIZE); imshow(input_title, src); /*Canny提取邊緣 extract edge*/ Canny(src, src_gray, 150, 200); //提取邊緣 ,輸入圖像可以是RGB每個通道佔8位就行,輸出8位灰度圖像 imshow("canny image", src_gray); /*霍夫直線檢測*/ vector<Vec4f> plines; //定義一個浮點數,二維數組 HoughLinesP(src_gray, plines, 1, CV_PI / 180.0, 10, 30, 10);//概率霍夫線變換直線檢測,灰度輸入,像素步長,角度步長,交點閾值,最短長度,最大間隔(經canny的梯度可能不連續,間隔調大) /*將檢測的直線畫出來*/ Scalar color = Scalar(255, 0, 0); // 設置線顏色 cvtColor(src_gray, dst, CV_GRAY2BGR); //灰度轉彩色RGB for (size_t i = 0; i < plines.size(); i++) { Vec4f hline = plines[i]; //數組獲取直線 line(dst, Point(hline[0], hline[1]), Point(hline[2], hline[3]), color, 2, LINE_AA); //畫直線,LINE_AA反鋸齒 } imshow("HoughLinesP image", dst); waitKey(0); return 0;}

推薦閱讀:

圖像風格化演算法綜述三部曲之 (三) (Neural Style Transfer: A Review)
第三篇:Scan to map 簡述
文本檢測之CTPN
DensePose開源了,人體姿態大規模識別也很高效 | Facebook·CVPR 2018
[計算機視覺論文速遞] 2018-06-15 人臉專場

TAG:OpenCV | 圖像處理 | 計算機視覺 |