3

我在带有两个摄像头的多视图场景中使用 C++ 中的 open cv。我有两个相机的内在和外在参数。

我想将视图 1 中的 (X,Y) 点映射到第二个视图中的同一点。我有点不确定我应该如何使用内在和外在矩阵来将点转换为 3D 世界,并最终在视图 2 中得到新的 2D 点。

4

1 回答 1

3

在没有一些附加信息的情况下,(通常)不可能在一个图像中获取 2D 坐标并将其映射到另一个 2D 坐标。

主要问题是左侧图像中的单个点将映射到右侧图像中的一条线(极线)。因为深度是一个自由参数,所以有无数个可能的对应位置。其次,该点完全有可能在正确的图像中不存在,即它被遮挡了。最后,可能很难准确地确定哪个点是正确的对应关系,例如,如果场景中没有纹理,或者它是否包含大量重复特征。

cv::StereoCalibrate尽管基本矩阵(无论如何您都可以摆脱)在每个相机中的点之间为您提供了一个约束: x'Fx = 0,对于给定的x',将有一个完整的x' 族将满足方程。

一些可能的解决方案如下:

  1. 您知道一张图像中 2D 点的 3D 位置。假设 3D 点位于公共坐标系中,您只需使用cv::projectPoints要投影到的其他相机的校准参数即可。

  2. 您可以使用 SIFT 或 ORB 之类的方法进行一些稀疏特征检测和匹配。然后,您可以计算单应性以将点从一个图像映射到另一个图像。这对事物是平面做出了一些假设。如果你谷歌全景单应性,有大量的讲座幻灯片详细说明了这一点。

  3. 您校准您的相机,执行对极校正(cv::StereoRectify, cv::initUndistortRectifyMap, cv::remap),然后通过立体匹配器运行它们。输出是一个视差图,它为您提供了您想要的东西:从一个相机到另一个相机的每像素映射。即,left[y,x] = right[y, x+disparity_map[y,x]]

(1) 是迄今为止最简单的,但您不太可能已经拥有该信息。(2) 通常是可行的并且可能是合适的,正如另一位评论者指出的那样,在平面性假设失败的情况下会很差。(3) 是一般(理想)解决方案,但有其自身的缺点,并且依赖于图像可以进行密集匹配。

于 2017-04-22T23:32:28.547 回答