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

BCa*_*Cat 9 opencv pose-estimation

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

  1. 读入先前计算的相机内在文件
  2. 从轮廓中获取目标矩形的4个点的像素坐标
  3. 使用矩形的世界坐标,像素坐标,相机矩阵和失真矩阵调用solvePnP
  4. 使用旋转和平移向量调用projectPoints
  5. ???

我已经阅读了OpenCV书籍,但我想我只是遗漏了一些如何使用投影点,旋转和平移向量来计算相机的世界坐标及其姿势(我不是数学专家): - (

2013-04-02根据"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));
}
Run Code Online (Sandbox Code Playgroud)

我在我的测试中使用的像素坐标是从目标矩形左侧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
Run Code Online (Sandbox Code Playgroud)

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

姿势是什么单位?

mor*_*icz 8

您可以从中获取平移和旋转矢量solvePnP,这些矢量指示相机坐标中的对象在哪里.你需要得到一个逆变换.

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

如果您知道对象在世界坐标中的位置您可以使用world-> object transform*object-> camera transform矩阵来提取摄像机的平移和姿势.

姿势由单个矢量或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;
Run Code Online (Sandbox Code Playgroud)

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