立体匹配视差图生成

6

我正在处理KITTI数据集,取两张图像并找到视差以获取3D点云。我面临的问题是无法得到良好的视差图。大多数视差值小于0.1。视差值在0到1之间(我需要对它们进行缩放吗)?我的立体参数如下:

cv::StereoBM sbm;
    sbm.state->SADWindowSize = 9;
    sbm.state->numberOfDisparities = 112;
    sbm.state->preFilterSize = 5;
    sbm.state->preFilterCap = 1;
    sbm.state->minDisparity = 0;
    sbm.state->textureThreshold = 5;
    sbm.state->uniquenessRatio = 5;
    sbm.state->speckleWindowSize = 0;
    sbm.state->speckleRange = 20;
    sbm.state->disp12MaxDiff = 64;
sbm(leftimage, rightimage,disp);
    normalize(disp, disp8, 0.1, 255, CV_MINMAX, CV_8U);

right image left image Disparity map


2
没问题。是的,当你使用滑动窗口进行视差计算时,你必须找到合适的窗口大小。太小了意味着你无法捕捉到任何视差...而太大则可能会在比较窗口中引入错误信息。虽然使用滑动窗口速度很快,但并不提供最佳结果。已经有一些关于自适应确定窗口大小的研究。请查看Kanade和Okutomi的工作:http://www.cs.cmu.edu/~ph/869/papers/kanade-okutomi.pdf - 不管怎样,我离题了。很高兴你解决了问题! - rayryeng
感谢您的所有帮助和信息... - shashank bhushan
对于使用矩形窗口(宽度大于高度)的地面点,由于它们沿y轴具有不断变化的视差(因此在滑动窗口区域内视差不是恒定的),建议您查看与“V-视差图像”相关的研究。 - Antonio
抱歉 @Antonio,我没有理解你的意思。你能详细说明一下吗?谢谢。 - shashank bhushan
想象一个以地面某一点为中心的正方形窗口。该窗口的顶部像素对应于比同一窗口底部像素对应的更远的地面点。因此,同一窗口内顶部像素的正确视差低于底部像素。对于大窗口,这会导致匹配效果较差。然而,例如,如果您使用双倍宽度和半高度(相同面积)的窗口,则顶部和底部像素之间的视差差异将更小,在窗口内具有更均匀的视差,可能会导致更好的匹配。 - Antonio
显示剩余4条评论
1个回答

17
您的“视差图”看起来适用于块匹配。块匹配是获取视差图的最基本方法之一,它是一种局部方法,通过暴力搜索(经过opencv滤波)计算视差估计值。因此,它的输出精度有限且通常存在噪点。正如其他人所提到的,您可以调整窗口大小略微改善结果,但这不会显著提高视差的质量。如果需要,可以查看KITTI基准上的立体评估并选择更准确的算法。OpenCV实现了SGM,可以产生更平滑的视差图。所需的视差图质量取决于您的应用程序。在某些情况下,块匹配已足够使用。在其他情况下,则可能不够用。请记住,视差的定义是:左图像中像素的x坐标与其在右图像中对应像素的x坐标之间的差异。也就是说,视差的单位是“像素”。较大的视差意味着更近的物体。当您缩放图像以进行显示时,较大的视差会变得更亮。例如,路上的标志靠近相机,比路上远处的像素更亮。
您的视差值不应该在0和1之间。您正在对图像进行缩放以显示为uint8,这对于显示来说是可以的,但不适合将视差用于实际测量。
在OpenCV中,默认行为是生成一个带有符号短整型的视差图,通过将亚像素移位乘以16获得。要获得真实的视差值,您需要将OpenCV的输出除以16并转换为float。
您可以像这样做:
cv::Mat<float> true_dmap = disp * (1.0 / 16.0f);

或者

disp.convertTo(true_dmap, CV_32F, 1.0/16.0, 0.0);

或者,您可以调用reprojectImageTo3D来获取基于估计视差图和立体校准的点云。

注意,如果您尝试通过imshow显示true_map,您将看不到有意义的东西。

祝好运,


1
嘿,Bender,你的回答相当令人印象深刻。我一直在使用OpenCV中的stereoBM的GPU版本,但奇怪的是它返回的结果与CPU版本不同,并且大多数参数设置似乎没有作用。代码的GPU版本返回8UC1,而CPU版本返回16SC1。我的深度计算好像出了问题,例如在50厘米距离处得到20000厘米。请问我该如何获得正确的距离? - mohanen b
如果你尝试通过imshow显示true_map,你将看不到有意义的东西。也许你可以补充一下什么“工具”能够显示出有意义的内容。 - vyi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接