精选文章 OpenCV 识别图片中的米粒个数,并计算米粒的平均面积和长度(转)

OpenCV 识别图片中的米粒个数,并计算米粒的平均面积和长度(转)

作者:_路漫漫其修远 时间: 2020-08-05 08:19:36
_路漫漫其修远 2020-08-05 08:19:36

介绍

OpenCV+Python

使用OpenCV构建图像识别算法,识别图片中的米粒个数,并计算米粒的平均面积和长度

软件架构

模块:OpenCV 4.0.0.21

编程语言:Python 3.7.2

编译器:PyCharm 2018

程序设计思路

首先介绍一下程序设计的思路:

  1. 图像采集(取到图像):可以用摄像头拍摄或者图片直接导入
  2. 图像预处理:对图像进行灰度化
  3. 基于灰度的阈值分割:使用局部大津算法进行阈值分割二值化,形态学去噪
  4. 图像特征描述及目标分析:使用灰度直方图计算轮廓,并通过面积条件进行筛选
  5. 得到最终结果:统计识别的米粒个数,并将米粒用矩形框标记出来,并打上编号

先看看效果图:

OpenCV 识别图片中的米粒个数,并计算米粒的平均面积和长度(转)1
左边是原始图像,右边是识别之后的结果。

下面介绍程序实现:

第一步:图像采集``

img = cv2.imread("test.png")  #导入图片,图片放在程序所在目录
  • 1

使用cv2.imread()函数导入图片,括号内输入图片路径,如果图片位于程序所在目录,就可以直接写图片文件名。

第二步:图像预处理

gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) #转换为灰度图
  • 1

主要使用cv2.cvtColor()函数将彩色图片转化为灰度图

第三步:基于灰度的阈值分割

#使用局部阈值的大津算法进行图像二值化
dst = cv2.adaptiveThreshold(gray,255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY,101, 1)

element = cv2.getStructuringElement(cv2.MORPH_CROSS,(3, 3))#形态学去噪
dst=cv2.morphologyEx(dst,cv2.MORPH_OPEN,element)  #开运算去噪
  • 1
  • 2
  • 3
  • 4
  • 5

使用局部大津算法对图像进行二值化,全局大津法的优点在于可以快速有效的找到类间分割阈值,但其缺点也很明显,就是只能针对单一目标分割,或者感兴趣的目标都属于同一灰度范围,若需探测目标灰度范围分布较大,则必将有一部分目标探测丢失(例如上图中黑色和白色的汽车)。局部分割的优点在于可以进行多目标分割,缺点在于基于局部阈值分割出的目标连结性较差,包含噪声。
在这个米粒图片中,下部的图像亮度较暗,如果使用全局大津算法,下部的米粒将会被认为是背景,而被屏蔽掉。OpenCV 识别图片中的米粒个数,并计算米粒的平均面积和长度(转)2
如图所示:左边是使用局部大津算法,右边是使用全局大津算法,可以看到左边的效果比右边的效果好。

函数原型:

   cv2. adaptiveThreshold(InputArray src, OutputArray dst, double maxValue, int adaptiveMethod, int thresholdType, int blockSize, double C)
  • 1

参数解释:
**InputArray src:**源图像

**OutputArray dst:**输出图像,与源图像大小一致

**int adaptiveMethod:**在一个邻域内计算阈值所采用的算法,有两个取值,分别为 ADAPTIVE_THRESH_MEAN_C 和 ADAPTIVE_THRESH_GAUSSIAN_C 。

ADAPTIVE_THRESH_MEAN_C的计算方法是计算出领域的平均值再减去第七个参数double C的值

ADAPTIVE_THRESH_GAUSSIAN_C的计算方法是计算出领域的高斯均值再减去第七个参数double C的值

**int thresholdType:**这是阈值类型,只有两个取值,分别为 THRESH_BINARY 和THRESH_BINARY_INV 具体的请看官方的说明,这里不多做解释

**int blockSize:**adaptiveThreshold的计算单位是像素的邻域块,邻域块取多大,就由这个值作决定

**double C:**在对参数int adaptiveMethod的说明中,我已经说了这个参数的作用,从中可以看出,这个参数实际上是一个偏移值调整量

然后对图像进行形态学去噪,形态学去噪有一下几种:

  • 开运算:先腐蚀再膨胀,用来消除小物体
  • 闭运算:先膨胀再腐蚀,用于排除小型黑洞
  • 形态学梯度:就是膨胀图与俯视图之差,用于保留物体的边缘轮廓。
  • 顶帽:原图像与开运算图之差,用于分离比邻近点亮一些的斑块。
  • 黑帽:闭运算与原图像之差,用于分离比邻近点暗一些的斑块。

我们使用开运算去除小噪声

第四步:图像特征描述及目标分析

