霍夫變換是一種特徵提取,被廣泛應用在圖像分析、電腦視覺以及數位影像處理。霍夫變換是用來辨別找出物件中的特徵,例如:線條。他的算法流程大致如下,給定一個物件、要辨別的形狀的種類,算法會在參數空間中執行投票來決定物體的形狀,而這是由累加空間(accumulator space)裡的局部最大值來決定。
理論上,霍夫變換就是對於原圖上的每一個直線都在參數空間畫一條線,最終找出參數空間變換線比較密集的地方在對應回到xy 空間坐標系。為了方便理解,下面簡單寫了一下草稿,希望對你有幫助。
注意:建正交直角坐標系過程中, 要選取好以圖片的某個方位左起始點,以像素作為標度。
下圖所示:
圖像是一個 2D 矩陣,超過一些 x 和 y 坐標系,一條線可以描述為y = mx + b
霍夫空間的形成:
輸入的圖片中有兩條粗直線,經過霍夫變換後的結果得到accumaltor矩陣,右圖就是把accumaltor矩陣畫出來,越亮值越大,越黑值越小。在右圖中,有兩個很明顯的亮點, 這兩個亮點分別代表兩條不同參數的直線,與輸入的圖片(下圖)吻合。然後讀取矩陣的兩個最大值就可以得出這兩條線距畫面中心距離以及角度。
類似地,如果給的點坐標越多,形成的霍夫空間為:
Hough 變換是一種用於檢測圖像中簡單形狀(如圓、線等)的特徵提取方法。
"簡單"特徵由形狀表示以參數表示派生。"簡單"形狀僅由幾個參數表示,例如,一條線可以由其斜率和截距表示,也可以用 x、y 和半徑表示。
在我們下面的行示例中,Hough 變換將負責處理圖像上的點並計算霍夫空間中的值。在 OpenCV 中,使用霍夫變換的線路檢測在函數和(概率霍夫變換)中實現。
直線檢測cv2.HoughLinesP()函數原型:
HoughLinesP(image, rho, theta, threshold, lines=None, minLineLength=None, maxLineGap=None)
image:必須是二值圖像,推薦使用canny邊緣檢測的結果圖像;rho: 線段以像素為單位的距離精度,double類型的,推薦用1.0theta:線段以弧度為單位的角度精度,推薦用numpy.pi/180threshod: 累加平面的閾值參數,int類型,超過設定閾值才被檢測出線段,值越大,基本上意味著檢出的線段越長,檢出的線段個數越少。根據情況推薦先用100試試lines:這個參數的意義未知,發現不同的lines對結果沒影響,但是不要忽略了它的存在 minLineLength:線段以像素為單位的最小長度,根據應用場景設置 maxLineGap:同一方向上兩條線段判定為一條線段的最大允許間隔(斷裂),超過了設定值,則把兩條線段當成一條線段,值越大,允許線段上的斷裂越大,越有可能檢出潛在的直線段
import cv2
import numpy as np
original_img = cv2.imread("lane.png", 0)
img = cv2.resize(original_img, None, fx=0.8, fy=0.8,
interpolation=cv2.INTER_CUBIC)
img = cv2.GaussianBlur(img, (3, 3), 0)
edges = cv2.Canny(img, 50, 150, apertureSize=3)
lines = cv2.HoughLines(edges, 1, np.pi / 180, 118) # 這裡對最後一個參數使用了經驗型的值
result = img.copy()
for line in lines:
rho = line[0][0] # 第一個元素是距離rho
theta = line[0][1] # 第二個元素是角度theta
print(rho)
print(theta)
if (theta < (np.pi / 4.)) or (theta > (3. * np.pi / 4.0)): # 垂直直線
pt1 = (int(rho / np.cos(theta)), 0) # 該直線與第一行的交點
# 該直線與最後一行的焦點
pt2 = (int((rho - result.shape[0] * np.sin(theta)) / np.cos(theta)), result.shape[0])
cv2.line(result, pt1, pt2, (255)) # 繪製一條白線
else: # 水平直線
pt1 = (0, int(rho / np.sin(theta))) # 該直線與第一列的交點
# 該直線與最後一列的交點
pt2 = (result.shape[1], int((rho - result.shape[1] * np.cos(theta)) / np.sin(theta)))
cv2.line(result, pt1, pt2, (255), 1) # 繪製一條直線
cv2.imshow('Canny', edges)
cv2.imshow('Result', result)
cv2.waitKey(0)
cv2.destroyAllWindows()
import cv2import numpy as npimg = cv2.imread('lane.jpg', cv2.IMREAD_COLOR)gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)edges = cv2.Canny(gray, 50, 200)lines = cv2.HoughLinesP(edges, 1, np.pi/180, 100,minLineLength=10, maxLineGap=250)for line in lines: x1, y1, x2, y2 = line[0] cv2.line(img, (x1, y1), (x2, y2), (255, 0, 0), 3)
cv2.imshow("Result Image", img) cv2.waitKey() cv2.destroyAllWindows()
類似地還有圓形檢測,這裡就不介紹了,感興趣的替換一下面的代碼,並且找有圓形照片測試一下函數就可以。
霍夫圓形檢測cv2.HoughCircles(image, method, dp, minDist[, circles[, param1[, param2[, minRadius[, maxRadius]]]]]) → circles
參數說明:image- 8位,單通道, 灰度輸入圖像。circles- 找到的圓的輸出向量。每個向量被編碼為3元素的浮點向量 (x,y,半徑)。circle_storage - 在C函數中,這是一個將包含找到的圓的輸出序列的內存存儲。method- 使用檢測方法。目前,唯一實現的方法是 CV_HOUGH_GRADIENT,基本上是 21HT,在[Yuen90]中有描述 。dp - 累加器解析度與圖像解析度的反比。例如,如果 dp = 1,則累加器具有與輸入圖像相同的解析度。如果 dp = 2,則累加器的寬度和高度都是一半。minDist -檢測到的 圓的中心之間的最小距離。如果參數太小,除了真正的參數外,可能會錯誤地檢測到多個鄰居圈。如果太大,可能會錯過一些圈子。param1 - 第一個方法特定的參數。在CV_HOUGH_GRADIENT的情況下, 兩個傳遞給Canny()邊緣檢測器的閾值較高(較小的兩個小於兩倍)。param2 - 第二種方法參數。在CV_HOUGH_GRADIENT的情況下,它是檢測階段的圓心的累加器閾值。越小,可能會檢測到越多的虛假圈子。首先返回對應於較大累加器值的圈子。minRadius -最小圓半徑。maxRadius - 最大圓半徑。參考文獻
https://zhuanlan.zhihu.com/p/47649796https://docs.opencv.org/2.4/modules/imgproc/doc/feature_detection.html?highlight=houghlines#houghlineshttps://docs.opencv.org/2.4/doc/tutorials/imgproc/imgtrans/hough_lines/hough_lines.html