我努力让OpenCV triangulatePoints
功能发挥作用。我正在使用光流生成的点匹配功能。我使用单个移动摄像头的两个连续帧/位置。
目前这些是我的步骤:
给出内在函数,看起来像人们期望的那样:
2.6551e+003 0. 1.0379e+003
0. 2.6608e+003 5.5033e+002
0. 0. 1.
然后,我根据(高度准确的)GPS和相机相对于GPS的位置计算两个外在矩阵([R | t])。请注意,GPS数据使用荷兰周围的笛卡尔坐标系,该坐标系使用米作为单位(因此不需要奇怪的lat / lng数学运算)。这产生以下矩阵:
接下来,我只是删除这些矩阵的底行并将它们与内在矩阵相乘以得到投影矩阵:
projectionMat = intrinsics * extrinsics;
这导致:
我的图像点只包含第一组的所有像素坐标
(0, 0)...(1080, 1920)
和所有像素坐标+他们计算的第二组光学流量。
(0 + flowY0, 0 + flowX0)...(1080 + flowYN, 1920 + flowXN)
为了计算3D点,我将图像点(以OpenCV期望的格式)和投影矩阵提供给triangulatePoints
函数:
cv::triangulatePoints(projectionMat1, projectionMat2, imagePoints1, imagePoints2, outputPoints);
最后,我将outputPoints
从齐次坐标转换为除以第四个坐标(w)并删除此坐标。
我最终得到的是一些奇怪的锥形点云:
现在我已经尝试了我能想到的每一个调整组合(反转矩阵,改变X / Y / Z顺序,反转X / Y / Z轴,改变乘法顺序......),但是一切都有类似的结果奇怪的结果。 做的给我带来更好结果的一件事就是将光流值乘以0.01。这导致以下点云:
这仍然不完美(远离相机的区域看起来非常弯曲),但更像是我期望的。
我想知道是否有人能发现我做错的事情。我的矩阵看起来不错吗?我的输出是否与某个问题有关?
我非常肯定的是,它与GPS或光流无关,因为我测试了多个帧并且它们都产生相同类型的输出。我认为这与三角测量本身有关。
答案 0 :(得分:1)
triangulatePoints()适用于立体相机,不适用于单目相机!
在opencv文档中,我阅读了以下快报:
该函数通过使用
获得投影矩阵stereo camera
的观察来重建三维点(在齐次坐标中)。可以从stereoRectify()
答案 1 :(得分:0)
在我的情况下,为了计算投影矩阵,我必须修复旋转矩阵中使用的约定,请确保对两个摄像机都使用此约定:
rotationMatrix0 = rotation_by_Y_Matrix_Camera_Calibration(camera_roll)*rotation_by_X_Matrix_Camera_Calibration(camera_pitch) *rotation_by_Z_Matrix_Camera_Calibration(camera_yaw);
Mat3x3 Algebra::rotation_by_Y_Matrix_Camera_Calibration(double yaw)
{
Mat3x3 matrix;
matrix[2][2] = 1.0f;
double sinA = sin(yaw), cosA = cos(yaw);
matrix[0][0] = +cosA; matrix[0][1] = -sinA;
matrix[1][0] = +sinA; matrix[1][1] = +cosA;
return matrix;
}
Mat3x3 Algebra::rotation_by_X_Matrix_Camera_Calibration(double pitch)
{
Mat3x3 matrix;
matrix[1][1] = 1.0f;
double sinA = sin(pitch), cosA = cos(pitch);
matrix[0][0] = +cosA; matrix[0][2] = +sinA;
matrix[2][0] = -sinA; matrix[2][2] = +cosA;
return matrix;
}
Mat3x3 Algebra::rotation_by_Z_Matrix_Camera_Calibration(double roll)
{
Mat3x3 matrix;
matrix[0][0] = 1.0f;
double sinA = sin(roll), cosA = cos(roll);
matrix[1][1] = +cosA; matrix[1][2] = -sinA;
matrix[2][1] = +sinA; matrix[2][2] = +cosA;
return matrix;
}