主要步骤为:
1、检测轮廓- cv2.findContours()函数
2、提取轮廓的水平矩形坐标- rect = cv2.boundingRect( ) 函数
3、绘制矩形- cv2.rectangle()函数
4、 在米粒左上角写上编号-cv2.putText( ) 函数

contours, hierarchy = cv2.findContours(dst,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)  #轮廓检测函数
cv2.drawContours(dst,contours,-1,(120,0,0),2)  #绘制轮廓

count=0 #米粒总数
ares_avrg=0  #米粒平均
#遍历找到的所有米粒
for cont in contours:

    ares = cv2.contourArea(cont)#计算包围性状的面积

    if ares<50:   #过滤面积小于10的形状
        continue
    count+=1    #总体计数加1
    ares_avrg+=ares

    print("{}-blob:{}".format(count,ares),end="  ") #打印出每个米粒的面积

    rect = cv2.boundingRect(cont) #提取矩形坐标

    print("x:{} y:{}".format(rect[0],rect[1]))#打印坐标

    cv2.rectangle(img,rect,(0,0,0xff),1)#绘制矩形

    y=10 if rect[1]<10 else rect[1] #防止编号到图片之外

    cv2.putText(img,str(count), (rect[0], y), cv2.FONT_HERSHEY_COMPLEX, 0.4, (0, 255, 0), 1) #在米粒左上角写上编号

print("米粒平均面积:{}".format(round(ares_avrg/ares,2))) #打印出每个米粒的面积
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

1、检测轮廓

cv2.findContours(image, mode, method[, contours[, hierarchy[, offset ]]])  
  • 1

参数:

  • image参数是寻找轮廓的图像;

  • mode参数表示轮廓的检索模式,有四种(本文介绍的都是新的cv2接口):

    cv2.RETR_EXTERNAL表示只检测外轮廓
    cv2.RETR_LIST检测的轮廓不建立等级关系
    cv2.RETR_CCOMP建立两个等级的轮廓,上面的一层为外边界,里面的一层为内孔的边界信息。如果内孔内还有一个连通物体,这个物体的边界也在顶层。
    cv2.RETR_TREE建立一个等级树结构的轮廓。

  • method参数method为轮廓的近似办法

    cv2.CHAIN_APPROX_NONE存储所有的轮廓点,相邻的两个点的像素位置差不超过1,即max(abs(x1-x2),abs(y2-y1))==1
    cv2.CHAIN_APPROX_SIMPLE压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,例如一个矩形轮廓只需4个点来保存轮廓信息
    cv2.CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS使用teh-Chinl chain 近似算法

返回值:

cv2.findContours()函数返回两个值,一个是轮廓本身,还有一个是每条轮廓对应的属性。

  • contour返回值:cv2.findContours()函数首先返回一个list,list中每个元素都是图像中的一个轮廓,用numpy中的ndarray表示。
  • hierarchy返回值:此外,该函数还可返回一个可选的hiararchy结果,这是一个ndarray,其中的元素个数和轮廓个数相同,每个轮廓contours[i]对应4个hierarchy元素hierarchy[i][0]
    ~hierarchy[i][3],分别表示后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号,如果没有对应项,则该值为负数。

2、提取轮廓的水平矩形坐标

  cv2.boundingRect(InputArray points)
  • 1

参数:

  • points:输入信息,可以为包含点的容器(vector)或是Mat。
  • 返回包覆输入信息的最小正矩形。

3、绘制矩形

cv2.rectangle(img, (x,y), (x+w,y+h), (0,255,0), 2)
  • 1

参数解释:

  • img是原图
  • (x,y)是矩阵的左上点坐标
  • (x+w,y+h)是矩阵的右下点坐标
  • (0,255,0)是画线对应的rgb颜色
  • 2是所画的线的宽度

4、 在米粒左上角写上编号

cv2.putText(img,str(count), (rect[0], y), cv2.FONT_HERSHEY_COMPLEX, 0.4, (0, 255, 0), 1) 
  • 1

各参数依次是:图片输入/添加的文字/左上角坐标/字体/字体大小/颜色/字体粗细

第五步:统计米粒的编号、面积、长度

ares = cv2.contourArea(cont)
  • 1

计算包围形状的面积,并使用一个for循环来计算面积平均值和长度平均值

效果图:
OpenCV 识别图片中的米粒个数,并计算米粒的平均面积和长度(转)3
OpenCV 识别图片中的米粒个数,并计算米粒的平均面积和长度(转)4

完整程序代码请点击这里下载:OpenCV 识别图片中的米粒python程序

原博主文章地址:https://blog.csdn.net/u014005758/article/details/88283238

勿删,copyright占位
分享文章到微博
分享文章到朋友圈

上一篇:畅通工程再续(Kruskal)

下一篇:多线程基础例题

