KITTI下使用SGBM立体匹配算法获得深度图

KITTI下使用SGBM立体匹配算法获得深度图

以下内容不涉及原理,仅为工程性内容:

经典的立体匹配算法主要由:BM(Block Matching),SGBM(Semi-Global Block matching),GC。更高级的就直接用上了深度学习,这里就不在考虑了。

上述三种算法速度:BM > SGBM > GC,效果:BM < SGBM < GC;暂取折中的SGBM算法研究。

SGBM及相关程序参考博客:

  1. https://www.cnblogs.com/riddick/p/8486223.html
  2. https://blog.csdn.net/cxgincsu/article/details/74451940?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task

SGBM算法参数众多,而且对于不同场景默认参数表现不好,这个问题也出现在了BM算法里面,由于接触的不多,并不清楚这个问题是不是立体匹配的通病。

我使用了KITTI截取的两张图片作为输入,但是在前几次输入时发现一个小问题,我的表现效果和博客上表现的相差极大:

失败的视差图

这是我输出的时差图,可以明显看出这个图片表述的一塌糊涂,一开始我还以为是我参数的问题,所以我调了半天的参数,但是情况并没有本质的改变。于是我向沈老师请教。

沈老师给了我一个很有用的表格:

参数表

但是效果仍然改变不大。这时候老师突然想起来:你是不是左右图颠倒了?这个算法对于左右视图顺序是有要求的。

我试了一下,果然。下图是ndisparities为64、80、128时:

正确的视差图

可以看出随着ndisparities逐渐增加,右侧的碎片数量逐渐减少。到128时基本符合我们的要求。当然,亮度有所下降,但是因为距离拉大了,这个倒是很正常。

值得注意的一点是disp这个参数,opencv解释

disp – Output disparity map. It is a 16-bit signed single-channel image of the same size as the input image. It contains disparity values scaled by 16. So, to get the floating-point disparity map, you need to divide each disp element by 16.

这个意思是:disp每个元素包含16位,其中12位整数,4位小数。如果转化为可读形式的,需要对1.0/16;

对应类型和比特的博客参考:
https://blog.csdn.net/YunLaowang/article/details/86583351

为了验证得到的时差图是否正确,我们需要手工标注验证一下:找出左图和右图中对应的一组特征点,打开画图工具得到他们的坐标,一般来说纵坐标是相同的。将横坐标相减得到时差,在时差图中找到改点(位置同左图),访问该点的元素。

当然,获得视差图仅仅是第一步,后面我们需要通过视差图来获得深度图。

获得深度图之前需要先对视差图进行预处理,我们预处理选择的是之前引用博客中作者给出的方法,直接copy来测试,然后利用视差公式求解深度。

这里有5点注意的地方:

  1. 视差图左边黑条不能去:左边黑条代表右侧相机没有采集到的位置,因此是没有深度的。

  2. 深度图的表示问题:如果仅仅使用8UC1还是没有问题的,但是万一需要使用16UC1及更高的32FC1等时,显示范围扩大到了255以上,这样在imshow基本就是一片黑,无法验证我们的猜想。有一个巧妙的思路是利用.xml文件采集图片的矩阵元素,这样可以看整体的情况,虽不是很直观,但是比一抹黑强很多。关于xml文件的使用详见博客https://blog.csdn.net/YunLaowang/article/details/86583351。另一种方法是对图像像素值进行缩放,至0-255之前,这样可以之间观察像素变化,但是缺点是由于缩放原因,像素差值不大。两种方法各有利弊,综合使用效果更好。

  3. 在对深度值缩放至0-255之间以方便进行表示时,删去空洞填充中高斯模糊部分。因为深度缩放后差距极小,很容易全部变成一种颜色。

  4. 一开始我模仿博客代码选择16UC1,但是由于不便于直接观察,因此我试图将depthMap选择我8UC1格式,但是结果显示,道路部分深度误差较大问题,在时差图上表现良好的道路在深度图中出现了明显的层次,详见下面:错误的深度图

    经过老师沟通,发现是范围出现了问题,8U表示范围在2的8次方,255,而最大深度值f*b/1=718.856*35=25159.96,远超8位depthMap所能表示的数据范围,因此被截断了,出现了奇怪的现象。修正方法详见第二点,修正后的图片如下:
    缩放的深度图
    测试代码如下:

#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <cmath>
//#include <Eigen/Core>
//#include <Eigen/Geometry>
using namespace std;
using namespace cv;

void insertDepth32f(cv::Mat& depth);

float fx = 718.856;
float baseline = 35;

int main(int argc, char const *argv[])
{
   
	cv::Mat imgR,imgL;
	imgL = cv::imread( argv[1],IMREAD_GRAYSCALE );
	imgR = cv::imread( argv[2],IMREAD_GRAYSCALE );
    int mindisparity = 0;
    int ndisparities = 
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值