1. 程式人生 > >OpenCV 學習筆記03 直線和圓檢測

OpenCV 學習筆記03 直線和圓檢測

ray 一半 .net 效果 print 標準 不錯 msh article

檢測邊緣和輪廓不僅重要,還經常用到,它們也是構成其他復雜操作的基礎。

直線和形狀檢測與邊緣和輪廓檢測有密切的關系。

霍夫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 直線和圓檢測