
今天,我们想为Raspberry Pi上的OpenCV学习者共享一系列Python示例,即双腔StereoPi板。 完成的代码(加上Raspbian图像)将帮助您完成所有步骤,从捕获图片开始到从捕获的视频获取深度图结束。
介绍性
我必须立即强调,这些示例仅是为了让您沉浸在该主题中,而不是用于生产解决方案。 如果您是OpenCV的高级用户,并且一直在处理树莓派,那么您应该知道,对于成熟的工作,建议一口气编写代码,甚至使用树莓派GPU。 在本文的结尾,我将详细介绍python解决方案的“瓶颈”和整体性能。
我们在做什么
我们有铁这样的设置:

Raspberry Pi计算模块3+上的StereoPi板。 为Raspberry Pi版本V1(在ov5647传感器上)连接了两个最简单的相机。
安装了什么:
- Raspbian Stretch(内核4.14.98-v7 +)
- 的Python 3.5.3
- OpenCV 3.4.4(预编译,来自Python Wheels的“ pip”)
- Picamera 1.13
- StereoVision lib 1.0.3(https://github.com/erget/StereoVision)
安装所有软件的过程不在本文的讨论范围之内,我们只建议下载完成的Raspbian映像(在本文末尾链接到github)。
第一步:拍摄照片
为此,请使用1_test.py脚本
打开控制台,从主文件夹转到包含示例的文件夹:
cd stereopi-tutorial
运行脚本:
python 1_test.py
启动后,屏幕上会显示我们的立体图像的预览。 按下Q按钮可以中断该过程,这将保存最后捕获的图像,该图像将在以下脚本之一中用于配置深度图。
该脚本使您可以确保所有硬件都能正常工作,并获得第一张图片以备将来使用。
这是第一个脚本的样子:
第二步:收集图片进行校准
如果我们在真空中谈论球形马,那么要获得高质量的深度图,我们需要有两个绝对相同的摄像机,其垂直轴和光轴完全平行,而水平轴重合。 但是在现实世界中,所有摄像机都略有不同,因此无法完美地布置它们。 因此,发明了一种软件校准技巧。 使用来自现实世界的两台摄像机,拍摄了大量先前已知物体的照片(我们有一张带有棋盘的照片),然后一种特殊的算法计算所有“缺陷”并尝试校正这些照片,以使其接近理想状态。
该脚本完成了第一阶段的工作,即有助于制作一系列照片以进行校准。
在每张照片之前,脚本都会开始5秒钟的倒计时。 通常,这一次足以将板子移动到新位置,以确保在两个摄像机上都不会爬行,并且固定其位置(以使照片中没有模糊)。 默认情况下,系列大小设置为30张照片。
发射:
python 2_chess_cycle.py
工艺流程:
结果,我们在/ scenes文件夹中有一系列照片。
我们将图片分成两半
第三个脚本3_pairs_cut.py将拍摄的照片剪切为“左”和“右”照片,并将它们保存在/ pair文件夹中。 实际上,我们可以排除此脚本并即时进行剪切,但是在进一步的实验中它非常有用。 例如,您可以保存来自不同系列的切片,使用脚本与这些对配合使用,甚至可以将在其他立体相机上拍摄的照片成对放开。
另外,在剪切每张图像之前,脚本会显示其图像,这通常使您可以在下一个校准步骤之前查看失败的照片,并将其删除。
运行脚本:
python 3_pairs_cut.py
短片:
在完成的图像中,有一组我们用于实验的照片和剪切对。
标定
脚本4_calibration.py绘制棋盘中的所有对,并计算必要的校正以校正图片。 该脚本会自动拒绝未找到棋盘的照片,因此,如果照片不成功,工作不会停止。 上传所有30对图片后,计算开始。 我们大约需要一分钟半的时间。 完成后,脚本将获取一对立体声对,并根据计算出的校准参数对它们进行“校正”,从而在屏幕上显示校正后的图像。 此时,您可以评估校准的质量。
通过命令运行:
python 4_calibration.py
工作中的校准脚本:
深度图设置
5_dm_tune.py脚本加载第一个脚本拍摄的图片和校准结果。 接下来,显示一个界面,使您可以更改深度图的设置并查看发生了什么变化。 提示:在设置参数之前,先取一个框架,在该框架中同时放置不同距离的物体:闭合(30-40厘米),平均距离(一两米)和该距离。 这将允许您选择参数,在这些参数中,靠近的对象将为红色,而远处的对象将为深蓝色。
该图像包含具有我们的深度图设置的文件。 您只需单击“加载设置”按钮即可在脚本中加载我们的设置
我们推出:
python 5_dm_tune.py
设置过程如下所示:
实时深度图
最后一个脚本6_dm_video.py使用先前脚本的结果(深度图的校准和设置)从视频中构建深度图。
发射:
python 6_dm_video.py
实际结果是:
我们希望我们的脚本将对您的实验有用!
为了以防万一,我将添加所有脚本都具有按键处理功能,并且您可以通过按Q按钮来中断工作。如果您“大致”停止(例如Ctrl + C),则Python与摄像头的交互过程可能会中断,并且需要重新启动树莓派。
对于高级
- 该过程中的第一个脚本显示两次帧捕获之间的平均时间,完成后显示平均FPS。 这是一个简单方便的工具,用于选择python仍未“窒息”的图像参数。 有了它,我们以20 FPS的速度拍摄了1280x480,其中视频呈现没有延迟。
- 您可能会注意到,我们捕获了1280x480分辨率的立体声对,然后将其缩放为640x240。
一个合理的问题:为什么要所有这些,为什么不立即抓取缩略图并通过缩小而不加载我们的python?
答:在非常低的分辨率下直接捕获时,树莓派核心仍然存在问题(图片破裂)。 因此,我们采用较大的分辨率,然后缩小图片。 这里我们使用了一个小技巧:图片不是使用python缩放的,而是在GPU的帮助下缩放的,因此arm核心没有负载。 - 为什么要以BGRA格式而不是BGR格式捕获视频?
我们使用GPU资源来减小图片的大小,而调整大小模块的本机是BGRA格式。 如果我们使用BGR代替BGRA,我们将有两个缺点。 第一个略低于最终的FPS(在我们的测试中为20%)。 第二个是控制台“ PiCameraAlfaStripping:使用alpha-stripping转换为非alpha格式; 您可能会更快找到等效的Alpha格式”。 对其进行谷歌搜索导致了Picamera文档部分,该部分描述了该技巧。 - PiRGBArray在哪里?
这就像用于相机的本机Picamera类,但此处未使用。 事实证明,在我们的测试中,使用“手工制作”的numpy数组比使用PiRGBArray快得多(大约是一半)。 这并不意味着PiRGBArray不好,很可能是我们弯曲的双手。 - 计算深度图的百分比如何加载?
让我们用图片回答:

我们看到,在处理器的4个内核中,实际上只有一个被加载,占70%。 尽管我们使用GUI,并且我们正在向用户输出图片和深度图,但事实并非如此。 这意味着有很好的性能余量,并且使用C语言中的OpenMP和其他功能对OpenCV进行微调以及没有GUI的“战斗”模式都可以产生非常有趣的结果。 - 通过这些设置获得的最大FPS深度图是多少?
当我们从相机每秒捕获20帧时,我们获得的最大速度为17 FPS。 在深度图设置中,就速度参数而言,最“响应”的是MinDisparity和NumOfDisparities。 这是合乎逻辑的,因为它们确定用于比较帧的搜索窗口在算法内执行的“步数”。 第二敏感的是preFilterCap;它特别影响深度图的“平滑度”。 - 处理器的温度如何?
在Compute Module 3+ Lite(一个新的系列,过程上有一个铁“帽”)上,它大致显示以下结果:

- 如何使用GPU?
至少,它可以用于实时对图片进行安定和校正,因为有示例( 在WebGL上有此示例),Python Pi3d以及Processing项目( 有覆盆子的示例 )。
中村浩一还有另一个有趣的发展,叫做py-videocore 。 在与他的通讯中,他表达了一个想法,即要加速StereoBM,可以在Cuda支持下使用其核心和OpenCV排序。 总的来说,为了优化-正如他们所说,这是未触及的优势。
感谢您的关注,这是
承诺的链接 。