理論
如上圖,左邊a,b固定可以確定一條直線(xiàn),線(xiàn)是() 組成的集合.
下面從xy空間變化到ab空間,此時(shí)給定一個(gè)綠點(diǎn)()可以確定一條綠色的線(xiàn),給定一個(gè)藍(lán)點(diǎn)?
()可以確定一條藍(lán)色的線(xiàn),綠線(xiàn)和藍(lán)線(xiàn)相交的點(diǎn)就是左邊確定紅線(xiàn)的參數(shù)a和b.此時(shí)xy空間里紅線(xiàn)上的其他點(diǎn),變換到ab空間必過(guò)藍(lán)綠線(xiàn)相交點(diǎn).
下面把a(bǔ)b換成rho和theta.
rho = x cos (theta) + y sin (theta)? 這里面rho?是原點(diǎn)到直線(xiàn)的垂直距離,和?theta是由這條垂直線(xiàn)和逆時(shí)針測(cè)量的水平軸形成的角度(該方向因您表示坐標(biāo)系的方式而異。OpenCV 中使用了這種表示)。檢查下面的圖像:
所以如果線(xiàn)在原點(diǎn)以下通過(guò),它會(huì)有一個(gè)正的 rho 并且角度小于 180。如果它在原點(diǎn)之上,而不是取大于 180 的角度,而是取小于 180 的角度,并且 rho被取為陰性。任何垂直線(xiàn)將具有 0 度,水平線(xiàn)將具有 90 度。
現(xiàn)在讓我們看看霍夫變換如何處理線(xiàn)條。任何線(xiàn)都可以用這兩個(gè)術(shù)語(yǔ)表示,(rho, theta).?因此,首先創(chuàng)建一個(gè)二維數(shù)組或累加器(以保存兩個(gè)參數(shù)的值),并且最初設(shè)置為 0。讓行表示(rho)?和列表示?(theta).?數(shù)組的大小取決于您需要的精度。假設(shè)您希望角度精度為 1 度,您將需要 180 列。對(duì)于(rho),可能的最大距離是圖像的對(duì)角線(xiàn)長(zhǎng)度。所以取一像素精度,行數(shù)可以是圖像的對(duì)角線(xiàn)長(zhǎng)度。
考慮一個(gè) 100x100 的圖像,取一個(gè)點(diǎn)。你知道它的 (x,y) 值?,F(xiàn)在在線(xiàn)方程中,輸入值(theta = 0,1,2,....,180)?并檢查?(rho)你得到。對(duì)于每(rho,theta)?對(duì),您在相應(yīng)的累加器中將值增加 1 ,所以現(xiàn)在在累加器中,單元格 (50,90) = 1 以及其他一些單元格。
現(xiàn)在取直線(xiàn)上的第二個(gè)點(diǎn)。執(zhí)行與上述相同的操作。增加與您獲得的單元格相對(duì)應(yīng)的值。這樣,最后,(rho,theta)?單元格累積數(shù)越多,說(shuō)明過(guò)這條線(xiàn)的點(diǎn)越多,當(dāng)大于某一閾值的時(shí)候,我們說(shuō)這是我們要找的一條直線(xiàn).
OpenCV 中的霍夫變換
上面解釋的所有內(nèi)容都封裝在 OpenCV 函數(shù)cv2.HoughLines() 中。它只是返回一組(rho, theta)列表。rho以像素為單位測(cè)量,并且theta以弧度為單位。第一個(gè)參數(shù),輸入圖像應(yīng)該是一個(gè)二值圖像,所以在應(yīng)用霍夫變換之前應(yīng)用閾值或使用精明的邊緣檢測(cè)。第二個(gè)和第三個(gè)參數(shù)分別是rho?和theta的精度。第四個(gè)參數(shù)是閾值,這意味著它應(yīng)該被視為一條線(xiàn)的最低投票數(shù)。請(qǐng)記住,投票數(shù)取決于線(xiàn)上的點(diǎn)數(shù)。所以它可能代表了應(yīng)該檢測(cè)的最小線(xiàn)長(zhǎng)。
Python: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
cv.HoughLines( | image, rho, theta, threshold[, lines[, srn[, stn[, min_theta[, max_theta]]]]] | ) -> | lines |
例子代碼:
import cv2
import numpy as np
img = cv2.imread('../data/sudoku.png')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray,50,150,apertureSize = 3)
lines = cv2.HoughLines(edges,1,np.pi/180,200)
for line in lines:
rho,theta = line[0]
a = np.cos(theta)
b = np.sin(theta)
x0 = a*rho
y0 = b*rho
x1 = int(x0 + 1000*(-b))
y1 = int(y0 + 1000*(a))
x2 = int(x0 - 1000*(-b))
y2 = int(y0 - 1000*(a))
cv2.line(img,(x1,y1),(x2,y2),(0,0,255),2)
cv2.imwrite('houghlines3.jpg',img)
?概率霍夫變換
在霍夫變換中,您可以看到,即使對(duì)于具有兩個(gè)參數(shù)的行,也需要進(jìn)行大量計(jì)算。概率霍夫變換是我們看到的霍夫變換的優(yōu)化。它沒(méi)有考慮所有要點(diǎn)。相反,它只需要一個(gè)足以進(jìn)行線(xiàn)檢測(cè)的隨機(jī)點(diǎn)子集。只是我們必須降低閾值。請(qǐng)參見(jiàn)下圖,它比較了霍夫空間中的霍夫變換和概率霍夫變換。
OpenCV 實(shí)現(xiàn)基于 Matas, J. 和 Galambos, C. 和 Kittler, JV?[55]使用漸進(jìn)式概率霍夫變換對(duì)線(xiàn)條進(jìn)行魯棒檢測(cè)。使用的函數(shù)是cv2.HoughLinesP()。它有兩個(gè)新參數(shù)。
- minLineLength?- 線(xiàn)的最小長(zhǎng)度。比這短的線(xiàn)段被拒絕。
- maxLineGap?- 線(xiàn)段之間的最大允許間隙,將它們視為一條線(xiàn)。
好處是,它直接返回線(xiàn)的兩個(gè)端點(diǎn)。在前面的例子中,你只得到線(xiàn)的參數(shù),你必須找到所有的點(diǎn)。在這里,一切都是直接而簡(jiǎn)單的。
示例代碼:
import cv2
import numpy as np
img = cv2.imread('../data/sudoku.png')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray,50,150,apertureSize = 3)
lines = cv2.HoughLinesP(edges,1,np.pi/180,100,minLineLength=100,maxLineGap=10)
for line in lines:
x1,y1,x2,y2 = line[0]
cv2.line(img,(x1,y1),(x2,y2),(0,255,0),2)
cv2.imwrite('houghlines5.jpg',img)
參考英文鏈接:文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-457351.html
https://vovkos.github.io/doxyrest-showcase/opencv/sphinxdoc/page_tutorial_py_houghlines.html文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-457351.html
到了這里,關(guān)于[圖解]cv2.HoughLines() 和 cv2.HoughLinesP()原理和代碼的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!