前言
在这里我们不硬啃原理(原理可参考Opencv[人民邮电出版社出版])。
一 霍夫检测原理-圆形检测
霍夫变换检测圆形和直线相似,都是将图像空间x-y直角坐标系中的像素投影到参数空间中,之后寻找交点。
HoughCircles(InputArray image,
OutputArray circles,
int method,
double dp,
double minDist,
double param1 = 100,
double param2 = 100,
int minRadius = 0,
int maxRadius = 0);
image: 输入图像,必须是CV-8U的单通道图像。
circles: 检测圆的输出量,每个圆用三个参数表示,分别为:圆心坐标(x,y)、圆的半径(r)
method: 检测圆的方法标志,支持Hough_GRADIENT
dp: 离散化时分辨率与图像分辨率的反比
minDist: 圆心之间的最小距离,如果太小多个相邻圆可能被错误的检测成一个重合圆。如果太大,某些圆可能检测不出来。
param1: 使用Hough_GRADIENT方法检测圆时,传递给Canny边缘检测器的两个阈值的较大值
param2: 使用Hough_GRADIENT方法检测圆时,检测圆形的累加器阈值,阈值越大则检测圆形越精确
minRadius: 检测圆的最小圆半径
maxRadius: 检测圆的最大圆半径\
二.动手开撸
开撸之前的准备工作:我们拿倒图像后,先检查是三通道还是单通道,三通道则转单通道,接下来就需要传统的滤波降噪等操作的处理,这样是为了剔除不必要的干扰.
示例图像:
进行边缘检测处理
这一步没啥好说的,都是一些基础的操作
img = cv2.imread('4.jpg')
# 将图像转换为灰度图像
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 高斯滤波降噪
gaussian_img = cv2.GaussianBlur(gray_img, (7, 7), 0)
# 利用Canny进行边缘检测
edges_img = cv2.Canny(gaussian_img, 80, 180, apertureSize=3)
进行检测圆
在检测圆的过程中需要注意这个例图中圆的半径有大有小,圆与圆之间的距离也都不一样,我们需要调整minRadius和maxRadius确定能把所有圆检测出来,确定了能检测所有圆后为了避免乱画圆,就需要调整minDist。
(大家可以自行更改参数进行优化)
# 自动检测圆
circles1 = cv2.HoughCircles(edges_img, cv2.HOUGH_GRADIENT, 1, 100, param1=300, param2=10, minRadius=5, maxRadius=95)
circles = circles1[0, :, :]
circles = np.uint16(np.around(circles))
for i in circles[:]:
cv2.circle(img, (i[0], i[1]), i[2], (0, 0, 255), 2)
cv2.imshow('img', edges_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
完整DEMO:
import cv2
import numpy as np
img = cv2.imread('4.jpg')
# 将图像转换为灰度图像
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 高斯滤波降噪
gaussian_img = cv2.GaussianBlur(gray_img, (7, 7), 0)
# 利用Canny进行边缘检测
edges_img = cv2.Canny(gaussian_img, 80, 180, apertureSize=3)
# 自动检测圆
circles1 = cv2.HoughCircles(edges_img, cv2.HOUGH_GRADIENT, 1, 100, param1=300, param2=10, minRadius=5, maxRadius=95)
circles = circles1[0, :, :]
circles = np.uint16(np.around(circles))
for i in circles[:]:
cv2.circle(img, (i[0], i[1]), i[2], (0, 0, 255), 2)
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()