我在带有两个摄像头的多视图场景中使用C ++中的open cv。我有两个摄像头的内在和外在参数。
我想将视图1中的(X,Y)点映射到第二个视图中的同一点。我有点不确定如何使用内在矩阵和外在矩阵将点转换为3D世界,最后以视图2中的新2D点结束。
答案 0 :(得分:2)
(通常)不可能在一个图像中采用2D坐标并将其映射到另一个2D坐标而无需其他信息。
主要问题是左图像中的单个点将映射到右图像中的一条线(一条极线)。存在无限数量的可能对应位置,因为深度是自由参数。其次,完全有可能在右图像中点不存在,即它被遮挡。最后,可能难以确切地确定哪个点是正确的对应关系,例如,如果场景中没有纹理或者它包含许多重复的特征。
虽然基本矩阵(无论如何你从cv::StereoCalibrate
得出)给你一个约束,每个相机中的点:x'Fx = 0
,对于给定的x'
,将有一个完整的家庭x
的{{1}}将满足等式。
一些可能的解决方案如下:
您知道一个图像中2D点的3D位置。如果3D点位于公共坐标系中,您只需将cv::projectPoints
与要投影的另一台摄像机的校准参数一起使用。
使用SIFT或ORB之类的东西进行稀疏特征检测和匹配。然后,您可以计算单应性以将点从一个图像映射到另一个图像。这对飞机的事情做了一些假设。如果你是谷歌全景单应,那么有很多讲座幻灯片详细介绍了这一点。
您校准相机,执行极线校正(cv::StereoRectify
,cv::initUndistortRectifyMap
,cv::remap
),然后通过立体匹配器运行它们。输出是一个视差图,它可以准确地提供您想要的内容:从一个摄像头到另一个摄像头的每像素映射。也就是left[y,x] = right[y, x+disparity_map[y,x]]
。
(1)是迄今为止最简单的,但你不太可能已经掌握了这些信息。 (2)通常是可行的并且可能是合适的,并且正如另一位评论者所指出的那样,在平面性假设失败的情况下会很差。 (3)是一般(理想)解决方案,但有其自身的缺点,并依赖于图像适合密集匹配。