python opencv 数米粒

1.介绍

opencv入门之数米粒:给出一幅米粒图数出图中米粒数目以及最大米粒位置。在原图上画出最大米粒的位置。并输出最大米粒的面积和最大米粒的周长。使用pycharm编码,亲测功能强大。
米粒分布原图

2.思路

首先利用opencv轮廓检测函数来分别提取每一个米粒,并计算出每个米粒的面积,然后对最大米粒求周长,最后在原图上标记最大米粒的位置,并且输出米粒信息。

3.预处理

opencv轮廓检测函数所需要的图像为二值化图片,所以在进行轮廓检测前,需要对图像进行预处理。预处理过程为:

(1).对图片进行灰度化:

  • #打开图片 img=cv2.imread(‘Img/rice.jpg’,0) (-1为原图,0为强制灰度图,1为强制彩图)
  • 灰度化函数gray=cv2.cvtColor(frame,cv2.COLOR_RGB2GRAY)

(2)获取去背景的米粒图
利用腐蚀膨胀,对原图进行5次腐蚀,然后进行5次膨胀,得到背景图
原图减去背景图可以得到去背景的米粒图

  • 腐蚀:就像土壤侵蚀一样,这个操作会把前景物体的边界腐蚀掉(但是前景仍然 是白色)。这是怎么做到的呢?卷积核沿着图像滑动,如果与卷积核对应的原图 像的所有像素值都是 1,那么中心元素就保持原来的像素值,否则就变为零。

import import cv2
import numpy as np

#打开图片
img=cv2.imread('Img/rice.jpg',0)

#构造模板,5次腐蚀
kernel=np.ones((5,5),np.uint8)#构造5x5卷积核
erosion=cv2.erode(img,kernel,iterations=5)#进行5次腐蚀
  • 膨胀:与腐蚀相反,与卷积核对应的原图像的像素值中只要有一个是 1,中心元 素的像素值就是 1。所以这个操作会增加图像中的白色区域(前景)。一般在去 噪声时先用腐蚀再用膨胀。因为腐蚀在去掉白噪声的同时,也会使前景对象变 小。
dilation=cv2.dilate(erosion,kernel,iterations=5) #进行5次膨胀
  • 获取去背景的米粒图
    用原图减去5次腐蚀,5次膨胀后的背景图
#原图减去背景得到米粒形状
backImg=dilation
rice=img-backImg

去背景米粒效果图:
去背景

(3)图像二值化

  • 简单阈值
    与名字一样,这种方法非常简单。但像素值高于阈值时,我们给这个像素 赋予一个新值(可能是白色),否则我们给它赋予另外一种颜色(也许是黑色)。 这个函数就是 cv2.threshhold()。这个函数的第一个参数就是原图像,原图 像应该是灰度图。第二个参数就是用来对像素值进行分类的阈值。第三个参数 就是当像素值高于(有时是小于)阈值时应该被赋予的新的像素值。OpenCV 提供了多种不同的阈值方法,这是有第四个参数来决定的。这些方法包括:
    cv2.THRESH_BINARY
    cv2.THRESH_BINARY_INV
    cv2.THRESH_TOZERO
    cv2.THRESH_TOZERO_INV

  • OSTU全局阈值
    这里用到到的函数还是 cv2.threshold(),但是需要多传入一个参数 (flag):cv2.THRESH_OTSU。这时要把阈值设为 0。然后算法会找到最 优阈值,这个最优阈值就是返回值 retVal。如果不使用 Otsu 二值化,返回的 retVal 值与设定的阈值相等。

#OSTU二值化,th1返回阈值,ret1返回二值化的结果图像
th1,ret1=cv2.threshold(rice,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)

二值化效果图如下
二值化

4.轮廓分析

轮廓可以简单认为成将连续的点(连着边界)连在一起的曲线,具有相同 的颜色或者灰度。轮廓在形状分析和物体的检测和识别中很有用。 python3.x-opencv开发指导用书
(1) 轮廓提取

  • 为了更加准确,要使用二值化图像。在寻找轮廓之前,要进行阈值化处理 或者 Canny 边界检测。
  • 查找轮廓的函数会修改原始图像。如果你在找到轮廓之后还想使用原始图 像的话,你应该将原始图像存储到其他变量中。
  • 在 OpenCV 中,查找轮廓就像在黑色背景中超白色物体。你应该记住, 要找的物体应该是白色而背景应该是黑色。

**#轮廓检测,注意输出结果应有3个,其他著作上为2个输出结果,亲测错误**
ret1,contours,hierarchy=cv2.findContours(ret1,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)

(2)轮廓数据

  • 轮廓面积
    轮廓的面积可以使用函数 cv2.contourArea() 计算得到,也可以使用矩 (0 阶矩),M[‘m00’]。
cv2.contourArea(cnt)
  • 轮廓周长
    也被称为弧长。可以使用函数 cv2.arcLength() 计算得到。这个函数 的第二参数可以用来指定对象的形状是闭合的(True),还是打开的(一条曲 线)。
cv2.arcLength(cnt,True)

(3)输出结果
遍历所有轮廓,比较轮廓数据,得出最大轮廓,并在原图上标注。
函数 cv2.drawContours() 可以被用来绘制轮廓。它可以根据你提供 的边界点绘制任何形状。它的第一个参数是原始图像,第二个参数是轮廓,一 个 Python 列表。第三个参数是轮廓的索引(在绘制独立轮廓是很有用,当设 置为 -1 时绘制所有轮廓)。接下来的参数是轮廓的颜色和厚度等。

#遍历得到最大面积的米粒
maxC=-1
maxS=-1
for cnt in contours:
    tempS=cv2.contourArea(cnt)
    if maxS<tempS:
        maxS=tempS
        maxC=tempC=cv2.arcLength(cnt,True)
        contour=cnt

#在img中画出最大面积米粒
cv2.drawContours(img,[contour],-1,(0,0,255,),1)

改变参数可以获取更好的效果

这里写图片描述


整体代码

import cv2
import numpy as np

#打开图片
img=cv2.imread('Img/rice.jpg',0)

#构造模板,5次腐蚀,5次膨胀,得到背景
kernel=np.ones((5,5),np.uint8)
erosion=cv2.erode(img,kernel,iterations=5)
dilation=cv2.dilate(erosion,kernel,iterations=5)

#原图减去背景得到米粒形状
backImg=dilation
rice=img-backImg

#OSTU二值化
th1,ret1=cv2.threshold(rice,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)

#轮廓检测
ret1,contours,hierarchy=cv2.findContours(ret1,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)

#遍历得到最大面积的米粒
maxC=-1
maxS=-1
for cnt in contours:
    tempS=cv2.contourArea(cnt)
    if maxS<tempS:
        maxS=tempS
        maxC=tempC=cv2.arcLength(cnt,True)
        contour=cnt

#在img中画出最大面积米粒
cv2.drawContours(img,[contour],-1,(0,0,255,),1)

cv2.imshow('image',rice)
print('面积最大:',maxS)
print('对应米粒周长:',maxC)
cv2.waitKey(0)
cv2.destroyAllWindows()
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值