前言
在这里我们不硬啃原理(原理可参考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()