您可能感兴趣

  • 浅谈微服务体系中的分层设计和领域划分

    引言 看标题感觉这个东西很理论,比起“高并发、多线程”、“分布式CAP、一致性、Paxos”、“高可用SLA”等具体的干货技术点,软件体系知识显得很“湿”,似乎人人都有自己的认识,但又很少有人能说完整,有一点可以确定的是,如果你未来需要独立设计一个复杂的系统中台,并使之未来能快速应对各种需求变化的话,科学合理的领域划分和边界界定需要我们“处女座级”的坚持下去,这对防止人力失控、减少项目烂尾很...

  • 个人理解数据中台与大数据平台区别

    个人理解数据中台与大数据平台区别 概念介绍 本文主要介绍如下几个数据概念: 数据库 数据库是“按照数据结构来组织、存储和管理数据的仓库”。是一个长期存储在计算机内的、有组织的、有共享的、统一管理的数据集合。 数据库是以一定方式储存在一起、能与多个用户共享、具有尽可能小的冗余度、与应用程序彼此独立的数据集合,可视为电子化的文件柜——存储电子文件的处所,用户可以对文件中的数据进行新增、查询、更新...

  • 数据存储(1):从数据存储看人类文明-数据存储器发展历程

    传统文本存储 泥版/钟鼎/甲骨/莎草纸/羊皮纸等文字存储 传统的考古学家和历史学家认为,楔形文字起源于美索不达米亚特殊的渔猎生活方式。这是较为通行的看法,西方的各种百科全书大都持这一观点。约在公元前3400年左右,楔形文字雏形产生,多为图像。到公元前 500 年左右, 这种文字甚至成了西亚大部分地区通用的商业交往媒介。楔形文字一直被使用到公元元年前后,使用情景如同现今的拉丁文。 有了文字后,...

  • 2020年iOS面试反思总结

    Object-C系列面试题总结 基础题: 1.Objective-C的类可以多重继承么?可以实现多个接口么?Category是什么?重写一个类的方式用继承好还是分类好?为什么不要在category中重写一个类原有的方法? 答: Objective-c的类不可以有多继承,OC里面都是单继承,多继承可以用protocol委托代理来模拟实现 可以实现多个接口,可以通过实现多个接口完成OC的多重继承...

  • 详文解读微信「看一看」多模型内容策略与召回

    微信已经成了不少人获取咨询的来源之一,看一看功能在这基础上实现内容的精确推荐,以及拓宽用户阅读兴趣,打破信息茧房。本文从六个方面,以多模型内容策略与召回的角度分析微信看一看,希望对你有帮助。 目录 一、看一看介绍 二、内容库与内容画像 1. 内容源 2. 内容画像 3. 多模态标签语义标签 4. 基于知识体系的表示与可解释标签 5. 嵌入表示 6. 倾向性与目标性识别 三、召回架构 四、队列...

  • 这是我见过最通俗易懂的微服务架构改造解读

    点击上方肉眼品世界, 右上角选择“设为星标” 深度价值体系传递 作者介绍 古霜卡比,7年开发和架构经验。喜欢探索新事物、造轮子与瞎折腾。认为与其追逐日新月异的技术,不如研究底层的基础理论。目前专注于微服务相关技术、程序语言理论以及运筹学的应用。 本文将介绍微服务架构和相关的组件,介绍他们是什么以及为什么要使用微服务架构和这些组件。 本文侧重于简明地表达微服务架构的全局图景,因此不会涉及具体如...

  • 一文入门基于三维数据的深度学习

    本文转载自北京智源人工智能研究院。 这是一篇三维数据深度学习的入门好文,兼顾基础与前沿,值得收藏!为方便大家学习,本文PDF版本和所列出的所有文献提供下载,(2020年7月27日11点后)在我爱计算机视觉公众号后台回复“3DDL”。 众所周知,计算机视觉的目标是对图像进行理解。我们从图像中获取视觉特征,从视觉特征中对图像、场景等进行认知,最终达到理解、感知、交互。 目前,比较主流的计算机视觉...

  • 基于业务描述语言BDL的需求方法论

    业务需求 需求重要吗?业务需求重要吗? 为什么重要?它有多重要? 需求的切入点在哪里? 业务架构与业务需求之间是什么关系? 业务需求与软件需求之间又是什么关系? 软件需求与软件设计之间是什么关系? 设计与实现、实现与应用系统之间又是什么关系? 可以做到所需即所得吗? …… 说到需求我们爱恨交加,说到需求我们有很多话题。 概述 1 基本概念 为了后面讨论方便,首先明确几个基本概念。 业务事项(...

华为云40多款云服务产品0元试用活动

免费套餐,马上领取!
CSDN

CSDN

中国开发者社区CSDN (Chinese Software Developer Network) 创立于1999年,致力为中国开发者提供知识传播、在线学习、职业发展等全生命周期服务。