霍夫變換是一種特徵提取,被普遍應用在圖像分析、電腦視覺以及數位影像處理。霍夫變換是用來辨別找出物件中的特徵,例如:線條。他的算法流程大體以下,給定一個物件、要辨別的形狀的種類,算法會在參數空間中執行投票來決定物體的形狀,而這是由累加空間(accumulator space)裏的局部最大值來決定。javascript
理論上,霍夫變換就是對於原圖上的每個直線都在參數空間畫一條線,最終找出參數空間變換線比較密集的地方在對應回到xy 空間座標系。爲了方便理解,下面簡單寫了一下草稿,但願對你有幫助。html
注意:建正交直角座標系過程當中, 要選取好以圖片的某個方位左起始點,以像素做爲標度。java
下圖所示:
python
圖像是一個 2D 矩陣,超過一些 x 和 y 座標系,一條線能夠描述爲y = mx + b
算法
霍夫空間的造成:
編程
輸入的圖片中有兩條粗直線,通過霍夫變換後的結果獲得accumaltor矩陣,右圖就是把accumaltor矩陣畫出來,越亮值越大,越黑值越小。在右圖中,有兩個很明顯的亮點, 這兩個亮點分別表明兩條不一樣參數的直線,與輸入的圖片(下圖)吻合。而後讀取矩陣的兩個最大值就能夠得出這兩條線距畫面中心距離以及角度。微信
相似地,若是給的點座標越多,造成的霍夫空間爲:
app
圖像如何使用霍夫變換?
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 np# Read imageimg = cv2.imread('lane.jpg', cv2.IMREAD_COLOR)# Convert the image to gray-scalegray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# Find the edges in the image using canny detectoredges = cv2.Canny(gray, 50, 200)# Detect points that form a linelines = cv2.HoughLinesP(edges, 1, np.pi/180, 100,minLineLength=10, maxLineGap=250)# Draw lines on the imagefor line in lines: x1, y1, x2, y2 = line[0] cv2.line(img, (x1, y1), (x2, y2), (255, 0, 0), 3)# Show result
cv2.imshow("Result Image", img) cv2.waitKey() ##記得寫上,不然閃退cv2.destroyAllWindows()
相似地還有圓形檢測,這裏就不介紹了,感興趣的替換一下面的代碼,而且找有圓形照片測試一下函數就能夠。
霍夫圓形檢測method, dp, minDist[, circles[, param1[, param2[, minRadius[, maxRadius]]]]]) → circles
:8位,單通道, 灰度輸入圖像。 找到的圓的輸出向量。每一個向量被編碼爲3元素的浮點向量 (x,y,半徑)。 circle_storage - 在C函數中,這是一個將包含找到的圓的輸出序列的內存存儲。使用檢測方法。目前,惟一實現的方法是 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
本文分享自微信公衆號 - AI科技與算法編程(kangsinx)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。