zoukankan      html  css  js  c++  java
  • 提取内环图像

    项目开源部分代码:Extract-inner-image

    项目成果:

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

    软件界面:

    算法选型:

    •   第一期做圆柱形毛毡柱的计数时,首先想到的是滑窗(模板匹配),对于不同型号的圆柱形毛毡柱设定特定的模板,然后从左上到右下,遍历0-180度,根据IOU来判断是否是一个目标物体,但是对于T形或者L形的摆放会产生误检,区域生长算法也是因为无法避免这种缺点而被淘汰,其次这种算法耗时太长;
    •        接着打算直接对目标物体进行分割,尝试了凹点分割和分水岭算法,顾名思义,先找到粘连图像的凹点,再按照一定的规则进行配对分割,但是当两个圆柱形顶部或侧面无缝相接时,是找不到这样的凹点的,因此需要用到面积特征来筛选,然而即使筛选过后也不能进行分割;同样的分水岭算法也是不能分割相邻过于紧密的目标;
    •        考虑到圆柱形的纵向横截面积与矩形类似,因此尝试了角点检测算法来检测矩形的四个顶点,实际效果中显示有些角点未检测到,而有些角点检测了多次。主要的原因是圆柱形的侧面并不是严格的直角,会有一些弧度,因此这种方法不适用;
    •        接着矩形的思路走,矩形有四条边,因此想起是否可以用霍夫变换检测直线,将矩形的四条边检测出来,然后按照直线围成的轮廓来判断是否是目标物体,但是实际中的目标物体并不是严格的直线,其次,先用canny边缘检测算法时,图像中倾斜的目标物体的边缘是锯齿形状的间断的线,因此会出现无数多条误检直线,这个方法同样pass;
    •        最后选择的是基于面积特征的方法,基本思路是将图像二值化后,目标区域处理为白色,计算出图像中的非零点,然后与一个目标的像素点相除求出目标物体个数。但是这种方法有一个非常明显的缺点:因为毛毡是有弹性的,并不是完全规则的物体,所以对图像整体计算像素点会累计很大的误差。为降低误差,首先采用的是对二值化后的图像进行边缘处理,简单求外部轮廓,然后将各个轮廓提取出来求取像素点并计算个数,再对所有个数求和。对算法进行测试时发现,当图像中目标物体距离比较近时,检测到的轮廓并不多,分割效果比较差。为了提高目标的分割个数,换用基于标记的分水岭算法对图像进行分割,然后对分割后的图像进行轮廓提取,结果显示是可行的。

    项目算法:

    • 圆柱形、方形和圆柱目标物体的计数算法

      先对图像灰度化,二值化,然后进行距离变换,再对变换后的图像利用分水岭算法分割,得到带有分割线,并对分割区域赋予随机颜色得到图像src_water,用opencv自带的findContours函数对src_water寻找轮廓contours,轮廓的参数为RETR_LIST(即全部轮廓),重新创建一个原图大小的全0图像(黑色),通过遍历contours中的轮廓,将轮廓内部全部填充为白色,生成黑底白目标的mask,与原图二值化后的图像相与来提取出各个目标区域。

      特别注意,本算法使用opencv中自带的watershed时,原图参数处的图片为原图二值化后利用Gray2RGB函数将单通道二值图转换成三通道图片。因为本算法涉及到面积特征,通过这种方式可以减少误差。当目标物体颜色为白色等浅色时,图像的边缘会出现阴影,watershed后边缘会出现很多噪点,影响面积特征。

      提取算法的具体流程见下图:

      上述算法中当循环次数不符合条件时,继续计算更新后的src_th的非零像素点的原因是,分水岭算法并不是能完全将目标物体全部分隔开,会将几个目标物体分割在一起,也会遗漏几个目标,因此将提取到的目标在二值图中删除后,最后剩下的会是全黑图或者几个目标。

      提取算法的结果图如下:

    • 环形目标物体的计数算法

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

       

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

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

            

      PickUp算法的实际结果图如下所示:

               

      将内环图像提取出来后,对图像进行腐蚀操作,消除噪点,再对图像求取轮廓,对轮廓进行计数统计从而得到目标物体的个数。

     项目程序总结:

    • 项目中涉及到使用Opencv中的findcontours函数对二值图寻找轮廓,二值图如下图左所示,findcontours函数之后的二值图如下图右所示。

            

    • Opencv中形态学的腐蚀膨胀操作默认是对白色元素进行操作,膨胀,直观上就是把白色区域扩大,腐蚀,与膨胀相反,缩小白色区域。
  • 相关阅读:
    【UVa】And Then There Was One(dp)
    【vijos】1006 晴天小猪历险记之Hill(dijkstra)
    【UVa】Palindromic Subsequence(dp+字典序)
    【UVa】Wavio Sequence(dp)
    【UVa】Salesmen(dp)
    【UVa】Partitioning by Palindromes(dp)
    小结:特殊的技巧
    java 中 进程和线程的区别
    java中的 sleep() 和 wait() 有什么区别?
    Java 静态static 关键字作用
  • 原文地址:https://www.cnblogs.com/qinguoyi/p/8325010.html
Copyright © 2011-2022 走看看