【发布时间】:2014-11-08 08:23:15
【问题描述】:
目的是为校准的立体图像生成视差图。
使用 OpenCV 函数 cv::projectPoints() 将 3D 模型投影到一对校准的立体图像(左/右)上。 cv::projectPoints() 在 cv::Point2f 中给出二维图像坐标上的点,即亚像素精度。
由于一些 3D 点被投影到相同的像素区域,我只保留深度/Z 较小的点,因为更近的点会遮挡更多的点。
通过这样做,我可以分别获得左右图像的两个索引图像。索引图像的每个像素指的是其在 3D 模型中的位置(存储在 std::vector 中)或在 2D 中的位置(std::vector)。
下面sn -p应该简单解释一下程序:
std::vector<cv::Point3f> model_3D;
std::vector<cv::point2f> projectedPointsL, projectedPointsR;
cv::projectPoints(model_3D, rvec, tvec, P1.colRange(0,3), cv::noArray(), projectedPointsL);
cv::projectPoints(model_3D, rvec, tvec, P2.colRange(0,3), cv::noArray(), projectedPointsR);
// Each pixel in indexImage is a index pointing to a position in the vector of projected points
cv::Mat indexImageL, indexImageR;
// This function filter projected points and return the index image
filterProjectedPoints(projectedPointsL, model_3D, indexImageL);
filterProjectedPoints(projectedPointsR, model_3D, indexImageR);
为了生成视差图,我可以:
1.对于视差图中的每个像素,在左/右索引图像中找到对应的像素位置并减去它们的位置。这种方式给出了整数差异(不是亚像素精度);
2.对于视差图中的每个像素,在左右投影点上找到其2D(浮动精度)位置,并计算x轴上的差异作为视差。这种方式会产生亚像素精度差异。
第一种方法很简单,但由于忽略了亚像素投影点而引入了误差。 然而,第二种方式也引入了误差,因为一对投影像素(来自相同的 3D 点)可能被投影到像素内的不同位置。例如,左图中的投影点为 (115.289, 80.393),右图中的投影点为 (145.686, 79.883)。它在视差图中的位置将是 (115, 80),视差可以是:145.686 - 115.289 = 30.397。如您所见,它们可能没有完全对齐以具有相同的 y 坐标。
问题是: 1. 两种方式都正确吗(除了引入错误)? 2.如果第二种方式是正确的,如果计算亚像素精度差异时误差是可忽略的。
好吧,你也可以告诉我在这种情况下你将如何计算亚像素视差图。
【问题讨论】:
-
为什么不看一下用于生成 OpenCV 中已经可用的视差图的代码和文档? BlockMatching,或StereoSGBM。
-
@Unapiedra,我对此有所了解,并试图通读代码。然而,这对我来说有点模糊,因为有内存操作和缺少 cmets。我再看一遍,看看能不能看懂,谢谢。
-
@Unapiedra 此外,OpenCV BM 和 SGBM 尝试找到每个像素的差异以最小化成本,而在这里我已经有了对应关系并想要计算差异。
-
如果您已经知道物体的 3D 位置,为什么还需要视差图?为什么你不能分析地找到它,即在纸上?
-
@Unapiedra 我需要生成地面实况视差图以进行立体算法评估