1. 程式人生 > >【Opencv】Hough變換找直線和圓

【Opencv】Hough變換找直線和圓

目錄

題目

解決方法

完整程式碼

Hough引數詳解

總結

參考


題目

用霍夫變換找出影象中的直線和圓(用彩色直線和圓標記在原圖上)。要求有程式碼,有註釋,有過程、有結果

 

解決方法

# -*- coding: UTF-8 -*-
import cv2
import numpy as np
# 1.載入圖片,轉為二值圖
img = cv2.imread('image.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 由於Canny只能處理灰度圖,所以將讀取的影象轉成灰度圖。
cv2.imshow('gray', gray)

gray = cv2.GaussianBlur(gray, (3, 3), 0)  # 用高斯平滑處理原影象降噪。
cv2.imshow('Gaussian smoothing', gray)

edges = cv2.Canny(gray, 70, 220)
cv2.imshow('edges', edges)


 

# 2.1.霍夫直線變換
lines = cv2.HoughLinesP(edges, 1, np.pi / 180, 25, minLineLength=19, maxLineGap=17)
'''
image: 必須是二值影象,推薦使用canny邊緣檢測的結果影象
rho: 線段以畫素為單位的距離精度,推薦用1.0
theta: 線段以弧度為單位的角度精度,推薦用numpy.pi/180
minLineLength:表示直線長度的閾值,超過設定閾值才被檢測出線段,值越大,基本上意味著檢出的線段越長,檢出的線段個數越少
MaxLineGap:同一方向上兩條線段判定為一條線段的最大允許間隔(斷裂),小於了設定值,則把兩條線段當成一條線段

返回值為直線的起點和終點。
'''

# 2.2.霍夫圓變換
circles = cv2.HoughCircles(edges, cv2.HOUGH_GRADIENT, 1, 100, param2=30)
circles = np.int0(np.around(circles))

# 3.將檢測到的畫出來
lines1 = lines[:, 0, :]  # 提取為二維
for x1, y1, x2, y2 in lines1[:]:
    cv2.line(img, (x1, y1), (x2, y2), (0, 0, 255), 2)

for i in circles[0, :]:
    cv2.circle(img, (i[0], i[1]), i[2], (0, 0, 255), 2)  # 畫出外圓
    # cv2.circle(img, (i[0], i[1]), 2, (0, 255, 0), 3)  # 畫出圓心

cv2.imshow('Result', img)
cv2.waitKey(0)

完整程式碼

# -*- coding: UTF-8 -*-
import cv2
import numpy as np
 
# 1.載入圖片,轉為二值圖
img = cv2.imread('image.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 由於Canny只能處理灰度圖,所以將讀取的影象轉成灰度圖。
cv2.imshow('gray', gray)
gray = cv2.GaussianBlur(gray, (3, 3), 0)  # 用高斯平滑處理原影象降噪。
cv2.imshow('Gaussian smoothing', gray)
 
edges = cv2.Canny(gray, 70, 220)
cv2.imshow('edges', edges)
 
# 2.1.霍夫直線變換
lines = cv2.HoughLinesP(edges, 1, np.pi / 180, 25, minLineLength=19, maxLineGap=17)
'''
image: 必須是二值影象,推薦使用canny邊緣檢測的結果影象
rho: 線段以畫素為單位的距離精度,推薦用1.0 
theta: 線段以弧度為單位的角度精度,推薦用numpy.pi/180 
minLineLength:表示直線長度的閾值,超過設定閾值才被檢測出線段,值越大,基本上意味著檢出的線段越長,檢出的線段個數越少
MaxLineGap:同一方向上兩條線段判定為一條線段的最大允許間隔(斷裂),小於了設定值,則把兩條線段當成一條線段
返回值為直線的起點和終點。
'''
 
# 2.2.霍夫圓變換
circles = cv2.HoughCircles(edges, cv2.HOUGH_GRADIENT, 1, 100, param2=30)
circles = np.int0(np.around(circles))
 
# 3.將檢測到的畫出來
lines1 = lines[:, 0, :]  # 提取為二維
for x1, y1, x2, y2 in lines1[:]:
    cv2.line(img, (x1, y1), (x2, y2), (0, 0, 255), 2)
 
for i in circles[0, :]:
    cv2.circle(img, (i[0], i[1]), i[2], (0, 0, 255), 2)  # 畫出外圓
    # cv2.circle(img, (i[0], i[1]), 2, (0, 255, 0), 3)  # 畫出圓心
 
cv2.imshow('Result', img)
cv2.waitKey(0)

Hough引數詳解

cv2.HoughCircles(image,method,dp,minDist[, circles[,param1, param2[,minRadius[,maxRadius]]]]])

其返回N個圓的資訊儲存在1×N×的ndarray。

image 不用多說,輸入矩陣
method cv2.HOUGH_GRADIENT 也就是霍夫圓檢測,梯度法
dp 計數器的解析度影象畫素解析度與引數空間解析度的比值(官方文件上寫的是影象解析度與累加器解析度的比值,它把引數空間認為是一個累加器,畢竟裡面儲存的都是經過的畫素點的數量),dp=1,則引數空間與影象畫素空間(解析度)一樣大,dp=2,引數空間的解析度只有畫素空間的一半大
minDist 圓心之間最小距離,如果距離太小,會產生很多相交的圓,如果距離太大,則會漏掉正確的圓
param1 canny檢測的雙閾值中的高閾值,低閾值是它的一半(如果你的圓找不到,可以將該引數變小點)
param2 最小投票數(基於圓心的投票數)
minRadius 需要檢測院的最小半徑
maxRadius 需要檢測院的最大半徑

總結

我對hough變換的理解:你的圓一定要非常明顯,通過影象處理的方式將圓的邊界變得足夠清晰,然後使用hough變換才有效。

參考

https://blog.csdn.net/zuliang001/article/details/81607548 

https://blog.csdn.net/dz4543/article/details/80699431