钢管识别项目1
零、相关说明:
首先进行一下相关说明。在“jsxyhelu.cnblogs.com/项目实战派”栏目里面出现的需求、图片和其他资源,都是我在浏览威客网站、论坛等网站的时候通过正规渠道获得的真实需求。个人觉得比较感兴趣,但是由于时间或者工作的冲突自己没有去接这些项目。但是由于这些需求都很有实现价值,所以过了一段时间,仍然拿出来练一练手,并且实现了核心模块。希望能够给浏览者一些启发。如果你认为这些图片和资源放在这里不合适,请及时联系我(1755311380@qq.com),我会及时处理的。此外,我会将核心代码和技术细节尽可能将清楚,我认为这样才是最有价值的方式。如果需要原始代码,也可以和我联系。
一、原始需求/图片:
二、初步分析:
钢管的特点是由于其是有深度的,这就造成了管子的内部形成一个阴影。寻找并识别这个阴影,是解决问题的主要方法。
同时需要注意到的一点是管子它本身的排列是有符合物理特性的,就是大体上要符合下图的这种情况,这是个先验知识。
干扰在于这个阴影不仅是管子内部才有的,管子和管子之间也会形成阴影;
此外,这些实际的图片中都存在管子被堵死的情况,这也是需要考虑的。
三、解决方案:
灰度并阈值处理,得到这样的结果。需要注意的是这里不要使用OSTU。的确OSTU很多时候都很好用,但是也有不好用的时候。即使是固定的阈值在本例的效果也比 OSTU效果要好,可以尝试一下。
寻找所有的轮廓,首先根据轮廓的面积大小去除一部分区域
两图对照,可以发现根据面积约束以后,丢掉了一些东西。一方面是哪些被堵起来的管子;一方面是哪些和旁边的阴影合在一起的管子。这个需要专门来做,并且根据先验知识来进行约束。当期的图片进行找圆操作并且限制半径大小后得到这样的结果。
主要存在的干扰就是孔洞之间被识别出来构成的圆。
四、难点攻关:
一、去除识别结果中的干扰,主要是管子和管子之间的间隙造成的误识别
主要采用的方法是识别出各轮廓的外接椭圆。对于那些错误识别的地方,它们的外界椭圆总是可能不规则的,或者是过大、或者是长宽比失调。通过这个方法可以提出一部分干扰。留下的那些都是本身非常近视于圆的地方了。
bool ellipseLikeCircle(RotatedRect rotatedrect)
{
float width = rotatedrect.size.width;
float height = rotatedrect.size.height;
if (width/height >= 1.6 || height/width >= 1.6)
{
return false;
}
if (min(width,height)>20*1.2)
{
return false;
}
return true;
}
{
float width = rotatedrect.size.width;
float height = rotatedrect.size.height;
if (width/height >= 1.6 || height/width >= 1.6)
{
return false;
}
if (min(width,height)>20*1.2)
{
return false;
}
return true;
}
二、将图像中的那些被堵起来的部分,采用相反的方法进行识别,最后将结果叠加在一起
另一幅图片(要调整阈值)
四、小结反思:
对于此类直接取图于实际,也利用于实际的项目(对比与生产线上的那种大规模批量的)来说,我认为做成半自动的要比全自动的效果要好。毕竟图像质量放在那里,无论向那个方向优化都很容易做成过度优化,而且算法的优化也会很复杂。
但是最终得到有用的结果才是重要的,才是有价值的。与其做成全自动的不如将图像识别做成辅助识别的一部分,将那些重复性的工作(比如识别哪些容易识别的管子)由机器来做,将哪些复杂的识别交给人来做,这样在提供工作效率的同时也提高了识别效率。
和此相类似的是现在许多安卓的软件,在使用的时候,上面都有个框子,要求你把需要识别的图像大概框到这个框子里面。我也的确认为这样的现场的运用,最好是用安卓来运行,但是运行于桌面也是有价值的。这个方面单独研究。
但是并不能因此而降低对算法的优化,说到底,算法优化才是根本。
P.S 在[blog 算法原理]选择轮廓(select_shape) 中,我研究了关于如何模仿halcon的形式进行轮廓的大小和圆的特性的判断,也能够得到不错的效果,有兴趣可以看一看。
同时,在“钢管识别项目2”中,我对采用GUI界面辅助识别进行了一些研究。