我正在尝试从平面标记的多个图像执行 3D 重建(运动结构)。我对 MVG 和 openCV 很陌生。
据我了解,我必须执行以下步骤:
- 识别一个图像中相应的 2D 角点。
- 使用 cv::solvePNP 计算第一张图像的相机姿势(假设原点是标记的中心)。
- 对第二张图像重复 1 和 2。
- 通过 Rot_relative = R2 - R1, Trans_relative = T2-T1 估计相机的相对运动。
- 现在假设第一个摄像机是原点,为两个视图构建 3x4 投影矩阵,P1 =[I|0]*CameraMatrix(由校准已知)和 P2 = [Rot_relative |Trans_relative]。
- 使用创建的投影矩阵和 2D 角点使用 cv::triangulatePoints(P1,P2,point1,point2,OutMat) 对 3D 坐标进行三角测量
- 可以通过将 OutMat 的每一行除以第 4 行来找到 3D 坐标。
- 我希望将我的“第一个视图”作为我的起源并遍历 n 个视图,重复从 1 到 7 的步骤(我想它称为 Global SFM)。
我希望通过“第一个视图作为原点”获得拐角的 (n-1)3D 点,我们可以使用 Bundle Adjustment 对其进行优化。
但是我得到的结果非常令人失望,计算出的 3D 点被一个巨大的因素所取代。
这些是问题:
1.我执行的步骤有问题吗?
2.我应该使用 cv::findHomography() 和 cv::decomposeHomographyMat() 来查找相机的相对运动吗?
3. cv::triangulatePoints(P1,P2,point1,point2,OutMat) 中的point1和point2是否应该归一化且不失真?如果是,应该如何解释“Outmat”?
请任何对该主题有见解的人,您能指出我的错误吗?
PS我在阅读“计算机视觉中的多视图几何”后得到了以上理解
请在下面找到代码片段:
cv::Mat Reconstruction::Triangulate(std::vector<cv::Point2f>
ImagePointsFirstView, std::vector<cv::Point2f>ImagePointsSecondView)
{
cv::Mat rVectFirstView, tVecFristView;
cv::Mat rVectSecondView, tVecSecondView;
cv::Mat RotMatFirstView = cv::Mat(3, 3, CV_64F);
cv::Mat RotMatSecondView = cv::Mat(3, 3, CV_64F);
cv::solvePnP(RealWorldPoints, ImagePointsFirstView, cameraMatrix, distortionMatrix, rVectFirstView, tVecFristView);
cv::solvePnP(RealWorldPoints, ImagePointsSecondView, cameraMatrix, distortionMatrix, rVectSecondView, tVecSecondView);
cv::Rodrigues(rVectFirstView, RotMatFirstView);
cv::Rodrigues(rVectSecondView, RotMatSecondView);
cv::Mat RelativeRot = RotMatFirstView-RotMatSecondView ;
cv::Mat RelativeTrans = tVecFristView-tVecSecondView ;
cv::Mat RelativePose;
cv::hconcat(RelativeRot, RelativeTrans, RelativePose);
cv::Mat ProjectionMatrix_0 = cameraMatrix*cv::Mat::eye(3, 4, CV_64F);
cv::Mat ProjectionMatrix_1 = cameraMatrix* RelativePose;
cv::Mat X;
cv::undistortPoints(ImagePointsFirstView, ImagePointsFirstView, cameraMatrix, distortionMatrix, cameraMatrix);
cv::undistortPoints(ImagePointsSecondView, ImagePointsSecondView, cameraMatrix, distortionMatrix, cameraMatrix);
cv::triangulatePoints(ProjectionMatrix_0, ProjectionMatrix_1, ImagePointsFirstView, ImagePointsSecondView, X);
X.row(0) = X.row(0) / X.row(3);
X.row(1) = X.row(1) / X.row(3);
X.row(2) = X.row(2) / X.row(3);
return X;
}