项目开源部分代码:Extract-inner-imagehtml
项目成果:git
- 设计了一套基于背光板(冷光片)和暗箱的图像处理计数装置,能够对较规则目标进行计数,正确率可达99%(每计数500个);
- 对圆柱形、方形和圆形目标物体,利用距离变换和分水岭算法分割图像并提取出各个目标区域,再基于面积特征,计算出目标个数;
- 对于环形物体,设计了一种提取环形目标物体中内环图像的算法,将计算目标个数转化为计算内环图像的个数;
- 利用C++语言和OpenCV库实现了该系统的核心算法,并利用Qt设计了软件界面。
软件界面:github

算法选型:算法
- 第一期作圆柱形毛毡柱的计数时,首先想到的是滑窗(模板匹配),对于不一样型号的圆柱形毛毡柱设定特定的模板,而后从左上到右下,遍历0-180度,根据IOU来判断是不是一个目标物体,可是对于T形或者L形的摆放会产生误检,区域生长算法也是由于没法避免这种缺点而被淘汰,其次这种算法耗时太长;
- 接着打算直接对目标物体进行分割,尝试了凹点分割和分水岭算法,顾名思义,先找到粘连图像的凹点,再按照必定的规则进行配对分割,可是当两个圆柱形顶部或侧面无缝相接时,是找不到这样的凹点的,所以须要用到面积特征来筛选,然而即便筛选事后也不能进行分割;一样的分水岭算法也是不能分割相邻过于紧密的目标;
- 考虑到圆柱形的纵向横截面积与矩形相似,所以尝试了角点检测算法来检测矩形的四个顶点,实际效果中显示有些角点未检测到,而有些角点检测了屡次。主要的缘由是圆柱形的侧面并非严格的直角,会有一些弧度,所以这种方法不适用;
- 接着矩形的思路走,矩形有四条边,所以想起是否能够用霍夫变换检测直线,将矩形的四条边检测出来,而后按照直线围成的轮廓来判断是不是目标物体,可是实际中的目标物体并非严格的直线,其次,先用canny边缘检测算法时,图像中倾斜的目标物体的边缘是锯齿形状的间断的线,所以会出现无数多条误检直线,这个方法一样pass;
- 最后选择的是基于面积特征的方法,基本思路是将图像二值化后,目标区域处理为白色,计算出图像中的非零点,而后与一个目标的像素点相除求出目标物体个数。可是这种方法有一个很是明显的缺点:由于毛毡是有弹性的,并非彻底规则的物体,因此对图像总体计算像素点会累计很大的偏差。为下降偏差,首先采用的是对二值化后的图像进行边缘处理,简单求外部轮廓,而后将各个轮廓提取出来求取像素点并计算个数,再对全部个数求和。对算法进行测试时发现,当图像中目标物体距离比较近时,检测到的轮廓并很少,分割效果比较差。为了提升目标的分割个数,换用基于标记的分水岭算法对图像进行分割,而后对分割后的图像进行轮廓提取,结果显示是可行的。
项目算法:函数
先对图像灰度化,二值化,而后进行距离变换,再对变换后的图像利用分水岭算法分割,获得带有分割线,并对分割区域赋予随机颜色获得图像src_water,用opencv自带的findContours函数对src_water寻找轮廓contours,轮廓的参数为RETR_LIST(即所有轮廓),从新建立一个原图大小的全0图像(黑色),经过遍历contours中的轮廓,将轮廓内部所有填充为白色,生成黑底白目标的mask,与原图二值化后的图像相与来提取出各个目标区域。测试
特别注意,本算法使用opencv中自带的watershed时,原图参数处的图片为原图二值化后利用Gray2RGB函数将单通道二值图转换成三通道图片。由于本算法涉及到面积特征,经过这种方式能够减小偏差。当目标物体颜色为白色等浅色时,图像的边缘会出现阴影,watershed后边缘会出现不少噪点,影响面积特征。spa
提取算法的具体流程见下图:设计

上述算法中当循环次数不符合条件时,继续计算更新后的src_th的非零像素点的缘由是,分水岭算法并非能彻底将目标物体所有分隔开,会将几个目标物体分割在一块儿,也会遗漏几个目标,所以将提取到的目标在二值图中删除后,最后剩下的会是全黑图或者几个目标。3d
提取算法的结果图以下:htm

该算法将计算目标个数转化为计算内环图像的个数,所以核心是提取环形目标物体中内环图像的算法,将背景和环形目标物体置为一个颜色,内环图像置为另外一个颜色,算法流程图以下:

该算法中findcontours的轮廓参数是RETR_EXTERNAL(外部轮廓),上述算法中当循环次数不符合条件时,继续对更新后的src_th进行PickUp算法的缘由是同上。PickUp算法的理论结果图以下:

PickUp算法的做用是消除间隙轮廓。当几个目标物体距离太近,围成一个封闭空间时,对该图像求取轮廓会包含内部封闭空间,若是直接对提取出来的图像src_temp进行两个mask相与,相或操做,会出现下图的错误,经过PickUp算法能够将间隙轮廓、封闭空间消除。

PickUp算法的实际结果图以下所示:
将内环图像提取出来后,对图像进行腐蚀操做,消除噪点,再对图像求取轮廓,对轮廓进行计数统计从而获得目标物体的个数。
项目程序总结:
- 项目中涉及到使用Opencv中的findcontours函数对二值图寻找轮廓,二值图以下图左所示,findcontours函数以后的二值图以下图右所示。

- Opencv中形态学的腐蚀膨胀操做默认是对白色元素进行操做,膨胀,直观上就是把白色区域扩大,腐蚀,与膨胀相反,缩小白色区域。