OpenCV---圆检测

OpenCV—圆检测

 推文:Opencv2.4.9源码分析——HoughCircles

圆检测

  • 圆的表示方式

两点确定一条直线,不在一条直线上的三点确定一个圆。与使用(r,theta)来表示一条直线相似,使用(a,b,r)来确定一个圆心为(a,b)半径为 r 的圆。

  • 如何判断多个点是否在一个圆上

同样经过一个点可以作出无数个圆,假设某个点平面坐标为(xi,yi),使用的参数为(ai,bi,ri)则经过此点的圆的表达式为(xi-ai)^2 +(yi-bi) ^ 2=ri ^ 2。对于点(xj,yj),必定存在(aj,bj,rj)使得 近似计算中 ai=aj,bi= bj, ri = rj,即两个点在同一个圆上;同理如果三个点在同一个圆上,则也必须存在 ai=aj =ak = a, bi=bj=bk = b, ri=rj=rk = r 的情况。

  • 如何检测圆

要将圆检测出来,也就是要将上述的(a,b,r)求解出来。

假设r确定,此时点(x,y)又已知,根据(x-a)^2 +(y-b) ^ 2=r ^ 2 ,则(a,b)的轨迹在几何上则变成了以(x,y)为圆心,r为半径的圆;而r不确定时,(a,b,r)的轨迹变成了以(x,y)为顶点的一个圆锥。则(ai,bi,ri),(aj,bj,rj), (ak,bk,rk)的圆为下图中圆锥面的角点A。

在这里插入图片描述

例子用一个opencv的霍夫变换检测圆:

https://blog.csdn.net/kh1445291129/article/details/45674417

找到灰度图后进行双边滤波,利用houghcircle检测圆,再利用circle将圆显示出来。

在这里插入图片描述

在这里插入图片描述

圆形的表达式为(x−xcenter)2+(y−ycenter)2=r2(x−xcenter)2+(y−ycenter)2=r2,一个圆环的确定需要三个参数。那么霍夫变换的累加器必须是三维的,但是这样的计算效率很低。

这里opencv中使用霍夫梯度的方法,这里利用了边界的梯度信息
首先对图像进行canny边缘检测,对边缘中的每一个非0点,通过Sobel算法计算局部梯度。那么计算得到的梯度方向,实际上就是圆切线的法线。三条法线即可确定一个圆心,同理在累加器中对圆心通过的法线进行累加,就得到了圆环的判定。

其他形状

无论是直线还是圆,都是根据本身的几何形状的数学性质,直线根据极坐标的(r,theta)来表示,圆根据(a,b,r)来表示。要检测出直线或者圆其实就是要找到这样的(r,theta)或者(a,b,r)。根据相关的直线或圆的表达式反推出(r,theta)及(a,b,r)的轨迹,相应轨迹的交点就是要找到的直线或圆或想要找到的形状。


 

 霍夫圆检测

加载一幅图像并对其模糊化以降噪
对模糊化后的图像执行霍夫圆变换 .
在窗体中显示检测到的圆.
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 = cv.GaussianBlur(image,(13,15),15) #使用高斯模糊,修改卷积核ksize也可以检测出来
    # cv.imshow("3", dst)
    gray = cv.cvtColor(dst,cv.COLOR_BGR2GRAY)
    circles = cv.HoughCircles(gray,cv.HOUGH_GRADIENT,1,20,param1=50,param2=30,minRadius=0,maxRadius=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("detect_circle_demo",image)

src = cv.imread("./c.png")  #读取图片
cv.namedWindow("input image",cv.WINDOW_AUTOSIZE)    #创建GUI窗口,形式为自适应
cv.imshow("input image",src)    #通过名字将图像和窗口联系

detect_circle_demo(src)

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

相关知识补充:

(一)HoughCircles方法

1.加载一幅图像
2.执行高斯模糊以降低噪声:GaussianBlur
3.转成灰度图:cvtColor
4.执行霍夫圆变换:HoughCircles
def HoughCircles(image, method, dp, minDist, circles=None, param1=None, param2=None, minRadius=None, maxRadius=None): # real signature unknown; restored from __doc__
cv.HoughCircles(gray,cv.HOUGH_GRADIENT,1,20,param1=50,param2=30,minRadius=0,maxRadius=0)
1.image:输入图像 (灰度图)
2.method:指定检测方法. 现在OpenCV中只有霍夫梯度法
3.dp: 指的是累加器的图像和原图像的比例,如果dp为1,则累加器的图像和原图具有相同的比例,如果dp为2,则累加器图像的长宽均只有原图的一半。`
解释一下:
  当dp为1后,那么累加器会在累加器图像[0,w],[0,h]上可能的圆心位置(a,b)进行投票,最后来计算是否达到阈值来判定是否为圆心。
  当dp为2后,那么累加器会在累加器图像[0,w/2],[0,h/2]上可能的圆心位置(a,b)进行投票,最后来计算是否达到阈值来判定是否为圆心。 
  显然,当dp为2后,由于累加器图像的缩小,之前在dp=1上投票的可疑的相邻4个圆心的坐标点,在dp=2的累加器图像上会投票四次(因为长宽只有一半)
  与之对应下面的(4,5,6,7,8)都需要调整,例如:minDist 需要扩大一些,param_2需要扩大差不多4倍,半径也需要调小一点
4.minDist :如果圆心之间的距离在这个范围内会被认为是同心圆
5.param_1 = 200: Canny边缘检测的高阈值
6.param_2 = 100: 要检测到一个圆,那么必须检测到多少个点在这个圆的圆周上,实际上就是累加器的阈值
7.min_radius = 0: 能检测到的最小圆半径, 默认为0.
8.max_radius = 0: 能检测到的最大圆半径, 默认为0

 

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值