霍夫線變換的原理
- 一條直線在圖像二維空間可由兩個變量表示,有以下兩種情況:
① 在笛卡爾坐標系中:可由參數斜率和截距(k,b)表示。
② 在極坐標系中:可由參數極經和極角(r,θ)表示。
對於霍夫線變換,我們將采用第二種方式極坐標系來表示直線,因此直線的表達式可為:
化簡便可得到:
- 對於(x0,y0),我們可以將通過這一點的所有直線統一定義為:
這就意味着每一對 代表一條通過點
的直線。
-
對於一個給定點
,我們可以在直角坐標系中,繪出所有通過它的直線(θ 為 x 軸,r 為 y 軸)。最終我們將得到一條正弦曲線。
注意:只繪出滿足下列條件的點 and
。
- 我們可以對圖像中所有的點進行上述操作.。如果兩個不同點進行上述操作后得到的曲線在平面
-
相交, 這就意味着它們有一個公共的(θ,rθ),即過一條公共的直線。下圖中,若曲線每點權重均為 1 ,則交點處權重為 3。
-
越多曲線交於一點,也就意味着這個交點表示的直線由更多的點組成,權重和越大。我們可以設置一個閾值,來決定多少條曲線交於一點(權重多大)我們才認為檢測到了一條直線。
-
這就是霍夫線變換要做的.。它追蹤圖像中每個點對應曲線間的交點.。如果交於一點的曲線的數量超過了閾值, 那么可以認為這個交點所代表的參數對
在原圖像中為一條直線。
OpenCV 實現了以下三種霍夫線變換:
- 標准霍夫變換(StandardHough Transform,SHT)
- 原理在上面的部分已經說明了. 它能給我們提供一組參數對(ρ,θ)的集合來表示檢測到的直線。
- 在 OpenCV 中通過函數 HoughLines 來實現。
- 多尺度霍夫變換(Multi-ScaleHough Transform,MSHT)
- 和標准霍夫變換類似。
- 累計概率霍夫變換(ProgressiveProbabilistic Hough Transform,PPHT),由HoughLinesP函數調用。
- 這是執行起來效率更高的霍夫線變換. 它輸出檢測到的直線的端點
。
- 在 OpenCV 中它通過函數 HoughLinesP 來實現。
- 這是執行起來效率更高的霍夫線變換. 它輸出檢測到的直線的端點
void HoughLines(InputArray image, OutputArray lines, double rho, double theta, int threshold, double srn = 0, double stn = 0);
- image,輸入圖像,即源圖像。需要為 8 位的單通道二值圖像。
- lines,存放直線的矢量信息的數組。每條直線由具有 2 個元素的矢量(ρ,Θ)表示,其中,ρ 是離坐標原點(0,0)也就是圖像左上角的距離,Θ 是弧度線條旋轉角度(0 表示垂直直線,∏/2 表示水平直線,注意,不是 0 度和 90 度)
- rho,以像素為單位的距離精度。另一種表述是平面
-
中 r 軸的單位長度。
- theta,以弧度為單位的角度精度。另一種表示是平面
-
中 θ 軸的單位長度。
- threshold,權重累加平面的閾值參數。大於閾值 threshold 的線段才可以被確認為直線。
- srn,默認值為 0。多尺度霍夫線變換才會用到的參數。對於多尺度霍夫線變換,平面
-
中 r 軸的單位長度 = rho / srn。
- stn,默認值為 0。也是多尺度霍夫線變換才會用到的參數。對於多尺度霍夫線變換,平面
-
中 θ 軸的單位長度 = theta / stn。如果 srn、stn 同時為 0,就表示使用經典霍夫變換,否則兩個參數都應該為正數。
代碼示例:
#include<opencv.hpp> #include<iostream>
using namespace std; using namespace cv; int hough_value = 70; Mat src, canny_img; void hough_change(int, void*) { vector<Vec2f>lines; HoughLines(canny_img, lines, 1, CV_PI / 180.0, hough_value); RNG rngs = { 12345 }; Mat show = src.clone(); for (int i = 0; i < lines.size(); i++) { float rho = lines[i][0], theta = lines[i][1]; double sin_theta = sin(theta), cos_theta = cos(theta); double x = rho * cos_theta, y = rho * sin_theta; //以垂點為基礎,將直線延長
Point pt1, pt2; pt1.x = cvRound(x + 1000 * (-sin_theta)); pt1.y = cvRound(y + 1000 * (cos_theta)); pt2.x = cvRound(x - 1000 * (-sin_theta)); pt2.y = cvRound(y - 1000 * (cos_theta)); Scalar colors = Scalar(rngs.uniform(0, 255), rngs.uniform(0, 255), rngs.uniform(0, 255)); line(show, pt1, pt2, colors, 2); } imshow("show", show); } int main() { src = imread("C:/Users/齊明洋/Desktop/1.jpg"); GaussianBlur(src, src, Size(3, 3), 0, 0); imshow("src", src); Canny(src, canny_img, 55, 110, 3); imshow("canny_img", canny_img); namedWindow("show"); createTrackbar("threshold", "show", &hough_value, 200, hough_change); hough_change(0, 0); waitKey(0); }
效果演示:
累計概率霍夫變換:HoughLinesP 函數
void HoughLinesP(InputArray image, OutputArray lines, double rho, double theta, int threshold, double minLineLength = 0, double maxLineGap= 0);
- lines,存放直線信息矢量的數組。每條直線由具有 4 個元素的矢量(x_1,y_1,x_2,y_2)表示,其中,(x_1,y_1)和(x_2,y_2)是每條檢測到的直線的兩端端點。
- minLineLength ,默認值為 0。最短線段的長度,比這個設定參數短的線段就不能被顯現出來。
- maxLineGap,默認值為 0。允許將同一行點與點之間連接起來的最大距離。
- 其余參數,類比 HoughLines 函數的參數。
代碼示例:
#include<opencv.hpp> #include<iostream>
using namespace std; using namespace cv; int hough_value = 70; Mat src, canny_img; void hough_change(int, void*) { vector<Vec4f>lines; HoughLinesP(canny_img, lines, 1, CV_PI / 180, hough_value, 10, 5); RNG rngs = { 12345 }; Mat show = src.clone(); for (int i = 0; i < lines.size(); i++) { Point pt1, pt2; pt1.x = lines[i][0]; pt1.y = lines[i][1]; pt2.x = lines[i][2]; pt2.y = lines[i][3]; Scalar colors = Scalar(rngs.uniform(0, 255), rngs.uniform(0, 255), rngs.uniform(0, 255)); line(show, pt1, pt2, colors, 2); } imshow("show", show); } int main() { src = imread("C:/Users/齊明洋/Desktop/1.jpg"); GaussianBlur(src, src, Size(3, 3), 0, 0); imshow("src", src); Canny(src, canny_img, 55, 110, 3); imshow("canny_img", canny_img); namedWindow("show"); createTrackbar("threshold", "show", &hough_value, 200, hough_change); hough_change(0, 0); waitKey(0); }
效果演示:
借鑒博客:https://www.cnblogs.com/xmu-rcs-jty/p/7531814.html