OpenCV+python:圆检测

1,圆检测基本原理
对霍夫变换有了这样一种理解-----实际上就是坐标变换,是一种数学上的变换,然后再转换到参数坐标系进行讨论,最终确定待检测圆(或者其他形状)的数学方程。在极坐标系下,圆的数学表达式如下:
OpenCV+python:圆检测_第1张图片类似于霍夫变换直线检测,这里我们也定义一个累加器,但是与直线检测不同的是,直线检测参数是二维的,而圆的参数是三维的。如果一个圆上的点,都沿着其梯度方向画线,那么所有线的角点就是圆心。OpenCV中的霍夫梯度算法就利用这个原理,先计算可能的圆心,然后再去计算可能的半径。

霍夫梯度检测圆形的算法如下:
I、估计圆心
(1)把原图做一次Canny边缘检测,得到边缘检测的二值图
(2) 对原始图像执行一次Sobel算子,计算出所有像素的邻域梯度值
(3)初始化圆心空间N(a,b),令所有的N(a,b)=0
(4)遍历Canny边缘二值图中的所有非零像素点,沿着梯度方向画线,将线段经过的所有累加器中的点(a,b)的N(a,b)+=1
(5)统计排序N(a,b),得到可能的圆心
II、估计半径(针对某一个圆心a,b)
(1)计算Canny图中所有非0点距离圆心的距离
(2)距离从小到大排序,根据阈值,选取合适的可能半径(比如3和3.5都被划为半径值3中)
(3)初始化半径空间r,N(r)=0
(4)遍历Canny图中的非0点,对于点所满足的半径r,N®+=1
(5)统计得到可能的半径值

利用霍夫变换检测其他图形的原理也是这样。找出表达式以及参数空间,遍历图像,找出参数空间中符合要求的参数。
2,源代码示例:

import cv2 as cv
import numpy as np


def detect_circles_demo(image):
    dst = cv.pyrMeanShiftFiltering(image, 10, 100) #均值迁移,EPT边缘保留滤波,霍夫噪声敏感,所以要先消除噪声
    cimage = cv.cvtColor(dst, cv.COLOR_BGR2GRAY)
    circles = cv.HoughCircles(cimage, cv.HOUGH_GRADIENT, 1, 20, param1=60, param2=28, minRadius=0, maxRadius=0)
    """
    HoughCircles(image, method, dp, minDist, circles=None, param1=None, param2=None, minRadius=None, maxRadius=None)
1.image:输入图像 (灰度图)

2.method:指定检测方法. 现在OpenCV中只有霍夫梯度法,加快速度

3.dp:累加器图像的反比分辨=1,默认即可

4.minDist = 检测到圆心之间的最小距离,这是一个经验值。这个大了,那么多个圆就是被认为一个圆。

5.param_1 = 50: Canny边缘函数的高阈值

6.param_2 = 30: 圆心检测阈值.根据你的图像中的圆大小设置,当这张图片中的圆越小,那么此值就设置应该被设置越小。

当设置的越小,那么检测出的圆越多,在检测较大的圆时则会产生很多噪声。所以要根据检测圆的大小变化。

7.min_radius = 0: 能检测到的最小圆半径, 默认为0.

8.max_radius = 0: 能检测到的最大圆半径, 默认为0
   
    """
    circles = np.uint16(np.around(circles)) #around对数据四舍五入,转化为整数
    for i in circles[0, :]:
        cv.circle(image, (i[0], i[1]), i[2], (0, 0, 255), 2)  #画圆
        cv.circle(image, (i[0], i[1]), 2, (255, 0, 0), 2)  #标记中心
    cv.imshow("circles", image)



src = cv.imread("F:/images/coins.jpg")
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)
detect_circles_demo(src)
cv.waitKey(0)

cv.destroyAllWindows()

运行结果:
OpenCV+python:圆检测_第2张图片OpenCV+python:圆检测_第3张图片

你可能感兴趣的:(OpenCV/基本图像处理算法)