自己弄基于opencv的sgbm输出双目深度图的一些坑点注意点整理

1 首先16位深度图得显示和保存为png,都是先转为8位的灰度图再显示和保存(所以rqt_image_view保存下来的D435i的深度图话题的深度图是8位的,像素值最大是255),想想也好理解,8位就256种灰度,16位有65536种灰度,你让别人显示这么多种灰度也确实难了点。还有目前经过一番研究,认为D435i的深度图显示,是做了手脚的,就是不是按照原本的深度值去显示的,也不是按照对应等比例的8位灰度图去显示的,所以才看着层次感明显,应该是按照实际的最大深度值再相应缩放显示,这样使得不管看哪里,深度图的黑白层次都比较明显(看D435i的bag包,里面深度图的颜色变化发现的,同样的距离,会因为视野里看到的最大距离不同,而显示的灰度深浅不同)。

2 十六位的深度图,取像素值的时候,不能用mat.data[id]; id = iwidth + j 的方式,是被https://blog.csdn.net/qq_36955294/article/details/84140788 里面的视差转深度图的函数带偏了!!!而且李迎松自己的代码里也喜欢用mat.data[id]; id = iwidth + j 的方式,当然他处理的8位的视差图这没有影响,处理16位的深度图时,得用mat.at<uint16_t>(i,j)的形式去读取16位深度图的像素值,这样不管是取值还是赋值,都是8位的,不是16位,所以导致了一系列的问题,你深度值算得正确,赋值也没有赋上去。

3 除法想得到小数,两个里面得有个浮点数,不然小心得到全是0,这个在把16位的深度转为8位深度同时按照最大深度值相应缩放时可能会遇到,这么做时为了转为对于8位灰度图进行显示和存为png,注意一下就行。

4 得到的深度图并非每个像素点都是有像素值的,会存在一些视差图像素值为0的像素点,除法分母不能为0,这个时候遇到这些点算深度值的之后会选择跳过,那么这些点的像素值就取决于初始建立深度图时候的赋值,我是赋值为0,也就是初始的时候是一个全黑的图,如果初始的时候是个全白的图,容易导致rqt_image_view显示的时候出现很多白色条纹。
也就是代码里这一句

if (!dispMap.at<uint16_t>(i, j))  continue;  //防止0除

我看D435i的深度图或者李迎松写的SGBM输出的深度图,这种视差为0的似乎都是默认给的黑,而不是白,似乎宁可偏黑也不偏白。想想这么做也有道理,直接给全白相当于深度值是65米了,这个不太现实,而且像rqt_image_view进行归一化显示的时候,也显示效果可能不好,归一化效果不太好。

 5 自己弄两张图的深度图估计,得到的深度图左边有一竖块是没有深度值的,这个是正常的,因为单纯靠两张图片,必然左侧有一部分是没有视差的。

6 opencv的StereoSGBM类里面的compute函数输出的视差图是个单通道16位的图像,其中里面还有4位是代表小数,也就是12位是整数4位是小数,opencv叫这是fixed-point类型中文叫定点型类型,浮点型的英文是floating-point,这个数的单位应该是像素,那么我只需要把这16位里面的12位整型取出来,再通过视差转深度公式,就可以得到对应单位是毫米的深度值,这么算比用什么normalize函数或者coverTo函数靠谱多了,他们的转换,你都不清楚他们按照什么比例去压缩的,导致最终最后算出的深度图的深度值其实不是毫米为单位的,存在一定的比例差,导致看着的深度图话题和实际的D435i深度图话题看着有点区别比如整体偏暗许多。现在清楚了自己该怎么算之后,就是如何代码实现了,关键就是如何从这个16位的定点型里面取出其中12位代表整型的值,我开始还想搜搜有没有什么现成函数什么的,后来发现自己弄挺简单的,把这16位数当成一个整型,然后除以2的4次方,余下的不就是那12位的代表真正整数位的数了么,基于此我就再专门写了一个disp2Depth_函数,直接把compute输出的16位的视差图转为16位的深度图,中间也不用什么归一化函数转为什么8为视差图了,这么最终出来的深度图话题就和D435i的深度图话题差不多了,也应该是一样的,而且自己可以严格确保这个深度图的像素值是毫米为单位的,自然就是和D435i的深度图话题一样了。后面可以考虑把compute函数输出视差图里的小数也用上。或许这样生成的深度图更精细一些。

7 opencv里面视差图有16位甚至32位的小数是有道理的,这样会让远处的深度图也比较精细,不至于一层一层很明显。弄mvsnet时候有个词叫亚像素估计。

 

 

  • 9
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
OpenCV是一个开源的计算机视觉库,可以用于图像处理和计算机视觉任务。在处理视觉任务时,通过计算图像中物体的视差值,可以得到这些物体的深度信息。 视差图转深度图的过程主要有以下几个步骤: 1. 从双目图像中计算视差图:双目摄像头捕获的图像包含了左右两个视角的图像,通过比较两幅图像中相同的位置偏移量,可以计算得到每个像素的视差值。OpenCV提供了SGBM(Semi-Global Block Matching)等算法来实现视差图的计算。 2. 根据相机参数计算深度值:根据双目摄像头的参数以及对应的分辨率等信息,可以利用三角测量的原理,将视差值转换为物体距离相机的深度值。这个过程需要知道相机的基线距离、焦距等参数信息。 3. 生成深度图:通过将视差值映射到深度值,可以得到每个像素对应的深度信息。将深度值进行可视化处理,就可以生成深度图。 在OpenCV中,可以使用cv2.reprojectImageTo3D()函数将视差图转换为深度图。该函数需要输入视差图、相机的立体校正变换矩阵和相机内参矩阵。然后,根据相机的参数信息,将视差值转换为云信息(每个像素对应一个3D坐标),并且根据三维坐标计算深度值,最终得到深度图。 总之,OpenCV提供了一系列的函数和算法,可以将视差图转换为深度图。通过计算每个像素的视差值和相关的相机参数,可以获得深度信息,从而进一步实现基于视差图的三维重建和深度感知任务。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值