OpenCV 學習筆記03 直線和圓檢測
檢測邊緣和輪廓不僅重要,還經常用到,它們也是構成其他復雜操作的基礎。
直線和形狀檢測與邊緣和輪廓檢測有密切的關系。
霍夫hough 變換是直線和形狀檢測背後的理論基礎。霍夫變化是基於極坐標和向量開展的,常規的直線是二維平面直角坐標上建立的
y = kx + b
該直線的參數 k、b 存在有負值,負值則不便於計算(有資料這樣撰寫的,沒有深究,就以此為參考吧),對於極坐標而言,其表達式為
r=x * cosθ + y * sinθ
參數r、θ均可以為正數(極坐標r值永遠是大於等於0的數,θ就可以用0~360度表示方便計算。其中r表示直線到原點的最短距離,θ表示x軸與原點到直線最短距離的夾角)。
1 直線檢測
直線檢測可通過 HoughLines 和 HoughLinesP 函數來完成,
- HoughLines - 使用標準的Hough變換
- HoughLinesP - 使用概率Hough變換,因此名稱後有一個P
HoughLinesP 屬於標準Hough變換的優化版本,它不僅分析點點的子集並且還會估計這些點都屬於一條直線的概率。該函數計算代價會少一些,執行會變得更快一些。
HoughLinesP 函數的應用
作用:通過概率Hough變換算法實現對二值圖像中的線檢測
cv2.HoughLinesP(image, rho, theta, threshold[, minLineLength[, maxLineGap]]) -> lines
參數:
image - 8-bit、單通道single-channel二進制源圖像;
HoughLines函數會接受由Canny邊緣檢測濾波器處理過的單通道二值圖像,但不一定必須經過Canny處理;不過經過去噪且只有邊緣的圖像當作Hough變換的輸入會得到不錯的效果,因此使用Canny濾波器的返回值是一個普遍的慣例。
rho - 累加器的距離分辨率,單位為像素,一般取值為1。
theta - 累加器的角度分辨率,單位為弧度,一般取值為np.pi/180
threshold - 累加器的閾值參數,只有落在直線上的像素點數大於thresh值才會返回直線。
minLineLength - 最小線段長度,小於該值的直線會被舍棄掉
maxLineGap - 同一直線中允許的最大間隙值(gap between points)
返回值:
lines - 矢量線,每行有 4 個元素組成,(x_1, y_1, x_2, y_2),(x_1, y_1) 和 (x_2, y_2) 分別是開始點和結束點
示例:
1 import cv2 2 import numpy as np 3 4 img = cv2.imread(‘lines.png‘) 5 # 將圖片轉為灰度圖 6 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 7 # 邊緣輪廓檢測 8 edges = cv2.Canny(gray,50,120) 9 10 minLineLength = 20 11 maxLineGap = 5 12 lines = cv2.HoughLinesP(edges,1,np.pi/180,100,minLineLength,maxLineGap) 13 14 # 打印lines.shape值,(29, 1, 4) 15 # print(lines.shape) 16 # 打印lines值 17 # print(lines) ♦ 18 for line in lines: 19 # 打印line[0].shape,(4,) 20 # print(line[0].shape) 21 # 打印line值 22 # print(line[0]) ♦ ♦ 23 cv2.line(img,(line[0][0],line[0][1]),(line[0][2],line[0][3]),(255,255,0),5) 24 25 26 # 邊緣檢測輪廓繪圖 27 cv2.imshow("edges", edges) 28 # Hough變換後繪圖 29 cv2.imshow("Hough", img) 30 cv2.waitKey() 31 cv2.destroyAllWindows()
另,第一個 ♦ 輸出值(第 17 行)
[[[ 82 356 943 356]] [[ 82 358 943 358]] [[455 333 455 39]] [[457 333 457 39]] [[282 331 309 331]] [[145 682 413 682]] [[562 121 818 121]] [[373 613 376 618]] [[402 663 405 668]] [[732 708 843 597]] [[560 330 560 123]] [[355 582 365 599]] [[561 331 819 331]] [[533 652 729 652]] [[285 461 355 581]] [[819 330 819 122]] [[534 538 730 538]] [[196 593 242 514]] [[251 498 254 493]] [[145 681 178 624]] [[457 511 457 455]] [[457 668 457 713]] [[457 617 457 667]] [[732 483 843 594]] [[455 433 455 489]] [[730 537 730 483]] [[457 597 457 541]] [[532 651 532 540]] [[732 484 843 595]]]
另,第二個 ♦ ♦ 輸出值(第 17 行)
[ 82 356 943 356] [ 82 358 943 358] [455 333 455 39] [457 333 457 39] [282 331 309 331] [145 682 413 682] [562 121 818 121] [373 613 376 618] [402 663 405 668] [732 708 843 597] [560 330 560 123] [355 582 365 599] [561 331 819 331] [533 652 729 652] [285 461 355 581] [819 330 819 122] [534 538 730 538] [196 593 242 514] [251 498 254 493] [145 681 178 624] [457 511 457 455] [457 668 457 713] [457 617 457 667] [732 483 843 594] [455 433 455 489] [730 537 730 483] [457 597 457 541] [532 651 532 540] [732 484 843 595]
圖片對比
我們可以發現,原圖在Canny函數檢測後,其輪廓均能被有效檢測出來,在霍夫Hough變換時,需要進一步修改參數才能進行有效檢測。
2 圓檢測
上述代碼是針對直線檢測的,函數HoughCircles是實現圓的檢測。
HoughCircles函數的應用
作用:使用Hough變換在灰度圖像中查找 / 檢測圓圈。
HoughCircles(image, method, dp, minDist[, circles[, param1[, param2[, minRadius[, maxRadius]]]]]) -> circles
參數:
image - 8位單通道二進制圖像。
method - 檢測方法,唯一實現的方法是 HOUGH_GRADIENT
dp - 累加器分辨率,其與圖像分辨率的反比,若dp = 1,則累加器具有與輸入圖像相同的分辨率,若dp = 2,則累加器的寬度和高度為輸入圖像的一半。
minDist - 檢測到的圓的中心之間的最小距離,若太小,則除真實的一個外,可能錯誤地檢測到多個相鄰的圓圈,若太大,則可能會遺漏一些圓
param1 - 第一個特定於方法的參數。在#HOUGH_GRADIENT的情況下,它是傳遞給Canny邊緣檢測器的兩個較高閾值(較低的一個小兩倍)。
param2 - 第二種方法特定參數。在#HOUGH_GRADIENT的情況下,它是檢測階段圓心的累加器閾值。它越小,可以檢測到更多的假圓圈。將首先返回與較大累加器值對應的圓圈。
minRadius - 最小圓半徑
maxRadius - 最大圓半徑
示例:
import cv2 import numpy as np planets = cv2.imread(‘planet_glow.png‘) gray_img = cv2.cvtColor(planets, cv2.COLOR_BGR2GRAY) # 進行中值濾波操作 # 中值濾波將圖像的每個像素用鄰域 (以當前像素為中心的正方形區域)像素的 中值 代替 img = cv2.medianBlur(gray_img,5) cimg = cv2.cvtColor(img,cv2.COLOR_GRAY2BGR) circles = cv2.HoughCircles(img,cv2.HOUGH_GRADIENT,1,120,param1=100,param2=30,minRadius=0,maxRadius=0) print(help(cv2.HoughCircles)) circles = np.uint16(np.around(circles)) for i in circles[0,:]: # draw the outer circle cv2.circle(planets,(i[0],i[1]),i[2],(0,255,0),2) # draw the center of the circle cv2.circle(planets,(i[0],i[1]),2,(0,0,255),3) cv2.imwrite("planets_circles.jpg",planets) cv2.imshow(‘HoughCircles‘,planets) cv2.waitKey() cv2.destroyAllWindows
運行:
參考:
極坐標系
OpenCV(Python)學習-霍夫變化直線和圓檢測
opencv 直線和圓檢測,該文中僅有代碼,可以借鑒
圖像處理之霍夫變換圓檢測算法
hough變換是如何檢測出直線和圓的
原圖:
OpenCV 學習筆記03 直線和圓檢測