如何确定相机的世界坐标?

时间:2013-03-31 07:55:23

标签: opencv pose-estimation

我在墙上有一个已知尺寸和位置的矩形目标,以及机器人上的移动摄像头。当机器人在房间里行驶时,我需要找到目标并计算摄像机的位置及其姿势。另外,使用伺服系统可以改变摄像机的高度和方位角。我能够使用OpenCV定位目标,但我仍然模糊计算摄像机的位置(实际上,我的额头上有一个平坦的位置,因为上周我的头撞在墙上)。这就是我在做的事情:

  1. 读入先前计算的相机内在文件
  2. 从轮廓
  3. 获取目标矩形的4个点的像素坐标
  4. 使用矩形的世界坐标,像素坐标,相机矩阵和失真矩阵调用solvePnP
  5. 使用旋转和平移向量调用projectPoints
  6. ???
  7. 我已经阅读过OpenCV书,但我想我只是遗漏了一些如何使用投影点,旋转和平移向量来计算相机的世界坐标及其姿势(我不是数学巫师) ): - (

    2013年4月2日 根据“morynicz”的建议,我写了这个简单的独立程序。

    #include <Windows.h>
    #include "opencv\cv.h"
    
    using namespace cv;
    
    int main (int argc, char** argv)
    {
    const char          *calibration_filename = argc >= 2 ? argv [1] : "M1011_camera.xml";
    FileStorage         camera_data (calibration_filename, FileStorage::READ);
    Mat                 camera_intrinsics, distortion;
    vector<Point3d>     world_coords;
    vector<Point2d>     pixel_coords;
    Mat                 rotation_vector, translation_vector, rotation_matrix, inverted_rotation_matrix, cw_translate;
    Mat                 cw_transform = cv::Mat::eye (4, 4, CV_64FC1);
    
    
    // Read camera data
    camera_data ["camera_matrix"] >> camera_intrinsics;
    camera_data ["distortion_coefficients"] >> distortion;
    camera_data.release ();
    
    // Target rectangle coordinates in feet
    world_coords.push_back (Point3d (10.91666666666667, 10.01041666666667, 0));
    world_coords.push_back (Point3d (10.91666666666667, 8.34375, 0));
    world_coords.push_back (Point3d (16.08333333333334, 8.34375, 0));
    world_coords.push_back (Point3d (16.08333333333334, 10.01041666666667, 0));
    
    // Coordinates of rectangle in camera
    pixel_coords.push_back (Point2d (284, 204));
    pixel_coords.push_back (Point2d (286, 249));
    pixel_coords.push_back (Point2d (421, 259));
    pixel_coords.push_back (Point2d (416, 216));
    
    // Get vectors for world->camera transform
    solvePnP (world_coords, pixel_coords, camera_intrinsics, distortion, rotation_vector, translation_vector, false, 0);
    dump_matrix (rotation_vector, String ("Rotation vector"));
    dump_matrix (translation_vector, String ("Translation vector"));
    
    // We need inverse of the world->camera transform (camera->world) to calculate
    // the camera's location
    Rodrigues (rotation_vector, rotation_matrix);
    Rodrigues (rotation_matrix.t (), camera_rotation_vector);
    Mat t = translation_vector.t ();
    camera_translation_vector = -camera_rotation_vector * t;
    
    printf ("Camera position %f, %f, %f\n", camera_translation_vector.at<double>(0), camera_translation_vector.at<double>(1), camera_translation_vector.at<double>(2));
    printf ("Camera pose %f, %f, %f\n", camera_rotation_vector.at<double>(0), camera_rotation_vector.at<double>(1), camera_rotation_vector.at<double>(2));
    }
    

    我在测试中使用的像素坐标是从目标矩形左侧27英尺(宽62英寸,高20英寸)拍摄的真实图像,大约45度角。输出不是我所期待的。我做错了什么?

    Rotation vector
    2.7005
    0.0328
    0.4590
    
    Translation vector
    -10.4774
    8.1194
    13.9423
    
    Camera position -28.293855, 21.926176, 37.650714
    Camera pose -2.700470, -0.032770, -0.459009
    

    如果我的世界坐标的Y轴与OpenCV的屏幕Y轴的Y轴相反,会不会有问题? (我的坐标系的原点位于目标左侧的地板上,而OpenCV的原点位于屏幕的左上方。)

    姿势中有哪些单位?

2 个答案:

答案 0 :(得分:8)

你从solvePnP得到平移和旋转向量,它们告诉摄像机坐标中的对象在哪里。你需要得到一个逆变换。

变换相机 - &gt;对象可以写为齐次坐标的矩阵[R T;0 1]。该矩阵的逆是使用它的特殊属性[R^t -R^t*T;0 1],其中R ^ t是R转置的。你可以从Rodrigues变换得到R矩阵。这样,您可以获得转换对象 - >相机坐标的平移向量和旋转矩阵。

如果你知道对象在世界坐标中的位置你可以使用world-&gt; object transform * object-&gt;相机变换矩阵来提取相机的平移和姿势。

姿势由单个矢量或R矩阵描述,你肯定会在你的书中找到它。如果是“学习OpenCV”,您将在第401-402页找到它:)

查看您的代码,您需要执行类似的操作

    cv::Mat R;
    cv::Rodrigues(rotation_vector, R);

    cv::Mat cameraRotationVector;

    cv::Rodrigues(R.t(),cameraRotationVector);

    cv::Mat cameraTranslationVector = -R.t()*translation_vector;

cameraTranslationVector包含相机坐标。 cameraRotationVector包含相机姿势。

答案 1 :(得分:-1)

我永远理解它,但姿势意义是每个轴上的旋转 - x,y,z。 它是弧度。值介于Pie到minus Pie(-3.14 - 3.14)

之间

编辑: 我可能弄错了。我读到姿势是指示摄像机方向的矢量,矢量的长度表示相机围绕该矢量旋转多少。