1. 霍夫空間和霍夫變換
1.1 霍夫空間
霍夫空間 (Hough space)是一種用於影像分析的 特征空間 ,用於描述影像中具有相同形狀的線段或曲線。
霍夫空間是指將影像空間中的點對映到 參數空間 後形成的空間。參數空間的維度由形狀的描述參數的個數決定。例如,對於直線檢測,參數空間的維度為 2,其中一個維度表示直線的斜率,另一個維度表示直線的截距。對於圓檢測,參數空間的維度為 3,這三個參數分別是圓心座標和圓的半徑。
霍夫空間具有以下特性:
霍夫空間的維度等於直線或曲線的特征參數的個數。
霍夫空間中的每個點都對應於影像空間中的一條特征線。
霍夫空間中的點的值表示該特征線在影像空間中的出現頻率。
1.2 霍夫變換
霍夫變換 (Hough transform)是一種基於 霍夫空間 的影像特征提取演算法。它可以用於檢測影像中的直線、圓形、橢圓等形狀。
霍夫變換具有以下優點:
速度快,適合處理大尺寸的影像。
可以檢測任意形狀的影像。
霍夫變換也具有以下缺點:
對影像雜訊敏感。
容易受到幹擾。
霍夫變換的步驟:
對影像進行預處理,提取邊緣點。
將邊緣點對映到霍夫空間中。
在霍夫空間中計算累加函式。
根據累加函式的值來檢測影像中的形狀。
2. 霍夫直線檢測
2.1 直線檢測的霍夫空間
在影像空間中,直線可以用 y = mx+b 表示,其中 m 是直線的斜率,b 是直線的截距。
在參數空間中,直線可以用 (m,b) 表示,其中 m 是直線的斜率,b 是直線的截距。
影像空間中的每條直線在參數空間中都對應著單獨 一個點 來表示。影像空間中的直線上任何一部份線段在參數空間對應的是 同一個點 。
將影像空間中的直線對映到參數空間中的點,其中 θ 是直線的傾斜角,r 是直線與原點的距離。
r 所在的直線跟直線 y = mx + b 的交點可得
由於
所以,
這樣,影像空間**(直角座標系x-y)**的一個點在參數空間( 極座標系𝜌-𝜃 )中就對應為一條曲線。
其中:(x,y) 表示線上點的座標,𝜌 表示線距原點的距離,𝜃 表示線與 x 軸的方向。
影像空間的一個點在參數空間中就對應為一條曲線 ρ = xcos(θ) + ysin(θ),而參數空間的每個點 (θ, ρ) 都對應了影像空間的一條直線。
霍夫變換預設使用極座標系來檢測影像中的線,因為笛卡爾座標系中線的斜率範圍無限大,導致計算量較高。
2.2 投票機制
在霍夫直線檢測中,有一個重要的投票機制,它的過程如下:
邊緣檢測:使用邊緣檢測演算法辨識影像中的邊緣像素。
參數空間對映:每個邊緣點為其可能所屬的參數空間(霍夫空間)中的每條潛線上「投票」。投票的位置取決於線的角度 (θ) 和距原點的距離 (ρ)。
累加器陣列:在霍夫空間中,每當邊緣像素符合該線參數化時,對應於特定 (θ, ρ) 組合的每個單元都會收到投票。投票被累加在累加器陣列中。
峰值檢測:叠代所有邊緣像素後,分析累加器陣列以尋找具有最高投票計數(峰值)的單元格。這些峰值代表由最多數量的邊緣點支持的線,並且被認為是影像中最可能出現的線。
線參數提取:最後利用峰值的(θ,ρ)值重建原始影像空間中的直線方程式,提供最終檢測到的線。
投票機制好處在於:
對雜訊和部份遮擋的魯棒性
能夠同時檢測多條直線
基於邊緣高效辨識直線
總體而言,投票機制是霍夫直線檢測的核心優勢,使其能夠有效地從雜訊和復雜影像中辨識直線。
2.3 例子
下面的例子,透過 Canny 尋找提取影像的邊緣,然後對映到霍夫空間進行直線檢測,最後繪制找到的直線。
#include"opencv2/imgproc.hpp"
#include"opencv2/highgui.hpp"
usingnamespacestd;
usingnamespace cv;
intmain(int argc, char **argv){
Mat src = imread(".../country_road.jpg");
imshow("src", src);
Mat gray;
cvtColor(src, gray, cv::COLOR_BGR2GRAY);
GaussianBlur(gray,gray,Size(7,7),0);
Mat edge;
Canny(gray,edge,100,300,3);
imshow("edge", edge);
std::vector<Vec4f> lines;
cv::HoughLinesP(edge, lines, 1, CV_PI / 180.0, 80, 50, 5);
cv::Scalar color = cv::Scalar(0, 0, 255);
for(size_t i = 0; i < lines.size(); i++){
line(src, cv::Point(lines[i][0], lines[i][1]), cv::Point(lines[i][2], lines[i][3]), color, 8, cv::LINE_AA);
}
imshow("result", src);
waitKey(0);
return0;
}
HoughLinesP() 函式是基於**累積機率霍夫變換(PPHT)**的一種實作。PPHT 演算法比標準霍夫變換演算法更準確,但也更耗時。
voidHoughLinesP( InputArray image, OutputArray lines,
double rho, double theta, int threshold,
double minLineLength = 0, double maxLineGap = 0 );
第一個參數 image:輸入影像,必須是單鍊結的灰度影像或二值影像。
第二個參數 lines:輸出陣列,其中儲存檢測到的直線。每個直線由四個元素的向量表示,分別為直線的起點 (x1, y1)、終點 (x2, y2)。
第三個參數 rho:參數空間中 ρ 的範圍。
第四個參數 theta:參數空間中 θ 的範圍。
第五個參數 threshold:累加器中用於判定線段是否有效的閾值。
第六個參數 minLineLength:線段的最小長度。
第七個參數 maxLineGap:線段之間的最大間隔。
HoughLinesP() 函式對雜訊敏感,因此在使用前應對影像進行降噪處理。
下面的例子,同樣是基於 Canny 尋找影像的邊緣,然後進行直線檢測。
#include"opencv2/imgproc.hpp"
#include"opencv2/highgui.hpp"
usingnamespacestd;
usingnamespace cv;
intmain(int argc, char **argv){
Mat src = imread(".../paper.jpg");
imshow("src", src);
Mat gray;
cvtColor(src, gray, cv::COLOR_BGR2GRAY);
Mat edge;
Canny(gray,edge,40,80,3);
imshow("edge", edge);
std::vector<Vec4f> lines;
cv::HoughLinesP(edge, lines, 1, CV_PI / 180.0, 20, 100, 30);
cv::Scalar color = cv::Scalar(0, 0, 255);
for(size_t i = 0; i < lines.size(); i++){
line(src, cv::Point(lines[i][0], lines[i][1]), cv::Point(lines[i][2], lines[i][3]), color, 8, cv::LINE_AA);
}
imshow("result", src);
waitKey(0);
return0;
}
HoughLinesP() 函式在使用時,需要註意的是:
threshold:投票閾值,閾值越高,檢測到的直線越少。
minLineLength:直線的最小長度,小於此值的直線將被拒絕。minLineLength 越大,檢測到的直線越長。
maxLineGap:最大允許的直線間距,以使它們被視為單一線段。maxLineGap 越大,檢測到的直線越可能被視為單一線段。
3. 總結
霍夫直線檢測是影像處理中用於檢測影像中直線的一種常用方法。可以檢測出影像中任意方向的直線,包括水平直線、垂直直線以及斜直線。也可以檢測出影像中多條直線,即使這些直線重疊或被遮擋。它是一種簡單而有效的影像處理方法,在許多套用中得到了廣泛的套用。
掃碼學習YOLOv8視訊課程
推薦閱讀