Raspberry Pi机器人视觉:深度图

图片

如今,“无人机构建”的所有技术都在积极地变得越来越便宜。除了一个:获取周围空间的地图。有两个极端:要么是昂贵的激光雷达(数千美元)和用于构建深度图的光学解决方案(数百美元),要么是非常便宜的解决方案,例如超声波测距仪。
因此,在一个带有一台照相机的廉价Raspberry Pi的基础上出现了一个想法,提出了一种解决方案,该解决方案将处于空白位置,并允许您“廉价”获得深度图。并以简单的编程语言(例如Python)进行操作,以便初学者可以尝试。实际上,我想介绍一下我的结果。生成的带有示例照片的脚本也可以在桌面上运行。



一台摄像机的深度图。



首先,谈谈光学部分。要创建深度图,始终使用两张图片-来自左右摄像机。我们用一台相机拍摄覆盆子。因此,开发了一种分光器,其结果是为相机提供了一对立体声。
简而言之-如果您看照片,则相机的两只眼睛从黑匣子注视着您。但是实际上相机是一台。只是一点光学魔术。

图片

图为该设备的第十二次迭代。花费了很长时间才能获得可靠的稳定设计,但同时又很便宜。最困难的部分是内部反射镜,这些反射镜是通过真空沉积铝制成的。如果使用标准反射镜,其中反射层位于玻璃下方而不是玻璃上方,则在接合处它们会形成间隙,从而彻底破坏整个图片。

我们将从事什么工作



Raspbian Wheezy的树莓派图像作为基础,安装了Python 2.7和OpenCV 2.4,好吧,这些小东西所需的软件包-matplotlib,numpy和其他。文章末尾列出了所有种类以及指向卡片最终图像的链接。可以在项目网站上找到课程形式的脚本描述

准备用于构建深度图的图片



由于我们的解决方案不是由金属制成,也没有超精密光学器件,因此组装后可能会与理想的几何形状产生微小偏差。另外,相机是通过螺丝固定在设备上的,因此其位置可能不理想。相机位置的问题是手动解决的,结构组装的“曲率”补偿将通过软件完成。

脚本一-摄像机对准



理想情况下,图片中镜子的交界处应垂直且居中。肉眼很难做到,因此制作了第一个脚本。它只是在实时预览模式下从相机捕获图片,然后将其显示在屏幕上,然后在叠加层的中央绘制一条白色的条,并沿着该条进行对齐。正确对准相机的方向后,我们用力拧紧螺丝,然后完成组装。



第一个脚本的代码中有趣的是
  • – , cv.imshow() , . , . , , .
  • – , .. . «» , camera.hflip = True



第二个脚本-我们得到一个“干净的”立体声对



我们的左右图片在图片的中央。照片中的关节宽度非零-您只能通过从设备上卸下镜子来消除它,这会增加结构的尺寸。覆盆子的相机将焦点设置为无穷远,而位置靠近的对象(在我们的示例中为交汇处)只是“模糊”。因此,您只需要告诉脚本,我们认为这是一个“坏”区域,以便将立体声对切成清晰的图片。创建了第二个脚本,该脚本显示图片,并允许您使用键指示要剪切的区域。
流程如下所示:



第二个脚本的代码中有趣的是
  • , , cv2.rectangle(). , , . , , Enter .
  • , . , .
  • JSON. , , .
  • . , , , . , ./src . . pf_1280_720.txt – , .
  • , . . :
    loadImagePath = ""
    # loadImagePath = "./src/scene_1280x720_1.png"



第三个脚本-一系列校准照片



基础科学说,为了成功构建深度图,必须对立体声对进行校准。即,左侧图片中的所有关键点都应在右侧图片中处于相同的高度。在这种情况下,StereoBM功能(这是我们唯一的实时功能)可以成功完成其工作。
为了进行校准,我们需要打印参考图片,制作一系列照片,并将其提供给校准算法,该算法将计算所有失真并保存参数,以使图片恢复正常。
因此,打印“国际象棋棋盘 ”并将其粘贴在坚硬的平面上。为简单起见,将串行照片制作为带有倒数计时器的脚本,该脚本显示在视频顶部。
这是串行摄影脚本的工作方式:



第三个脚本代码中有趣的是
  • . , . , , «» . , – , . camera.capture () , use_video_port=True.
  • – camera.annotate_text() . 5 – .
  • -, , ./src



应当指出,所进行系列的“正确性”对于校准结果至关重要。过一会儿,我们将看一下错误拍摄的照片所获得的结果。

脚本4-在立体声对上剪切照片



拍摄完一系列照片后,我们将制作另一个服务脚本,该脚本将拍摄整个照片系列并将其左右切成两对,然后将其保存到文件夹中。图片中心的区域。脚本很普通,所以我将视频隐藏在剧透中。

工作示例和第四个脚本来源的链接


最有趣的是校准,第五个脚本


校准脚本将所有立体声对从./src文件夹馈入到校准功能,并陷入沉思。经过艰苦的工作(在第一个树莓上获取15张图片1280x720大约需要5分钟),他拍摄了最后一对立体声,“校正”图片(校正)并显示已经校正的版本,您可以通过这些版本建立深度图。
这是工作脚本的样子:



第5个脚本的代码中有趣的是
  • StereoVision. , , , «» .
  • , . . «» , ,
  • calibrator.add_corners((imgLeft, imgRight), True)
    True False – , .



