我计算了5个相机矩阵(c1, ... c5
),通过将3D物体放置在5个不同位置来计算相机矩阵,并且对于每个位置我计算出相机矩阵(并且相机是恒定的)。相机矩阵使用SVD方法计算。
现在我想在opencv
中使用束调整来获得一个最佳的相机矩阵。
我找到了文档here
但是文档不清楚,我也找不到任何示例代码。
任何人都可以解释我如何使用opencv bundle调整来获取optimal camera matrix
?
答案 0 :(得分:9)
我的回答是假设您使用特定的3D对象,其尺寸已知准确,以从多个图像中估算一个摄像头的内在参数对象的em>。根据你对@fireant的回答的评论,我认为这适用于你的问题。
术语“相机矩阵”非常模糊,可以通过多种方式理解:
正如你所说,你有多个图像,但你想要一个相机矩阵,我认为你在谈论内在的相机矩阵K.
束调整是一种用于解决比相机校准更普遍的问题的技术,其中外部相机参数(即3D方向和位置)和3D地标(例如3D点)都是未知的。正如@fireant所指出的,在全局联合优化中也可以包含内在的相机参数。另一方面,相机校准假设3D地标已知并由多个图像中的单个相机观察,因此它优化了一组固有相机参数和每个图像的一个相机姿势。
要理解的是,更一般的优化问题涉及更多要优化的变量,因此更难以使它们受到良好约束。如果它们没有很好的约束,它们将以确实减少全局误差的方式优化变量,但这并不符合您真正问题的解决方案。这就是为什么在使用联合优化算法时,应该总是尝试减少要优化的变量数量。
在捆绑调整VS摄像机校准的情况下,如果您对<3D>地标的位置没有准确的想法,则应该仅使用捆绑调整。即便如此,尝试解耦问题可能是更好的主意,例如事先校准3D对象。如果您确切了解3D地标的位置,则不应将它们视为要优化的变量,因此您应该使用相机校准技术。
您说您对相机矩阵K有多个不准确的估计值,并希望执行联合优化以获得更准确的一个。问题在于,由于您想要估算单个相机矩阵,因此您需要为联合优化算法提供仅一个初始估计。
为了仍然使用多个近似估计,您可以做的是尝试选择最接近真实解决方案的优化算法的初始估计。为此,您可以使用多个启发式标准。例如,您可以选择与最小重投影误差相关联的那个,或者您可以使用与校准对象最大的图像相关联的那个,等等。
然而,它可能不会对相机矩阵的最终估计产生很大的影响。
假设您有一个带有特征点的校准对象。它可以是标准的2D棋盘或不对称圆网格,或任何校准的3D对象。并且假设您已经开发出一种在图像中检测该校准对象的方法(例如,自定义特征检测器或手动确定对象位置的工具)。然后,您可以定义向量allObjectPoints
,其中包含可以检测到的对象上的3D点。然后,对于每个图像i
,您可以确定检测到的2D点的向量imagePoints_i
是对某些对象的3D点的观察(请注意,某些对象点可能被遮挡,因此可能会有更少的项目而不是allObjectPoints
)。然后,由于所有对象点都是可识别的(直接或通过推理),您可以确定向量objectPoints_i
,其中包含在图像i
中实际观察到的对象3D点,并与{{1}一致地排序}。
然后将所有imagePoints_i
向量堆叠在向量objectPoints_i
的一个大向量中。类似地,您将所有objectPoints
向量堆叠在向量imagePoints_i
的一个大向量中。然后,您可以使用标记imagePoints
拨打calibrateCamera
,以表明您希望优化算法使用您提供的初始值。
答案 1 :(得分:8)
请参阅Learning Image Processing with OpenCV第155页的示例代码。像这样:
vector<CameraParams> cameras;
vector<MatchesInfo> pairwise_matches;
vector<ImageFeatures> features(num_images);
// initialize the above params here
Ptr<BundleAdjusterBase> adjuster;
adjuster = makePtr<BundleAdjusterReproj>();
if (!(*adjuster)(features, pairwise_matches, cameras)) {
cout << "Camera parameters adjusting failed." << endl;
return -1;
}
如果您提供MCVE,则可以更轻松地提供帮助。
修改强> 鉴于您有5个相同K矩阵的估计值。最简单的方法是简单地平均您的5个估计值以获得更准确的K.在一些温和的假设下,这将是一个最佳估计。如果重投影错误差异很大,那么您可以计算加权平均值。