opencv 霍夫线变换
霍夫線變換
它是如何實現的?
眾所周知, 一條直線在圖像二維空間可由兩個變量表示. 例如:
對于霍夫變換, 我們將用?極坐標系?來表示直線. 因此, 直線的表達式可為:
化簡得:?
一般來說對于點?, 我們可以將通過這個點的一族直線統一定義為:
這就意味著每一對??代表一條通過點??的直線.
如果對于一個給定點??我們在極坐標對極徑極角平面繪出所有通過它的直線, 將得到一條正弦曲線. 例如, 對于給定點??and?我們可以繪出下圖 (在平面??-?):
只繪出滿足下列條件的點??and?.
我們可以對圖像中所有的點進行上述操作. 如果兩個不同點進行上述操作后得到的曲線在平面??-??相交, 這就意味著它們通過同一條直線. 例如, 接上面的例子我們繼續對點:?,??和點?,??繪圖, 得到下圖:
這三條曲線在??-??平面相交于點?, 坐標表示的是參數對 () 或者是說點?, 點??和點??組成的平面內的的直線.
那么以上的材料要說明什么呢? 這意味著一般來說, 一條直線能夠通過在平面??-??尋找交于一點的曲線數量來?檢測. 越多曲線交于一點也就意味著這個交點表示的直線由更多的點組成. 一般來說我們可以通過設置直線上點的?閾值?來定義多少條曲線交于一點我們才認為?檢測?到了一條直線.
這就是霍夫線變換要做的. 它追蹤圖像中每個點對應曲線間的交點. 如果交于一點的曲線的數量超過了?閾值, 那么可以認為這個交點所代表的參數對??在原圖像中為一條直線.
標準霍夫線變換和統計概率霍夫線變換
OpenCV實現了以下兩種霍夫線變換:
- 原理在上面的部分已經說明了. 它能給我們提供一組參數對??的集合來表示檢測到的直線
- 在OpenCV 中通過函數?HoughLines?來實現
- 這是執行起來效率更高的霍夫線變換. 它輸出檢測到的直線的端點?
- 在OpenCV 中它通過函數?HoughLinesP?來實現
代碼
- 加載一幅圖片
- 對圖片進行?標準霍夫線變換?或是?統計概率霍夫線變換.
- 分別在兩個窗口顯示原圖像和繪出檢測到直線的圖像.
代碼說明
加載圖片
Mat src = imread(filename, 0); if(src.empty()) {help();cout << "can not open " << filename << endl;return -1; }用Canny算子對圖像進行邊緣檢測
Canny(src, dst, 50, 200, 3);現在我們將要執行霍夫線變換. 我們將會說明怎樣使用OpenCV的函數做到這一點:
標準霍夫線變換
首先, 你要執行變換:
vector<Vec2f> lines; HoughLines(dst, lines, 1, CV_PI/180, 100, 0, 0 );帶有以下自變量:
- dst: 邊緣檢測的輸出圖像. 它應該是個灰度圖 (但事實上是個二值化圖)
- lines: 儲存著檢測到的直線的參數對??的容器 *?rho?: 參數極徑??以像素值為單位的分辨率. 我們使用?1?像素.
- theta: 參數極角??以弧度為單位的分辨率. 我們使用?1度?(即CV_PI/180)
- threshold: 要”檢測” 一條直線所需最少的的曲線交點
- srn?and?stn: 參數默認為0. 查缺OpenCV參考文獻來獲取更多信息.
通過畫出檢測到的直線來顯示結果.
for( size_t i = 0; i < lines.size(); i++ ) {float rho = lines[i][0], theta = lines[i][1];Point pt1, pt2;double a = cos(theta), b = sin(theta);double x0 = a*rho, y0 = b*rho;pt1.x = cvRound(x0 + 1000*(-b));pt1.y = cvRound(y0 + 1000*(a));pt2.x = cvRound(x0 - 1000*(-b));pt2.y = cvRound(y0 - 1000*(a));line( cdst, pt1, pt2, Scalar(0,0,255), 3, CV_AA); }統計概率霍夫線變換
首先, 你要執行變換:
vector<Vec4i> lines; HoughLinesP(dst, lines, 1, CV_PI/180, 50, 50, 10 );帶有以下自變量:
- dst: 邊緣檢測的輸出圖像. 它應該是個灰度圖 (但事實上是個二值化圖) *?lines: 儲存著檢測到的直線的參數對??的容器
- rho?: 參數極徑??以像素值為單位的分辨率. 我們使用?1?像素.
- theta: 參數極角??以弧度為單位的分辨率. 我們使用?1度?(即CV_PI/180)
- threshold: 要”檢測” 一條直線所需最少的的曲線交點 *?minLinLength: 能組成一條直線的最少點的數量. 點數量不足的直線將被拋棄.
- maxLineGap: 能被認為在一條直線上的亮點的最大距離.
通過畫出檢測到的直線來顯示結果.
for( size_t i = 0; i < lines.size(); i++ ) {Vec4i l = lines[i];line( cdst, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0,0,255), 3, CV_AA); }顯示原始圖像和檢測到的直線:
imshow("source", src); imshow("detected lines", cdst);等待用戶按鍵推出程序
waitKey();結果?
Note
?得到的結果使用的是在上面?代碼?部分提到的更高級版代碼. 霍夫線變換的代碼沒有改變, 唯一不同的是在GUI的部分加入了活動條可動態改變閾值.輸入圖像為:
通過執行統計概率霍夫線變換我們能得到下面的結果:
當你使用滑動條來改變?閾值?的時候會觀察到檢測到線的數目的改變. 這是因為: 如果你設置了一個更大的閾值, 能檢測到的線的數目將更少 (你需要更多的點來表示一條能檢測到的直線).
總結
以上是生活随笔為你收集整理的opencv 霍夫线变换的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: opencv copyto函数
- 下一篇: C/C++中的函数中的void和void