我使用OpenCV中和了openFrameworks(即OpenGL的),从图像计算的相机(世界变换和投影矩阵)(后来,几个图像进行三角测量)。
对于OpenCV中的目的,“平面图”成为与0,0,0世界的中心目标(即棋盘)。 世界/楼层位置是已知的,所以我需要让投影信息(失真系数,FOV等)和摄像机的外在坐标。
我已映射这些平面布置图的点的视图位到在归一化的视图空间我的2D图像([0,0]是左上。[1,1]是右下图)。
对象(平面图/世界分)是XZ平面,-y,所以我转换为OpenCV的xy平面(这里不知道是否Z-UP为负或正...),因为它需要是平面
ofMatrix4x4 gWorldToCalibration(
1, 0, 0, 0,
0, 0, 1, 0,
0, 1, 0, 0,
0, 0, 0, 1
);
我通过1,1为IMAGESIZE到calibrateCamera。 标志CV_CALIB_FIX_ASPECT_RATIO|V_CALIB_FIX_K4|CV_CALIB_FIX_K5
calibrateCamera
成功运行,给了我一个小错误(通常约为0.003
)。
使用calibrationMatrixValues
我得到一个合理的FOV,通常50度左右,所以我敢肯定的内在特性是正确的。
我们计算出相机的外在世界空间变换...我不认为我需要使用solvePnP
因为我只有一个对象(虽然我想这一切之前,与它带回来了相同的结果)
// rot and trans output...
cv::Mat& RotationVector = ObjectRotations[0];
cv::Mat& TranslationVector = ObjectTranslations[0];
// convert rotation to matrix
cv::Mat expandedRotationVector;
cv::Rodrigues(RotationVector, expandedRotationVector);
// merge translation and rotation into a model-view matrix
cv::Mat Rt = cv::Mat::zeros(4, 4, CV_64FC1);
for (int y = 0; y < 3; y++)
for (int x = 0; x < 3; x++)
Rt.at<double>(y, x) = expandedRotationVector.at<double>(y, x);
Rt.at<double>(0, 3) = TranslationVector.at<double>(0, 0);
Rt.at<double>(1, 3) = TranslationVector.at<double>(1, 0);
Rt.at<double>(2, 3) = TranslationVector.at<double>(2, 0);
Rt.at<double>(3, 3) = 1.0;
现在我有一个旋转和变换矩阵,但它是列为主(我相信作为对象是完全倾斜,如果我不转,以上代码看起来列为主向我)
// convert to openframeworks matrix AND transpose at the same time
ofMatrix4x4 ModelView;
for ( int r=0; r<4; r++ )
for ( int c=0; c<4; c++ )
ModelView(r,c) = Rt.at<double>( c, r );
之前,使用矩阵的反交换我的飞机回到我的坐标空间(Y向上)。
// swap y & z planes so y is up
ofMatrix4x4 gCalibrationToWorld = gWorldToCalibration.getInverse();
ModelView *= gCalibrationToWorld;
不知道如果我需要做到这一点...我没有否定了飞机,当我把它们放进校准...
// invert y and z planes for -/+ differences between opencv and opengl
ofMatrix4x4 InvertHandednessMatrix(
1, 0, 0, 0,
0, -1, 0, 0,
0, 0, -1, 0,
0, 0, 0, 1
);
ModelView *= InvertHandednessMatrix;
最后,模型视图是相对与相机对象,我想颠倒它是相机相对到物体(0,0,0)
ModelView = ModelView.getInverse();
这导致在错误的地方摄像头,并旋转错误。 这不是太离谱,相机是Y平面的右侧,翻译不是大错特错了,我认为这完全取决于正确的方式....只是不正确呢。 油漆绘制蓝色圆圈是我期待的相机可以。
我已经经历了这么回答,该文档了十几次的负荷了,但并不完全找到什么合适的,我敢肯定,我已经谈过了,我需要空间的转换,明智的,但也许我错过了一些明显? 或做错误的顺序的东西吗?
更新1 -世界空天飞机......我改变了我的世界空间地板平面XY(Z高达)来匹配OpenCV的输入。 (gWorldToCalibration现在是单位矩阵)。 旋转仍然是错的,和投影输出是一样的,但我认为现在的翻译是正确的(这当然是上的标记正确的一面)
UPDATE2 -真正的图像大小 ,我与图像尺寸进入摄像机标定打; 看到,因为我使用的是1,1这是标准化的,但IMAGESIZE参数是整数,我想这可能是显著......我猜它(红色框是投影视图空间点带z相交= 0地板面)没有任何失真校正,这里是结果(唯一改变的是IMAGESIZE从1.1至640,480。我通过640,480加倍重视自己的标准化输入视空间COORDS太) 我要去尝试,并添加失真校正,看它是否排队完美 ...