姿态估计:我在推理中的错误在哪里?

时间:2015-12-14 08:55:37

标签: c++ opencv

我正在尝试进行姿势估计。但我显然做错了什么。 我使用charuco board校准了相机。使用它进行姿态估计,所以我猜我的校准数据没有错误。

好的,我们说我有一个由4个标记组成的模式(A,B,C,D)。 这些标记中的每一个都具有图像坐标和图案坐标。 模式的原点是多边形的中心。

Pattern Upright

图像坐标(x / y)如下。 (在1280x960图像中)

  
      
  • Origin(616/814)
  •   
  • A(561/664)

  •   
  • B(八百三十八分之七百〇二)

  •   
  • C(982分之637)

  •   
  • d(七百五十五分之五百二十○)

  •   
     

模式坐标(x / y / z)

     
      
  • 原点(0/0/0)

  •   
  • A(-12/32/0)

  •   
  • B(18 / 10-5 / 0)

  •   
  • C(12 / -36 / 0)

  •   
  • d(21/13/0)​​

  •   

现在它旋转90度,但我的坐标系不会随图案旋转。  我想知道出了什么问题?是因为Z坐标总是0吗?

Pattern horizontal

  
      
  • (X / Y)
  •   
  • Origin(632/784)
  •   
  • A(718/812)

  •   
  • B(938分之567)

  •   
  • C(九百〇九分之四百四十一)

  •   
  • d(784分之632)

  •   
     

模式坐标(x / y / z)

     
      
  • 原点(0/0/0)

  •   
  • A(32/12/0)

  •   
  • B(-4/18/0)

  •   
  • C(-35/11/0)

  •   
  • d(11/19/0)

  •   

我正在使用像这样的solvePnP

 cv::solvePnP(patternPoints, imgPoints, cameraMatrix, distCoeffs, rvec, tvec);

绘制轴

//Method Call
pattern.drawAxis(image, camMatrix, distCoeffs, rvec, tvec,10);

//Implementation (taken from aruco.cpp)

void drawAxis(InputOutputArray _image, InputArray _cameraMatrix, InputArray _distCoeffs,
              InputArray _rvec, InputArray _tvec, float length) {

    CV_Assert(_image.getMat().total() != 0 &&
              (_image.getMat().channels() == 1 || _image.getMat().channels() == 3));
    CV_Assert(length > 0);

    // project axis points
    vector< Point3f > axisPoints;
    axisPoints.push_back(Point3f(0, 0, 0));
    axisPoints.push_back(Point3f(length, 0, 0));
    axisPoints.push_back(Point3f(0, length, 0));
    axisPoints.push_back(Point3f(0, 0, length));
    vector< Point2f > imagePoints;
    projectPoints(axisPoints, _rvec, _tvec, _cameraMatrix, _distCoeffs, imagePoints);

    // draw axis lines
    line(_image, imagePoints[0], imagePoints[1], Scalar(0, 0, 255), 3);
    line(_image, imagePoints[0], imagePoints[2], Scalar(0, 255, 0), 3);
    line(_image, imagePoints[0], imagePoints[3], Scalar(255, 0, 0), 3);
}

修改:计算图案坐标的代码

void calculateCoordinatesRealtiveToCenter(cv::Point2d center, Marker& p1, double realWorldPixelSize)
{
    double dx = p1.imageCoordinate.x - center.x;
    double dy = center.y - p1.imageCoordinate.y;

    p1.patternCoordinate.x = dx * realWorldPixelSize;
    p1.patternCoordinate.y = dy * realWorldPixelSize;
}

1 个答案:

答案 0 :(得分:3)

我自己从未使用过solvePnP,所以这可能不是100%真实。以前我见过人们使用solvePnP计算相机移动而不是物体移动,但文档说它实际上计算了物体位置。这是我的解释:

objectPoints – Array of object points in the object coordinate space 这些是3D空间中的对象点,但不是全局对象坐标,而是相对于其自身坐标系的对象坐标。因此,如果对象是实体,则此对象的这些坐标将是固定的。例如,如果立方体的坐标原点设置为其重心,则角点将位于(-n,-n,-n);(-n,-n,n);(-n,n,-n)位置,依此类推。无论对象如何旋转或平移,这些对象点都是相同的,因为它们相对于对象自己的坐标系。您想要计算的是此对象坐标系的位置。

最后你对相机外部参数(如果场景是固定的)或物体外部参数(如果相机是固定的)感兴趣,但两者都可以以相同的方式计算(也许矩阵操作顺序必须是还原或矩阵必须倒置。)

因此,对于您的任务,您将进行此设置:

The image coordinates (x/y) are the following. (In a 1280x960 image)

    Origin(616/814)

    A(561/664)
    B(702/838)
    C(637/982)
    D(520/755)

Pattern coordinates (x/y/z)

    Origin(0/0/0)
    A(-12/32/0)
    B(18/-5/0)
    C(12/-36/0)
    D(21/13/0)

和第二张图片:

    (x/y)
    Origin(632/784)

    A(718/812)
    B(567/938)
    C(441/909)
    D(632/784)

Pattern coordinates (x/y/z)

    Origin(0/0/0)
    A(-12/32/0)
    B(18/-5/0)
    C(12/-36/0)
    D(21/13/0)

我不确定你是如何计算第二张图片中的“图案坐标”的。可能是你通过旋转对象来旋转它们,但无论如何,你改变了对象的内在坐标系,这就是你观察到错误结果的原因。