我在墙上有一个已知尺寸和位置的矩形目标,以及机器人上的移动摄像头。当机器人在房间里行驶时,我需要找到目标并计算摄像机的位置及其姿势。另外,使用伺服系统可以改变摄像机的高度和方位角。我能够使用OpenCV定位目标,但我仍然模糊计算摄像机的位置(实际上,我的额头上有一个平坦的位置,因为上周我的头撞在墙上)。这就是我在做的事情:
我已经阅读过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的原点位于屏幕的左上方。)
姿势中有哪些单位?
答案 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)
之间编辑: 我可能弄错了。我读到姿势是指示摄像机方向的矢量,矢量的长度表示相机围绕该矢量旋转多少。