Soy*_*ham 6 opengl opencv camera-calibration extrinsic-parameters
我正在使用opencv和openframeworks(即opengl)来计算图像中的相机(世界变换和投影矩阵)(以及后来的几个图像用于三角测量).
出于opencv的目的,"平面图"成为世界中心0,0,0的对象(即棋盘).世界/楼层位置是已知的,因此我需要获得投影信息(失真系数,fov等)和相机的外部坐标.

我已经将这些平面图的视图位置映射到标准化视图空间中的2D图像上([0,0]是左上角.[1,1]是右下角).
对象(平面图/世界点)在xz平面上,-y向上,所以我转换为xy平面(这里不确定z-up是负的还是正的......)对于opencv,因为它需要是平面的
ofMatrix4x4 gWorldToCalibration(
1, 0, 0, 0,
0, 0, 1, 0,
0, 1, 0, 0,
0, 0, 0, 1
);
Run Code Online (Sandbox Code Playgroud)
我将1,1作为ImageSize传递给校准相机.标志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;
Run Code Online (Sandbox Code Playgroud)
现在我有一个旋转和变换矩阵,但它是专栏(我相信如果我不进行转置,对象完全倾斜,上面的代码看起来对我来说很重要)
// 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 );
Run Code Online (Sandbox Code Playgroud)
使用之前矩阵的逆矩阵将我的飞机交换回我的坐标空间(y up).
// swap y & z planes so y is up
ofMatrix4x4 gCalibrationToWorld = gWorldToCalibration.getInverse();
ModelView *= gCalibrationToWorld;
Run Code Online (Sandbox Code Playgroud)
不确定我是否需要这样做...当我把它们放入校准时我没有否定飞机......
// 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;
Run Code Online (Sandbox Code Playgroud)
最后,模型视图是对象相对于相机,我想将其反转为相机相对于对象(0,0,0)
ModelView = ModelView.getInverse();
Run Code Online (Sandbox Code Playgroud)

这导致相机处于错误的位置,并且旋转错误.这不是太离谱,相机是Y平面的右侧,翻译不是大错特错了,我认为这完全取决于正确的方式....只是不正确呢.绘制的蓝色圆圈是我期待相机的所在.
我已经经历了大量的SO答案,文档已经十几次了,但是找不到任何正确的东西,我很确定我已经涵盖了我需要的所有空间转换方式,但也许我错过了一些明显的东西?或者以错误的顺序做某事?
更新1 - 世界空间飞机......
我已将世界空间楼层平面更改为XY(Z向上)以匹配openCV的输入.(gWorldToCalibration现在是一个单位矩阵).旋转仍然是错误的,投影输出是相同的,但我认为现在的翻译是正确的(它肯定在标记的正确一侧)

Update2 - 实际图像尺寸
我正在使用进入相机校准的图像尺寸; 因为我正在使用1,1这是规范化的,但是imageSize参数是整数,我认为这可能是重要的......我猜它是(红色框是投影的视图空间点与z相交的地方) = 0楼层平面)没有任何失真校正,这里是结果(唯一改变的是从1,1到640,480的图像大小.我也将我的标准化输入 - 视图 - 空间坐标也乘以640,480)
我将尝试添加失真校正,以确定它是否完美排列......
| 归档时间: |
|
| 查看次数: |
5371 次 |
| 最近记录: |