介绍基于 C++ 的运动恢复结构(SfM)的三维重建
介绍基于 C++ 的运动恢复结构(SfM)的三维重建
今天主题是运动恢复结构(sfm),让我们通过一系列智能手机拍摄的图像,来探索“运动恢复结构”(Structure from Motion)技术,从而还原一个小场景的三维布局。请选择附近的物体,并拍摄若干张照片,确保相邻照片之间有一定的重叠区域。为了获得更精确的结果,请使用棋盘格对相机进行标定——从不同角度拍摄几张棋盘格图像。这一标定步骤将为整个流程提供关键信息(相机内参)。

引言
运动恢复结构(Structure from Motion,简称 SfM)是一种计算机视觉与摄影测量技术,它能够从一组二维图像中重建场景的三维结构,并同时确定各图像对应的相机位姿。通过识别图像间的共同特征并求解相应的数学方程,SfM 将多张图像转化为一个连贯的三维表示,广泛应用于三维建模、增强现实以及历史景观重建等领域。
基于深度学习的图像匹配与三维重建算法MASt3R和MASt3R-SfM详解
特征提取
特征提取是指从图像中识别并提取具有显著性和可重复性的模式或关键点。这些特征点可在多张图像之间进行匹配,从而建立图像间的对应关系,为后续的三维结构重建奠定基础。

SIFT(尺度不变特征变换):
SIFT 是由 David Lowe 提出的一种强大的特征提取算法。它对尺度变化、旋转以及光照变化具有很强的鲁棒性,因此非常适合各类计算机视觉任务。
void extractFeatures()
特征匹配
在运动恢复结构(Structure from Motion, SfM)中,从多张图像中提取出特征后,下一步是将这些特征在不同图像之间进行匹配。该过程旨在建立不同视角下特征点之间的对应关系,从而为重建场景的三维结构奠定基础。

在对齐不同图像并建立其特征点对应关系的过程中,我们采用了 OpenCV 的 cv::FlannBasedMatcher 接口。该接口基于“多维空间中的聚类与搜索”模块,提供了一种快速而高效的特征匹配机制。
为了增强匹配结果的鲁棒性,我们引入了距离比值检验(distance ratio test)。该检验方法会计算某个关键点与其两个最近邻匹配点之间的距离比值。只有当该比值低于某一设定阈值时,该匹配才被视为可靠。这种巧妙的策略有助于区分模糊不清的匹配(此时比值接近 1)和具有明显区分度的优质匹配。
此外,我们在匹配过程中加入了一个关键条件:如果两幅图像之间内点(inlier)匹配的数量不足(例如小于或等于 10 对),则不建立这两幅图像之间的匹配关系。这一实用性的检查可有效避免引入不可靠的匹配,从而提升后续三维重建的整体精度。
void exhaustiveMatching()三角测量:揭示三维奥秘
在深入探索运动恢复结构(Structure from Motion, SfM)的过程中,让我们聚焦于三角测量(Triangulation)——这是还原场景三维几何形状的核心环节。这一过程依赖于本质矩阵(Essential Matrix, E)与单应矩阵(Homography Matrix, H),二者在重建流程中各司其职。
本质矩阵与三维点定位
当场景包含丰富多样的非平面结构时,本质矩阵便成为关键。它隐含了相机之间相对位姿的几何信息,为三维点的恢复奠定基础。通过 OpenCV 的 cv::findEssentialMat() 函数,我们利用匹配的特征点推算出本质矩阵,从而“激活”三维点的重建:
cv::Mat E = cv::findEssentialMat(points0, points1, intrinsics_matrix, cv::RANSAC, 0.99, 1, inlier_mask_E);单应矩阵:揭示平面上的三维秘密
然而,若场景主要由平面结构组成,则单应矩阵将占据主导地位。借助cv::findHomography() 函数,我们可以高效地识别这些平面上的三维点:
cv::Mat H = cv::findHomography(points0, points1, inlier_mask_H, cv::RANSAC);随后,系统会比较两种模型所获得的内点数量:
int e = cv::sum(inlier_mask_E)[0];这些矩阵在后台默默参与决策过程。输出的掩码(mask)是一组数值序列,精确标识哪些点是重要的(标记为 1),哪些点可被忽略(标记为 0)。正是在这种“关键点”与“非关键点”的权衡之中,系统做出一个至关重要的判断。
我们通过比较关键点的数量来评估本质矩阵(E)相较于单应矩阵(H)的受欢迎程度。如果本质矩阵(E)拥有更多的支持者(即更多关键点),我们就使用它来为我们的三维世界注入活力,并点亮“种子已找到”标志。
简而言之,我们在运动恢复结构(Structure from Motion, SfM)中的旅程就像一场引人入胜的表演。我们精心挑选合适的工具(矩阵),如同施展魔法咒语一般,根据场景量身定制,确保我们的三维世界能够和谐地呈现出来。
揭示和谐:三维重建中的束调整与Ceres Solver
在探索运动恢复结构(SfM)的过程中,我们已经探讨了特征提取、匹配以及迷人的矩阵世界。现在,让我们聚焦于这一对动态组合:束调整(Bundle Adjustment)和Ceres Solver。
束调整:精度精炼
想象一下为一个三维场景拍摄一系列照片时,微小的误差,比如轻微的不对齐,可能会悄悄潜入。束调整则登场解决这些问题,它优化相机姿态和三维结构,以确保重建更加准确。
void bundleAdjustmentIter(int new_cam_idx)Ceres Solver:优化中的精确指南
作为我们的数值优化指南,Ceres Solver与束调整无缝协作。它确保参数得到精确调整,为准确的三维重建铺平道路。
ceres::Solver::Summary summary;残差块与自动可微代价函数:精准的核心
现在,让我们揭开背后的秘密。残差块和自动可微代价函数是无名英雄。残差块是对观察值与预测值之间差异的数学表示,简单来说,它帮助量化需要修正的“误差”。
struct ReprojectionError简言之,由自动可微代价函数驱动的残差块量化了优化过程中所需的修正。它们将复杂的误差舞蹈转化为Ceres Solver优雅执行的数字步骤。
下次当你见证令人惊叹的三维重建时,请记住这些幕后大师:束调整、Ceres Solver、残差块和自动可微代价函数。它们是精度建筑师,使运动恢复结构成为视觉奇迹。
结果会在点云快照中直观展现。使用MeshLab渲染和探索生成的.ply文件,可以获得全面的可视化体验。按回车键或点击以查看完整尺寸的图像。

就是这样!我们已经完成了这次使用 C++ 实现运动恢复结构(Structure from Motion)进行三维重建的精彩探索之旅。希望你在特征提取、特征匹配以及矩阵之间精妙协作的过程中收获了乐趣与启发。
如果你觉得本文既富有信息量又引人入胜,请持续关注我,未来我将带来更多关于计算机视觉与摄影测量领域的深度解析。我会继续拆解复杂概念,将其转化为易于理解的洞见。
若想深入了解并获取完整代码,请联系我。深入探索那些让三维重建既精准又视觉震撼的核心机制吧!
下次再见啦,感谢你与我一同踏上这段三维冒险之旅!保持探索,持续学习,永远精彩!