本文共 1871 字,大约阅读时间需要 6 分钟。
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 cvimport numpy as npdef 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()
运行结果:
转载地址:http://uahwi.baihongyu.com/