【Opencv】Hough變換找直線和圓
阿新 • • 發佈:2019-01-14
目錄
題目
用霍夫變換找出影象中的直線和圓(用彩色直線和圓標記在原圖上)。要求有程式碼,有註釋,有過程、有結果
解決方法
# -*- 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