“出事了。”


有时校准结果出乎意料。
以下是几个引人注目的示例:

视差图不好

实际上,校准是决定性的时刻。在构造深度图的阶段,我们得到的结果直接取决于其质量。经过大量的实验,下面列出了一些射击要求:
  • 图片棋是不平行于所述图像平面-总是从不同的角度。但是即使没有狂热主义,如果您将木板垂直于照片的平面放置,脚本也不会在图片中找到象棋。
  • 轻,好光。在昏暗的室内照明下,甚至从视频中拉出图片时,图片质量也会下降。就我而言,在90%的情况下,光线立即可以纠正这种情况。
  • 互联网上写道,板应尽可能占据图像中的最大空间。真的有帮助。


具有良好校准结果的“固定”立体声对的外观如下:

图片

脚本6-首次尝试构建深度图


就像一切准备就绪一样,您已经可以构建深度图。
我们加载校准结果,拍照并使用cv2.StereoBM大胆地构建深度图。我们得到这样

图片

的结果结果不是很令人印象深刻,显然我们需要扭转一些东西。好吧,让我们继续在下一个第7个脚本中进行更好的调整。在那里,我们将使用的不是2个参数,如StereoBM(),而是将近10个,这更有趣。

这是第六个脚本的来源

脚本7-具有高级设置的深度图


如果参数不是2而是10,那么在不断重启脚本的情况下对它们的选项进行排序是错误的。因此,制作了一个脚本,用于对深度图进行方便的交互式调整。任务不是使代码与接口复杂化,因此所有操作都在matplotlib上完成。树莓派上matplotlib中界面的绘制相当慢,因此我通常将工作文件夹从树莓派转移到笔记本电脑上,然后在其中选择参数。脚本的工作方式如下:



选择参数后,“保存”按钮旁边的脚本会将结果以JSON格式保存到3dmap_set.txt文件中。

第7个脚本的代码中有趣的是
  • 7-
  • . , - , .
  • , . , numOfDisparities 16, . update(val), . numOfDisparities 65.57 64. , .
  • matplotlib , .



深度图的实际工作表明,首先,您需要选择minDisparity参数,并将其与numOfDisparities结合使用。好吧,请记住,在步骤16中,numOfDisparities实际上是离散变化的。
设置了该对之后,您可以使用其他参数。

卡设置的功能已经取决于用户的喜好,并取决于要解决的任务。您可以将地图带到大量的小零件或显示放大的区域。为了使机器人简单地避开障碍物,第二种方法更为合适。对于点云,这里首先出现性能问题(我们将再次讨论它们)。

我们想看什么?


好吧,最重要的一点之一也许就是调整我们设备的“远见”。设置深度图时,通常将一个对象放置在大约30厘米的距离上,第二个放置在一米的距离内,其余放置在两米的距离上。在第7个脚本中设置前两个参数(minDisparity和numOfDisparities)时,我实现了以下目标:
  • 最近的物体(30厘米)-红色
  • 半米内的物体-黄色或绿色
  • 2-3米的物体-绿色或浅蓝色

结果,我们得到一个系统,该系统被配置为识别半径为5-10米的障碍物“附近”区域。

实时处理视频-脚本8,最终


好了,现在我们有一个现成的定制系统,我们将不得不得到实际的结果。我们正在尝试使用相机中的视频实时构建深度图,并在更新时实时显示。



第8个脚本的代码中有趣的是
– . , , overlay. , :

  • Overlay R, G B, - . grayscale
  • disparity_color = cv2.applyColorMap(disparity_grayscale, cv2.COLORMAP_JET)
  • overlay RGB, BGR – cv2.cvtColor()
  • Overlay 16. 16 — .



在速度竞赛中


因此,第一次测量是在第一个具有单核处理器的Raspberry上完成的。
- 4秒 -映射图像1280×720这是一个很大。
- 2.5秒 -到树莓PI 2更好。
分析表明,在这种情况下,第二个覆盆子仅使用一个核心。乱!我使用TBB并行化库重建了OpenCV。
- 1.5秒 -使用多个核启动第二树莓。实际上,事实证明只使用了2个核心-仍然需要修补。事实证明,不仅我遇到了这个问题,所以还有很大的发展空间。
通过算法判断,运算速度应线性取决于处理数据的大小。因此,如果将分辨率降低2倍,则理论上所有操作的速度应提高4倍。
- 0.3秒,或约3-4 FPS -在减压两次640×360的分辨率。该理论得到证实。

进一步的计划


首先,我想充分利用第二个覆盆子的多核功能。我将仔细研究StereoBM函数的来源,并尝试了解为什么工作没有一直进行下去。

下一阶段将带来更多的冒险-这是使用树莓GPU来加快计算速度。
这里绘制了三种可能的路径:



如果您有使用RBBberry OpenCV的TBB的经验,或者您正在处理Raspberry GPU的编码,我将不胜感激其他提示由于一个简单的原因,我设法找到了许多现成的产品-很少有带两个摄像头的树莓。如果您通过USB挂接两个网络摄像头,则会大刹车,并且只有Raspberry Pi Compute可以与两个本地摄像头配合使用,这也需要带有花边和适配器的大型开发板。

有用的链接:


工作脚本:

在树莓派上设置OpenCV和Python:

StereoVision库:

GPU工作

好吧,有关habr的有趣文章“ 识别图像,您不需要识别图像

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


All Articles