如何使用opencv bundle调整

Dee*_*pak 9 camera opencv mathematical-optimization camera-calibration

我已经计算了5个相机矩阵(c1, ... c5),通过将3D物体放置在5个不同的位置来计算相机矩阵,并且对于每个位置我已经计算出相机矩阵(并且相机是恒定的).相机矩阵使用SVD方法计算.

现在我想使用束调整opencv来获得一个最佳的相机矩阵.我在这里找到了文档

但文档不清楚,我也无法找到任何示例代码.任何人都可以解释我如何使用opencv bundle调整来获取optimal camera matrix

fir*_*ant 10

请参阅使用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;
}
Run Code Online (Sandbox Code Playgroud)

如果您提供MCVE,那么它会更容易提供帮助.

编辑: 鉴于您有5个相同K矩阵的估计值.最简单的方法是简单地平均您的5个估计值以获得更准确的K.在一些温和的假设下,这将是一个最佳估计.如果重投影错误差异很大,那么您可以计算加权平均值.


BCo*_*nic 10

我的回答是假设你使用一个特定的三维物体,其尺寸已经准确知道,从物体的多个图像估计一个摄像机的内在参数.根据你对@fireant的回答的评论,我认为这适用于你的问题.

关于'相机矩阵'含义的快速说明

术语"相机矩阵"非常模糊,可以通过多种方式理解:

  • 相机姿势T = [R | t],也表示外部相机参数.
  • 内在相机矩阵K = [fx,s,cx; 0,fy,cy; 0,0,1].
  • 相机投影矩阵P = K. [R | t].

正如你所说,你有多个图像,但你想要一个相机矩阵,我认为你在谈论内在的相机矩阵K.

为什么你不应该使用捆绑调整

捆绑调整是一种用于解决比摄像机校准更普遍的问题的技术,其中外部摄像机参数(即3D方向和位置)和3D地标(例如3D点)都是未知的.正如@fireant所指出的,在全局联合优化中也可以包含内在的相机参数.另一方面,相机校准假设3D地标是已知的并且由多个图像中的单个相机观察,因此它优化了一组固有相机参数和每个图像的一个相机姿势.

要理解的是,更一般的优化问题涉及更多要优化的变量,因此更难以使它们受到良好约束.如果它们没有很好的约束,它们将以确实减少全局误差的方式优化变量,但这并不符合您真正问题的解决方案.这就是为什么在使用联合优化算法时,您应该总是尝试减少要优化的变量数量.

在捆绑调整VS摄像机校准的情况下,如果您不准确了解 3D地标的位置,则应仅使用捆绑调整.即便如此,尝试解耦问题可能是更好的主意,例如事先校准3D对象.如果您对3D地标的位置有准确的了解,那么它们不应被视为要优化的变量,因此您应该使用相机校准技术.

优化的初步估计

您说您对相机矩阵K有多个不准确的估计值,并希望执行联合优化以获得单个更准确的估计.问题在于,由于您想要估计单个摄像机矩阵,因此需要为联合优化算法提供一个初始估计.

为了仍然使用多个近似估计,您可以做的是尝试选择最接近真实解决方案的优化算法的初始估计.为此,您可以使用多个启发式标准.例如,您可以选择与最小重投影误差相关联的那个,或者您可以使用与校准对象最大的图像相关联的那个,等等.

但是,它可能不会对相机矩阵的最终估计产生很大的影响.

如何使用'calibrateCamera'完成此任务

假设您有一个带有特征点的校准对象.它可以是标准的2D棋盘或不对称圆网格,或任何校准的3D对象.并且假设您已经开发出一种在图像中检测此校准对象的方法(例如,自定义特征检测器或手动确定对象位置的工具).然后,您可以定义一个矢量allObjectPoints,其中包含可以检测到的对象上的3D点.然后,对于每个图像i,您可以确定imagePoints_i检测到的2D点的矢量是对某些物体的3D点的观察(注意,一些物体点可能被遮挡,因此物品可能少于其中allObjectPoints).然后,由于所有对象点都是可识别的(直接或通过推理),您可以确定向量objectPoints_i,包含在图像中实际观察到的对象3D点i并且与其一致排序imagePoints_i.

然后将所有objectPoints_i向量堆叠在一个向量的大向量中objectPoints.类似地,您将所有imagePoints_i向量堆叠在一个向量的大向量中imagePoints.然后,您可以calibrateCamera使用标志调用,CV_CALIB_USE_INTRINSIC_GUESS以指示您希望优化算法使用您提供的初始值.