【opencv学习】【hough圆检测】

import cv2
import numpy as np

# 圆的检测原理
# 霍夫梯度法:先确定圆心,再确定半径
# 把原图做一次 Canny 边缘检测,得到边缘检测的二值图。
# 圆的边缘点切线的垂直方向,也就是梯度方向过圆点,所以我们可以遍历图像的所有点,
# 对每个像素点计算梯度,比如Sobel算子,对该直线上的所有像素点进行投票,
# 最后选取超过阈值的某个像素点,为了避免选取过多的圆心,
# 可以把一个像素点周围相差不大的像素点看做成一个圆心,确定圆心后再计算以改点为圆心的最佳半径
# 该方法优点:速度快
# 缺点:圆心可能会有偏差,这个方法对噪声比较敏感,所以可以先做中值滤波,做完之后再用hough圆变换

# 总体流程:
# 1.加载一幅图像
# 2.执行高斯模糊以降低噪声:GaussianBlur
# 3.转成灰度图:cvtColor
# 4.执行霍夫圆变换:HoughCircles

# HoughCircles 函数参数解析

# image,输入图像,即源图像,需要为 8 位的灰度单通道图像。
# method,使用的检测方法,目前 OpenCV 中就霍夫梯度法一种可以使用,标识符为 HOUGH_GRADIENT。
# dp,累加面分辨率(大小) = 原始图像分辨率(大小) × 1/dp。默认 dp = 1 时,两者分辨率相同。
# minDist,两个圆心之间的最小距离。若两圆心距离 < minDist,则认为是同一个圆。
# param1,Canny 边缘检测的高阈值,低阈值被自动置为高阈值的一半,默认为 100。
# param2,累加平面某点是否是圆心的判定阈值。它越大,能通过检测的圆就更接近完美的圆形,默认为 100。
# minRadius,圆半径的最小值。默认为 0。
# maxRadius,圆半径的最大值,默认为 0。

# 展示图像,封装成函数
def cv_show_image(name, img):
    cv2.imshow(name, img)
    cv2.waitKey(0)  # 等待时间,单位是毫秒,0代表任意键终止
    cv2.destroyAllWindows()

def detect_circle_demo(image):
    # 第一步:先进行滤波,去除噪声点
    # dst = cv.bilateralFilter(image, 0, 150, 5)  #高斯双边模糊,不太好调节,霍夫噪声敏感,所以要先消除噪声
    # cv.imshow("1",dst)
    # dst = cv.pyrMeanShiftFiltering(image,5,100)  #均值迁移,EPT边缘保留滤波,霍夫噪声敏感,所以要先消除噪声
    # cv.imshow("2", dst)
    dst = cv2.GaussianBlur(image, (13, 15), 15)  # 使用高斯模糊,修改卷积核ksize也可以检测出来
    # cv.imshow("3", dst)

    # 第二步:转成灰度图
    gray = cv2.cvtColor(dst, cv2.COLOR_BGR2GRAY)
    # ret, gray = cv2.threshold(gray, 100, 255, cv2.THRESH_BINARY)
    cv_show_image('gray', gray)

    # 第三步:进行圆检测
    circles = cv2.HoughCircles(image=gray, method=cv2.HOUGH_GRADIENT, dp=1, minDist=20,
                               param1=50, param2=30, minRadius=0, maxRadius=0)
    circles = np.uint16(np.around(circles))  # around对数据四舍五入,为整数
    for i in circles[0, :]:
        cv2.circle(image, (i[0], i[1]), i[2], (0, 0, 255), 2)  # 圆轮廓
        cv2.circle(image, (i[0], i[1]), 2, (255, 0, 0), 2)  # 圆心

    cv2.imshow("detect_circle_demo", image)


src = cv2.imread("images/circle1.png")  # 读取图片

# cv2.namedWindow("input image", cv2.WINDOW_AUTOSIZE)  # 创建GUI窗口,形式为自适应
# cv2.imshow("input image", src)  # 通过名字将图像和窗口联系

detect_circle_demo(src)

cv2.waitKey(0)  # 等待用户操作,里面等待参数是毫秒,我们填写0,代表是永远,等待用户操作
cv2.destroyAllWindows()  # 销毁所有窗口

效果图:
请添加图片描述

请添加图片描述

猜你喜欢

转载自blog.csdn.net/qq_29367075/article/details/123025762