如何使用传统图像处理方法进行圆的检测和测量

1 引言

上一篇使用传统方法进行石头检测的文章,受到了大家一致的好评.
嗯嗯,应该是一致的好评!
今天我们来研究一个新的方向,如何使用传统方法来进行圆的检测.

在这里插入图片描述
如上图所示,存在多个形状各异的物体,这里原型物体只有两个左下角的白色药片,
这里我们需要用图像处理的方法来检测出两个圆形物体,并计算圆形物体相应的面积.

2 解决方案

2.1 二值化

传统图像分割一般采用阈值分割的方法来区分前景和背景,
这里我们采用OTSU的方法来进行二值化操作,方法如下:

image_file = './images/pillsetc.png'
# Step 1: Read image
bgr_image = cv2.imread(image_file,cv2.IMREAD_COLOR)
# Step 2: Threshold the image
gray_image = cv2.cvtColor(bgr_image, cv2.COLOR_BGR2GRAY)
threshold, thresh_image = cv2.threshold(gray_image, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
print('Graylevel threshold computed with otsu: ', threshold)

运行后结果如下:
请添加图片描述
上图中,左侧为原图,右侧为二值化后的结果图.

2.2 图像去燥

观察上图二值化后的图像,存在一些零零散散的噪声,这里我们来想办法去除这些噪声.
这里推荐使用remove_small_objects这个函数,该函数可以直接去掉零散的小连通区域,我们代码实现如下:

from skimage import morphology
rmnoise_image = morphology.remove_small_objects(thresh_image.astype(bool), min_size=30)

上述代码,直接将面积小于30的小连通区域和孤点噪声直接剔除,运行结果如下:
请添加图片描述
上图中,左侧为去燥前的效果图,右侧为去燥后的效果图,可以看出很多零散的噪声和小的连通区域均被滤除.

2.3 消除空洞

观察上述去燥后的图像,注意查看下图绿色接头(红色框内)的二值图像,我们发现存在空洞,这里可以采用先膨胀在腐蚀的操作(闭运算),来消除空洞,代码如下:

fillcap_image = morphology.binary_closing(rmnoise_image, selem=morphology.disk(2))

运行效果如下:
请添加图片描述
上图中左侧为闭运算操作前的结果图,右侧为使用闭运算后的效果图,可以看出矩形框内的绿色转接头已经消除中间空洞.

2.4 填充

观察下图左侧图像.可以看出黄色框内的椭圆物品中间为空心的,这里需要对其进行填充,填充代码如下:

from scipy.ndimage.morphology import binary_fill_holes
clean_image = binary_fill_holes(fillcap_image)

运行效果如下:
请添加图片描述
上图中左侧为填充前的结果图,右侧为填充后的效果图,可以看出矩形框内的椭圆物品由空心经填充变为了实心.

2.5 查找轮廓

我们观察上图,可以看出所有物品均被我们处理成一个个独立的封闭区域,这时我们可以采用opencv下的findContours函数来寻找对应区域的外轮廓.代码如下:

contours, _ = cv2.findContours(clean_image.astype(np.uint8), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)
h,w = clean_image.shape
obj_image = np.zeros(shape=(h,w,3),dtype=np.uint8)
color_list=[(94,17,43),(128,31,113),(121,54,180),(118,173,253),(190,251,250),(93,96,239)]
for ind, cnt in enumerate(contours):
    cv2.drawContours(obj_image, [cnt], 0,color_list[ind], -1)

运行效果如下:
请添加图片描述
上图中左侧为输入原图,右侧为我们寻找出的外轮廓,并对其进行轮廓填充后的结果图.

2.6 圆的判断

经过上述操作,我们已经可以得到每个物品的外轮廓,接着我们回到我们原来的问题,怎么来判断那个物体是圆形呢?
首先我们来回顾一下圆的性质:

  • 圆的面积 A r e a = π R 2 Area= \pi R^2 Area=πR2
  • 圆的周长 P e r i m e t e r = 2 ∗ π ∗ R Perimeter=2*\pi*R Perimeter=2πR

接着我们定义 α \alpha α,由面积和周长组成,计算公式如下:

α = 4 ∗ π ∗ A r e a P e r i m e t e r 2 \alpha=\frac{4*\pi*Area}{Perimeter^2} α=Perimeter24πArea

对于圆形物体,我们将圆的面积和周长计算公式代入,可以知道 α = 1 \alpha=1 α=1.
对于正方形物体来说,我们将正方形的面积和周长计算公式代入,
α = 4 ∗ π ∗ A r e a P e r i m e t e r 2 = 4 ∗ π ∗ a 2 ( 4 ∗ a ) 2 = π 4 < 1 \alpha=\frac{4*\pi*Area}{Perimeter^2}=\frac{4*\pi*a^2}{(4*a)^2}=\frac{\pi}{4}<1 α=Perimeter24πArea=(4a)24πa2=4π<1

总上,我们可以得到以下结论:
如果一个物体的轮廓所计算出的 α \alpha α值越接近于1,那么该轮廓越趋向于圆形物体轮廓.

2.7 计算面积周长

经过2.6节的简单推导,我们已经知道如何判断一个轮廓是否趋向于圆形,基于此我们编写代码如下:

for ind, contour in enumerate(contours):
    perimeter = cv2.arcLength(contour, True)
    area = cv2.contourArea(contour)
    alpha = 4*np.pi*area/(perimeter**2)
    print('{0:>6} {1:>9,.0f} {2:>9,.2f} {3:>9,.3f}'.format(ind, area, perimeter, alpha))
    # Compute moments in order to find the centroid of objects
    moments = cv2.moments(contour)
    cx = int(moments['m10'] / moments['m00'])
    cy = int(moments['m01'] / moments['m00'])
    cv2.putText(obj_image,str(ind),(cx,cy),cv2.FONT_HERSHEY_SIMPLEX,0.5,color=(0,128,0),thickness=2)
    # Plot a red circle on the centroid of the round objects
    if alpha > round_thresh:
       cv2.circle(obj_image,(cx,cy),2,color=(0,0,255),thickness=2)

运行后的结果如下:

Object      Area Perimeter Roundness
     0       882    110.57     0.907
     1       876    110.57     0.900
     2    16,928    543.05     0.721
     3     3,026    261.12     0.558
     4     8,074    338.88     0.884
     5     4,908    264.01     0.885

可视化结果如下:
请添加图片描述
上图中,左侧为输入原图,右侧为我们圆检测后的结果图,图中红色圆点代表我们识别出的圆形物体的质心(也就是圆心).
同时根据定量结果输出我们可以得到以下结论:

  • 0号物体和1号物体为检测出的圆形物体,红色小点为对应的圆心
  • 0号物体的周长为110.57,面积为882
  • 1号物体的周长为110.57,面积为876

3 总结

本文介绍了使用传统图像处理方法进行圆形物体检测的基本方法,并根据圆的性质给出了如何根据轮廓的面积和周长来判断轮廓是否为圆的轮廓的方法.

您学废了吗?




关注公众号《AI算法之道》,获取更多AI算法资讯。
在这里插入图片描述

注: 关注公众号,后台回复 圆 , 可获取完整代码

  • 8
    点赞
  • 51
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

赵卓不凡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值