0

最近,我正在努力解决单个相机的姿势估计问题。我在图像上有一些 3D 点和相应的 2D 点。然后我使用solvePnP来获取旋转和平移向量。问题是,如何确定向量是否是正确的结果?

现在我使用一种间接的方式来做到这一点:
我使用旋转矩阵、平移向量和某个点的世界 3D 坐标来获得该点在 Camera 系统中的坐标。那么我所要做的就是确定坐标是否合理。我想我知道相机系统的 x、y 和 z 轴的方向。

  • 相机中心是相机系统的起源吗?
  • 现在考虑该点的 x 分量。x是否等于相机与世界空间中Camera x轴方向上的点的距离(符号可以通过该点放置在相机的哪一侧来确定)?

下图在世界空间中,而描绘的轴在相机系统中。

========How Camera and the point be placed in the world space=============
   |
   |              
Camera--------------------------> Z axis
   |                |} Xw?
   |                P(Xw, Yw, Zw)
   |              
   v x-axis     
     

图片在这里

我的 rvec 和 tvec 结果似乎对与错。对于一个指定的点,z 值似乎是合理的,我的意思是,如果这个点在 z 方向上距离相机大约一米,那么 z 值大约是 1。但是对于 x 和 y,根据位置点我认为 x 和 y 应该是积极的,但他们是消极的。更重要的是,在原始图像中检测到的图案是这样的:

使用从相机捕获的图像中进行特征检测的图案图像

但是使用相机系统中计算的点坐标和相机内在参数,我得到这样的图像:

恢复图像

目标保持其模式。但它从右下角移动到左上角。我不明白为什么。

4

2 回答 2

1

现在我知道答案了。

  • 是的,相机中心是相机坐标系的原点。

  • 考虑相机系统中的坐标计算为 (xc,yc,zc)。那么 xc 应该是相机与现实世界中点在 x 方向上的距离。

接下来,如何判断输出矩阵是否正确?
1. 正如@eidelen 所指出的,反投影误差是一种指示性措施。
2. 根据点在世界坐标系中的坐标和矩阵计算点的坐标。

那么为什么我得到了错误的结果(模式仍然存在但移动到图像的不同区域)?
参数cameraMatrixinsolvePnP()是提供相机外部参数参数的矩阵。在相机矩阵中,您应该对 cx 和 cy 使用 width/2 和 height/2。虽然我使用图像尺寸的宽度和高度。我认为这导致了错误。在我纠正并重新校准相机后,一切似乎都很好。

于 2017-05-12T08:29:20.207 回答
1

是的,相机中心是相机坐标系的原点,这似乎与这篇文章一样

在相机位姿估计的情况下,似乎合理的值可以称为反投影误差。这是对生成的旋转和平移将 3D 点映射到 2D 像素的程度的衡量标准。不幸的是,solvePnP不返回残差测量。因此必须计算它:

cv::solvePnP(worldPoints, pixelPoints, camIntrinsics, camDistortion, rVec, tVec);

// Use computed solution to project 3D pattern to image
cv::Mat projectedPattern;
cv::projectPoints(worldPoints, rVec, tVec, camIntrinsics, camDistortion, projectedPattern);

// Compute error of each 2D-3D correspondence.
std::vector<float> errors;
for( int i=0; i < corners.size(); ++i)
{
    float dx = pixelPoints.at(i).x - projectedPattern.at<float>(i, 0);
    float dy = pixelPoints.at(i).y - projectedPattern.at<float>(i, 1);
    // Euclidean distance between projected and real measured pixel
    float err = sqrt(dx*dx + dy*dy); 

    errors.push_back(err);
}

// Here, compute max or average of your "errors"

校准相机的平均反投影误差可能在 0 - 2 像素的范围内。根据你的两张照片,这会更多。对我来说,这看起来像是一个缩放问题。如果我是对的,你自己计算投影。也许您可以尝试一次 cv::projectPoints() 并进行比较。

当谈到变换时,我学会了不要跟随我的想象 :) 我对返回的 rVec 和 tVec 做的第一件事通常是从中创建一个 4x4 刚性变换矩阵(我在这里发布过一次代码)。这使事情变得不那么直观,但它却紧凑且方便。

于 2017-04-06T09:23:52.597 回答