霍夫變換---OpenCV-Python開發指南(35)
目錄
什么是霍夫變換
HoughLines函數
HoughLines實戰
HoughLinesP實戰
HoughCircles實戰
什么是霍夫變換
霍夫變換是一種在圖像中尋找直線,圓形以及其他簡單形狀的方法。霍夫變換采用類似于投票的方式來獲取當前圖像內的形狀集合,該變換由Paul Hough(霍夫)于1962年首次提出。
最初的霍夫變換只能用于檢測直線,經過發展后,霍夫變換不僅能夠識別直線,還能識別其他簡單的圖形結構,常見的有圓形,橢圓等。
HoughLines函數
在OpenCV中,它給我們提供了cv2.HoughLines()函數來實現霍夫直線變換,該函數要求所有操作的原圖是一個二值圖像,所以在進行霍夫變換之前,需要將圖像進行二值化處理。或者進行Canny邊緣檢測。
其完整定義如下:
def HoughLines(image, rho, theta, threshold, lines=None, srn=None, stn=None, min_theta=None, max_theta=None):
1
image:原始圖形,必須是8位單通道的二值圖像
rho:以像素為單位的距離r的精度。一般情況下,使用的精度是1
theta:為角度θ的精度。一般情況下,使用的精度是Π/180,表示要搜索所有可能的角度
threshold:閾值。該值越小,判定出直線就越多。識別直線時,要判定多少個點位于該直線上。在判定直線是否存在時,對直線所穿過的點的數量進行評估,如果直線所穿過的點的數量小于閾值,則認為這些點恰好在算法構成直線,但是在原始圖像中該直線并不存在;如果大于閾值,則認為直線存在。所以,如果閾值越小,就會得到較多的直線;閾值越大,就會得到較少的直線
lines:返回值,它的每個元素都是一對浮點數,表示檢測到的直線的參數,即(r,θ)。是numpy.ndarray類型。
HoughLines實戰
了解了函數常用的參數之后。下面,我們通過一個棋盤來進行霍夫變換。代碼如下:
import cv2 import numpy as np import matplotlib.pyplot as plt img = cv2.imread("35.jpg") plt.subplot(121) plt.imshow(img, cmap="gray") plt.axis('off') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) edges = cv2.Canny(gray, 50, 150, apertureSize=3) lines = cv2.HoughLines(edges, 1, np.pi / 180, 140) 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, 255, 0), 2) plt.subplot(122) plt.imshow(img, cmap="gray") plt.axis('off') plt.show()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
運行之后,效果如下:
HoughLinesP實戰
使用HoughLines雖然可以完成霍夫變換,但其本身存在非常嚴重的誤檢測。為了解決這個問題,OpenCV加入了概率霍夫變換函數cv2.HoughLinesP()函數。
其完整定義如下:
def HoughLinesP(image, rho, theta, threshold, lines=None, minLineLength=None, maxLineGap=None):
1
image:原始圖像,比如為8位單通道二值圖像
rho:同上
theta:同上
threshold:同上
lines:同上
minLineLength:用來控制”接受直線的最小長度“的值。默認值為0
maxLineGap:用來控制接受共線線段之間的最小間隔,即在一條直線中兩點的最大間隔。如果兩點間的間隔超過了參數maxLineGap的值,就認為這兩點不在一條直線上。默認值為0
將上面的例子,使用HoughLinesP改進以下:
import cv2 import numpy as np import matplotlib.pyplot as plt img = cv2.imread("35.jpg") plt.subplot(121) plt.imshow(img, cmap="gray") plt.axis('off') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) edges = cv2.Canny(gray, 50, 150, apertureSize=3) lines = cv2.HoughLinesP(edges, 1, np.pi / 180, 10, 10) for line in lines: x1, y1, x2, y2 = line[0] cv2.line(img, (x1, y1), (x2, y2), (255, 0, 0), 5) plt.subplot(122) plt.imshow(img, cmap="gray") plt.axis('off') plt.show()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
運行之后,效果如下:
可以看到,這里我們通過函數HoughLinesP,將棋盤線完整的全標記出來了。
HoughCircles實戰
霍夫變換出來用來檢測直線外,我們還可以用來檢測其他的幾何對象。實際上,只要是能用一個方程式表示的對象,都適合用霍夫變換來檢測。
其中,我們就可以使用霍夫圓變換來檢測圖像中的圓。這里我們只需要考慮圓心坐標(x,y)與半徑r共3個參數。
在OpenCV中要經過2個步驟:
找出可能存在圓的位置(圓心)
根據1計算半徑
在OpenCV中,它給我們提供的霍夫圓變換函數為cv2.HoughCircle()。該函數也是將Canny邊緣檢測與霍夫變換結合,唯一的區別是,不要我們進行Canny邊緣檢測,該函數自動先進行Canny邊緣檢測。
其完整定義如下:
def HoughCircles(image, method, dp, minDist, circles=None, param1=None, param2=None, minRadius=None, maxRadius=None):
1
image:原始圖像,8位單通道灰度圖像
method:檢測方法,HOUGH_GRADIENT是唯一可用的參數值。該參數代表霍夫圓檢測中兩輪檢測所使用的方法
dp:累計器分辨率,它是一個分割比例,用來指定圖像分辨率與圓心累加器分辨率的比例。例如,如果dp=1,則輸入圖像和累加器具有相同的分辨率
minDist:圓心間最小間距。該值被作為閾值來使用,如果存在圓心間距小于該值的多個圓,則僅有一個會被檢測出來。因此,如果該值太小,則會有很多臨近的圓被檢測出來;如果該值很大,則可能會在檢測時漏掉很多圓
circles:返回值,有圓心坐標和半徑構成的numpy.ndarray類型。
param1:該參數缺省,默認100。它對應的是Canny邊緣檢測器的高閾值(低閾值是高閾值的二分之一)
param2:圓心位置必須受到的投票數。只有在第1論篩選的過程中,投票數超過該值的圓,才有資格進入第2輪的篩選。因此,該值越大,檢測到的圓越少;該值越小,檢測到的圓越多。也是缺省值,默認100
minRadius:圓半徑最小值,小于該值的圓不會被檢測出來。也是缺省值,默認0,不起作用
maxRadius:圓半徑的最大值,大于該值的圓不會被檢測出來。也是缺省值,默認0,不起作用
下面,我們來用一個奧運五環的照片,進行霍夫圓變換。代碼如下:
import cv2 import numpy as np import matplotlib.pyplot as plt img = cv2.imread("35_1.jpg") plt.subplot(121) plt.imshow(img, cmap="gray") plt.axis('off') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1, 300, param1=50, param2=20,minRadius=0,maxRadius=0) circles = np.uint16(np.around(circles)) for i in circles[0, :]: cv2.circle(img, (i[0], i[1]), i[2], (255, 0, 0), 12) cv2.circle(img, (i[0], i[1]), 2, (255, 0, 0), 12) plt.subplot(122) plt.imshow(img, cmap="gray") plt.axis('off') plt.show()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
運行之后,效果如下:
OpenCV Python
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。