霍夫變換,就是一個可以讓機器自己學會找直線的算法。
- 基本原理
一條直線可由兩個點A=(X1,Y1)和B=(X2,Y2)確定(笛卡爾座標)
公式:
也可以寫成關於(k,q)的函數表達式(霍夫空間):
對應的變換可以通過圖形直觀表示:
變換後的空間成爲霍夫空間。即:笛卡爾座標系中一條直線,對應霍夫空間的一個點。
反過來同樣成立(霍夫空間的一條直線,對應笛卡爾座標系的一個點):
再來看看A、B兩個點,對應霍夫空間的情形:
三個點共線的情況:
可以看出如果笛卡爾座標系的點共線,這些點在霍夫空間對應的直線交於一點:這也是必然,共線只有一種取值可能。
如果不止一條直線呢?再看看多個點的情況(有兩條直線):
其實(3,2)與(4,1)也可以組成直線,只不過它有兩個點確定,而圖中A、B兩點是由三條直線匯成,這也是霍夫變換的後處理的基本方式:選擇由儘可能多直線匯成的點。
霍夫空間:選擇由三條交匯直線確定的點(中間圖),對應的笛卡爾座標系的直線(右圖):
到這裏問題似乎解決了,已經完成了霍夫變換的求解,但是如果像下圖這種情況呢?
k=∞是不方便表示的,而且q怎麼取值呢,這樣不是辦法。因此考慮將笛卡爾座標系換爲:極座標表示。
在極座標系下,其實是一樣的:極座標的點→霍夫空間的直線,只不過霍夫空間不再是[k,q]的參數,而是[ρ,θ]的參數,給出對比圖:
霍夫變換的算法步驟:
編程思路
1. 讀取一幅待處理二值圖像,最好背景爲黑色;
2. 取得源像素數據;
3. 根據直線的霍夫變換公式完成霍夫變換,預覽霍夫空間結果;
4. 尋找最大霍夫值,設置閾值,反變換到圖像RGB值空間(程序難點之一);
5. 越界處理,顯示霍夫變換處理以後的圖像;
Opencv-python code解釋:
1.檢測線
cv2.HoughLines(image, rho, theta, threshold[, lines[, srn[, stn]]])
image是輸入的圖像
rho是以像素爲單位的累加器的距離分辨率
theta是在弧度內的蓄能器的角度分辨率
threshold其實是閾值,當累加器超過一定的範圍纔看作是直線
cv2.HoughLinesP(image, rho, theta, threshold[, lines[, minLineLength[, maxLineGap]]])
其他的參數和上一個函數一樣
minLineLength是線的最短長度(比這個短的都忽略了)
maxLinegap兩條直線的最大間隔,小於這個間隔的看成一條直線。
下面左圖爲原始圖像,右圖爲HoughLines和HoughLinesP後的圖像,從圖中可以看到檢測到草叢中間的一條小路:
2.檢測圈
cv2.HoughCircles(image, method, dp, minDist[, circles[, param1[, param2[, minRadius[, maxRadius]]]]])
image是輸入圖象
method僅有一個cv2.HOUGH_GRADIENT
dp累加器分辨率與圖像分辨率的反比。例如,如果dp=1,累加器與輸入圖像具有相同的分辨率。如果dp=2,則累加器的寬度和高度爲原來的一半。
minDist檢測圓的中心之間的最小距離。如果參數太小,可能會錯誤地檢測到多個相鄰的圓。如果太大,可能會漏掉一些圓。
param1第一個method-specific參數。在CV_HOUGH_GRADIENT的情況下,它是兩個傳遞到Canny()邊緣檢測器的更高閾值(下一個是兩倍小)。
param2第二個method-specific參數。在CV_HOUGH_GRADIENT的情況下,它是檢測階段圓形中心的累加器閾值。它越小,就會發現更多的假圓。圓形,對應於較大的累加器值,將首先返回。
minradius圓的最小半徑
maxradius圓的最大半徑
下面左圖爲原始圖像,右圖爲HoughLines和HoughLinesP後的圖像,從圖中可以看到檢測到了蒙古包: