今天繼續討論直線偵測與圓形偵測技術
直線偵測(Line Detection)的技術,目標為偵測影像中的直線,簡單明瞭。最典型的直線偵測技術,稱為 **霍夫轉換(Hough Transform)**。
霍夫轉換是一種特徵擷取技術,主要是將數位影像的空間座標經過轉換成參數空間,這個參數空間稱為霍夫域(Hough Doamin)。由於霍夫轉換適合用來辨識物件的幾何特徵,例如:直線、圓形等,被廣泛應用於影像處理、影像分析與電腦視覺應用。
霍夫轉換直線偵測的演算法步驟如下:
(1) 使用邊緣偵測器偵測影像物件的邊緣
(2) 定義
,D為影像的最大距離
(3) 建立累積器,用來儲存(ρ,θ)參數空間的量化值。
(4) 根據每個邊緣點,計算(ρ,θ)值,並於累積器中進行累加
(5) 累積器的局部最大值,即是對應偵測直線的(ρ,θ)值
程式碼如下:
import numpy as np
import cv2
import math
img1 = cv2.imread("D:\Desktop\IThome\line.bmp", -1)
img2 = img1.copy()
gray = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, 50, 200)
lines = cv2.HoughLines(edges, 1, math.pi / 180.0, 120)
if lines is not None:
a, b, c = lines.shape
for i in range(a):
rho = lines[i][0][0]
theta = lines[i][0][1]
a = math.cos(theta)
b = math.sin(theta)
x0, y0 = a * rho, b * rho
pt1 = (int(x0 + 1000 * (-b)), int(y0 + 1000 * a))
pt2 = (int(x0 - 1000 * (-b)), int(y0 - 1000 * a))
cv2.line(img2, pt1, pt2, (255, 0, 0), 1, cv2.LINE_AA)
cv2.imshow("Original", img1)
cv2.imshow("Canny", edges)
cv2.imshow("After", img2)
cv2.waitKey()
cv2.destroyAllWindows()
在此,採用Canny邊緣偵測用來偵測可能的邊緣點。霍夫轉換後,需決定局部最大值的門檻值(本範例門檻設為120,表示值線長度須超過120個像素)。
結果如下:
除了直線偵測外,霍夫轉和可以用來偵測數位影像中的圓形物件,稱為 **圓形偵測(Circle Detection)**。
根據圓的方程式:
其中為圓心座標,r為半徑。因此我們可以使用這三個參數作為霍夫域建立累積器,原理與上面的直線偵測類似。然而這樣的累積器所需要的記憶體空間較大,而且搜尋的空間相當大,因此並不實用。
OpenCV提供圓偵測演算法,在效率上進行改良,稱為霍夫梯度法(Hough Gradient Method)。
程式碼如下:
import numpy as np
import cv2
import math
img1 = cv2.imread("D:\Desktop\IThome\circle3.bmp", -1)
img2 = img1.copy()
gray = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1, 150 ,200, 50,
minRadius = 120, maxRadius = 200)
circles = np.uint16(np.around(circles))
if circles is not None and circles[0][0].ndim == 1:
for i in circles[0, :]:
cv2.circle(img2, (i[0], i[1]), i[2], (0, 255, 0), 2)
cv2.circle(img2, (i[0], i[1]), 2, (0, 0, 255), 3)
cv2.imshow("Original", img1)
cv2.imshow("After", img2)
cv2.waitKey()
cv2.destroyAllWindows()
在本程式中,霍夫圓偵測是使用Canny邊緣偵測法。在此,根據數位影像設定圓的最小半徑與最大半徑,分別為120與200。
結果如下: