多功能乐高零件分拣设备中的高速机器视觉

在过去的几年中,我一直在设计和制造可以识别和分类乐高零件的机器。 机器最重要的部分是捕获单元捕获单元是一个几乎完全封闭的小隔间,其中装有传送带,照明设备和照相机。


照明时,您会看到一点点降低。

相机拍摄通过传送带的乐高零件的照片,然后将图像无线传输到运行人工智能算法的服务器,以识别数千种可能的乐​​高元素中的零件。 在以后的文章中,我将详细介绍AI算法,而本文将重点介绍摄像机原始输出与神经网络输入之间的处理过程。

我需要解决的主要问题是将来自传送带的视频流转换成神经网络可以使用的零件的独立图像。


最终目标是:从原始视频(左侧)切换到一组大小相同(右侧)的图像,以将其传输到神经网络。 (与实际工作相比,gif慢了一半左右)

这是一个表面上看起来很简单的任务的好例子,但实际上却构成了许多独特而有趣的障碍,其中许多障碍是机器视觉平台所独有的。

以此方式检索图像的正确部分通常称为对象检测。 这正是我需要做的:识别对象的存在,它们的位置和大小,以便可以为每一帧的每个零件生成边界矩形


最重要的是找到好的边界框(上面以绿色显示)

我将考虑解决问题的三个方面:

  • 准备消除不必要的变量
  • 通过简单的机器视觉操作创建流程
  • 在资源有限的Raspberry Pi平台上保持足够的性能

消除不必要的变量


对于此类任务,最好在使用机器视觉技术之前消除尽可能多的变量。 例如,我不必担心环境条件,不同的摄像头位置,由于某些零件彼此重叠而造成的信息丢失。 当然,可以(尽管非常困难)以编程方式解决所有这些变量,但是对我来说幸运的是,这台机器是从头开始创建的。 我本人可以为成功的解决方案做准备,甚至在我开始编写代码之前就消除所有干扰。

第一步是牢固地固定摄像机的位置,角度和焦点。 这样,一切都很简单-在系统中,摄像机安装在传送带上方。 我不必担心其他部分的干扰; 不需要的物体几乎没有机会进入捕获单元。 稍微复杂一点,但是确保恒定的照明条件非常重要。 我不需要对象识别器将沿着磁带的运动部件的阴影错误地解释为物理对象。 幸运的是,捕获单元非常小(相机的整个视野​​都比一块面包小),因此我对周围的环境有足够的控制权。


捕获单元,内部视图。 相机位于画面的上三分之一。

一种解决方案是将车厢完全封闭,以免外部照明进入。 我尝试了使用LED灯条作为光源的这种方法。 不幸的是,该系统看上去非常混乱-壳体上只有一个小孔就足够了,光线穿透了车厢,无法识别物体。

最后,最好的解决方案是通过用强光填充小隔间来“阻塞”所有其他光源。 事实证明,可用于照亮住宅房屋的光源非常便宜且易于使用。


得到阴影!

当光源直接进入微小隔间时,它会完全阻塞所有潜在的外部光干扰。 这样的系统还具有便利的副作用:由于相机中的大量光线,您可以使用非常高的快门速度,即使沿着传送带快速移动,也可以获得完美清晰的零件图像。

物体识别


如何将具有均匀照明的精美视频转换成我需要的边框? 如果您使用AI,可能会建议我实现一个用于对象识别的神经网络,例如YOLOFaster R-CNN 。 这些神经网络可以轻松应对任务。 不幸的是,我正在Raspberry pi上执行对象识别代码。 即使是功能强大的计算机,在我需要大约90FPS的频率下执行这些卷积神经网络时也会遇到问题。 而没有AI兼容GPU的Raspberry pi无法应对这种AI算法之一的简化​​版本。 我可以将视频从Pi流式传输到另一台计算机,但是实时视频传输是一个非常麻烦的过程,延迟和带宽限制会引起严重的问题,尤其是在需要高数据传输速度时。


YOLO非常酷! 但我不需要其所有功能。

幸运的是,我可以避免使用“老式”机器视觉技术的基于AI的困难解决方案。 第一种技术是背景减法 ,它试图隔离图像的所有更改部分。 就我而言,在摄像机视野中唯一移动的是乐高细节。 (当然,磁带也会移动,但是由于它具有统一的颜色,因此对于相机来说似乎是静止的)。 将这些乐高细节与背景分开,即可解决一半问题。

为使背景减法有效,前景对象必须与背景明显不同。 乐高细节有多种颜色,因此我必须非常仔细地选择背景色,以使其与乐高颜色尽可能远。 这就是为什么相机下面的胶带是纸制的-它不仅需要非常均匀,而且不能由乐高组成,否则它将具有我需要识别的零件之一的颜色! 我选择了浅粉红色,但是与普通的乐高颜色不同,任何其他柔和的颜色都可以。

很棒的OpenCV库已经有几种用于背景扣除的算法。 MOG2背景减法器是其中最复杂的,同时,即使在覆盆子pi上,它的工作速度也非常快。 但是,将视频帧直接馈送到MOG2效果不佳。 浅灰色和白色的数字太接近浅色背景的亮度,因此丢失了。 我需要想出一种方法来更清楚地将胶带与胶带上的各个部分分开,让背景减法器更靠近颜色而不是亮度 。 为此,在将图像转移到背景减法器之前,增加图像的饱和度就足够了。 结果有明显改善。

减去背景后,我需要使用形态学运算来消除尽可能多的噪声。 要查找白色区域的轮廓,可以使用OpenCV库的findContours()函数。 通过应用各种启发式方法来偏转包含噪声的循环,您可以轻松地将这些循环转换为预定义的边界框。


性能表现


神经网络是一种贪婪的生物。 为了在分类中获得最佳结果,她需要最大分辨率和尽可能多的图像。 这意味着我需要以很高的帧速率拍摄它们,同时保持图像质量和分辨率。 我不得不从相机和GPU Raspberry PI中挤出最大的力量。

关于picamera的非常详细的文档说,V2摄像头芯片可以产生1280x720像素大小的图像,最大频率为每秒90帧。 这是令人难以置信的数据量,尽管相机可以生成数据,但这并不意味着计算机可以处理它。 如果要处理原始的24位RGB图像,则必须以大约237 MB / s的速度传输数据,这对于Pi计算机的较差GPU和SDRAM来说都太高了。 即使在JPEG中使用GPU加速压缩,也无法达到90fps。

Raspberry Pi能够显示未经过滤的原始YUV图像。 尽管使用RGB比使用RGB更加困难,但YUV实际上具有许多方便的属性。 其中最重要的是每个像素仅存储12位(对于RGB,则为24位)。


Y的每四个字节有一个字节U和一个字节V,即每个像素1.5个字节。

这意味着与RGB帧相比,我可以处理两倍的 YUV帧,这还没有计算GPU在转换为RGB图像时节省的额外时间。

但是,这种方法对处理过程施加了独特的限制。 使用全尺寸视频帧进行的大多数操作都会消耗大量内存和CPU资源。 在我严格的时间限制内,甚至无法解码全屏YUV帧。

幸运的是,我不需要处理整个框架! 对于物体的识别,包围矩形不必一定是精确的,近似的精确度就足够了,因此识别物体的整个过程可以用很小的框架来执行。 不需要进行缩小操作来考虑全尺寸帧的所有像素,因此可以非常迅速地免费缩小帧。 然后,生成的边界矩形的比例会再次增加,并用于从完整大小的YUV帧中剪切对象。 因此,我不需要解码或以其他方式处理整个高分辨率帧。


幸运的是,由于这种YUV格式的存储方法(请参见上文),实现与YUV格式直接兼容的快速裁剪和缩放操作非常容易。 此外,整个过程可以并行化为四个Pi内核,而不会出现任何问题。 但是,我发现并非所有内核都已充分发挥其潜能,这告诉我们内存带宽仍然是瓶颈。 但是即使如此,我在实践中还是设法达到了70-80FPS。 对内存使用情况进行更深入的分析可能有助于进一步加快速度。



如果您想了解更多有关该项目的信息,请阅读我以前的文章“我如何创建超过10万张标记的乐高图像进行学习

整个分拣机操作的视频:

Source: https://habr.com/ru/post/zh-CN480294/


All Articles