如果相机平移也在 Z 方向上,单应性是否在平面场景的两个图像之间保持不变?
Does homography hold between two images for a planar scene if camera translation is also in the Z direction?
我正在尝试计算两个图像之间的相对姿势:我正在使用单应性来过滤特征匹配。我有一个相当平面的场景,只要两个图像之间的平移仅限于 X 轴和 Y 轴(opencv 约定),基于单应性的相对姿态估计就可以非常准确地工作。
一旦我开始使用另一个相机在 Z 方向上移动(第一个相机保持不变),相对姿势估计就无法正常工作,它会一直估计 Z 平移非常低的姿势。尽管场景是平面的,但当沿 Z 方向平移时单应性不适用吗?
在这里附上一张照片:我将第二个相机移动到两个方格中:一个在 XY 平面上,一个在 XZ 平面上。红色十字是相机平移的实际姿势(将其视为基本事实),蓝色圆圈是通过基于单应性的 RANSAC 估计的相对姿势。请注意在 X 和 Y 方向移动时的准确性,并在 Z 方向完全失败:所有估计都接近 z=0 平面。
我将同形矩阵分解为旋转和平移的代码取自this StackExchange answer
void cameraPoseFromHomography(const Mat& H, Mat& pose)
{
pose = Mat::eye(3, 4, CV_64FC1); //3x4 matrix
float norm1 = (float)norm(H.col(0));
float norm2 = (float)norm(H.col(1));
float tnorm = (norm1 + norm2) / 2.0f;
Mat v1 = H.col(0);
Mat v2 = pose.col(0);
cv::normalize(v1, v2); // Normalize the rotation
v1 = H.col(1);
v2 = pose.col(1);
cv::normalize(v1, v2);
v1 = pose.col(0);
v2 = pose.col(1);
Mat v3 = v1.cross(v2); //Computes the cross-product of v1 and v2
Mat c2 = pose.col(2);
v3.copyTo(c2);
pose.col(3) = H.col(2) / tnorm; //vector t [R|t]
}
这是准确的吗?单应矩阵的第三列是否编码完整的 3D 平移?
虽然场景是平面的,但在 Z 方向平移时单应性不适用吗?
如果您有一个平面场景,那么 所有 图像使用
透视相机(没有镜头失真)将与
同形异义词。这与相机是否旋转或
翻译。
如果有明显的镜头畸变那么图像就不会
由同形异义相关。
如果场景是非平面的,那么图像将通过
只有在没有镜头畸变和没有相机平移(只是旋转)的情况下,才有单应性。
相对位姿估计不正常,它一直在估计Z平移很低的位姿
使用单应分解计算的 3D 平移符合比例。这意味着返回的两个相机之间的平移矢量 t 与真实平移相差一个比例因子 s。不幸的是 s 无法恢复。由于这个原因,通常单眼图像的 3D 重建被称为 metric 重建(而不是解析真实比例的 Euclidean 重建)。要解决 s 需要更多信息,例如了解平面上某个点的深度或相机在图像之间移动的距离。
问题确实出在我分解单应矩阵的方式上:我在问题中发布的方法似乎不正确。单应矩阵的最后一列不编码完整的 3D 翻译。正确的分解方式作为 OpenCV 函数 (decomposeHomographyMat) 提供,其中矩阵被分解为 4 种可能的全 3D 平移和旋转解。
https://github.com/opencv/opencv/blob/master/modules/calib3d/src/homography_decomp.cpp#L435
该函数中使用的方法在 this paper 中有说明。
我正在尝试计算两个图像之间的相对姿势:我正在使用单应性来过滤特征匹配。我有一个相当平面的场景,只要两个图像之间的平移仅限于 X 轴和 Y 轴(opencv 约定),基于单应性的相对姿态估计就可以非常准确地工作。
一旦我开始使用另一个相机在 Z 方向上移动(第一个相机保持不变),相对姿势估计就无法正常工作,它会一直估计 Z 平移非常低的姿势。尽管场景是平面的,但当沿 Z 方向平移时单应性不适用吗?
在这里附上一张照片:我将第二个相机移动到两个方格中:一个在 XY 平面上,一个在 XZ 平面上。红色十字是相机平移的实际姿势(将其视为基本事实),蓝色圆圈是通过基于单应性的 RANSAC 估计的相对姿势。请注意在 X 和 Y 方向移动时的准确性,并在 Z 方向完全失败:所有估计都接近 z=0 平面。
我将同形矩阵分解为旋转和平移的代码取自this StackExchange answer
void cameraPoseFromHomography(const Mat& H, Mat& pose)
{
pose = Mat::eye(3, 4, CV_64FC1); //3x4 matrix
float norm1 = (float)norm(H.col(0));
float norm2 = (float)norm(H.col(1));
float tnorm = (norm1 + norm2) / 2.0f;
Mat v1 = H.col(0);
Mat v2 = pose.col(0);
cv::normalize(v1, v2); // Normalize the rotation
v1 = H.col(1);
v2 = pose.col(1);
cv::normalize(v1, v2);
v1 = pose.col(0);
v2 = pose.col(1);
Mat v3 = v1.cross(v2); //Computes the cross-product of v1 and v2
Mat c2 = pose.col(2);
v3.copyTo(c2);
pose.col(3) = H.col(2) / tnorm; //vector t [R|t]
}
这是准确的吗?单应矩阵的第三列是否编码完整的 3D 平移?
虽然场景是平面的,但在 Z 方向平移时单应性不适用吗?
如果您有一个平面场景,那么 所有 图像使用 透视相机(没有镜头失真)将与 同形异义词。这与相机是否旋转或 翻译。
如果有明显的镜头畸变那么图像就不会 由同形异义相关。
如果场景是非平面的,那么图像将通过 只有在没有镜头畸变和没有相机平移(只是旋转)的情况下,才有单应性。
相对位姿估计不正常,它一直在估计Z平移很低的位姿
使用单应分解计算的 3D 平移符合比例。这意味着返回的两个相机之间的平移矢量 t 与真实平移相差一个比例因子 s。不幸的是 s 无法恢复。由于这个原因,通常单眼图像的 3D 重建被称为 metric 重建(而不是解析真实比例的 Euclidean 重建)。要解决 s 需要更多信息,例如了解平面上某个点的深度或相机在图像之间移动的距离。
问题确实出在我分解单应矩阵的方式上:我在问题中发布的方法似乎不正确。单应矩阵的最后一列不编码完整的 3D 翻译。正确的分解方式作为 OpenCV 函数 (decomposeHomographyMat) 提供,其中矩阵被分解为 4 种可能的全 3D 平移和旋转解。
https://github.com/opencv/opencv/blob/master/modules/calib3d/src/homography_decomp.cpp#L435
该函数中使用的方法在 this paper 中有说明。