Multiview-3D-Reconstruction
基于SIFT特征匹配与Bundle Adjustment的传统SfM方法,从多张RGB图像增量式重建
加载项目详情…
本应用为开源项目,仅供学习研究,请遵守其开源协议。
基于SIFT特征匹配与Bundle Adjustment的传统SfM方法,从多张RGB图像增量式重建
加载项目详情…
本应用为开源项目,仅供学习研究,请遵守其开源协议。
想象你用手机从不同角度拍摄一尊雕塑——正面的鼻梁、侧面的轮廓、背面的褶皱。当你闭上眼睛,脑海中会自动"脑补"出立体的形状。如今,一个名为 Multiview-3D-Reconstruction 的开源项目,正在用代码复现这个人眼天然具备的能力:仅凭多张二维图像,重建出三维点云模型。
这不是科幻,而是计算机视觉领域经典的 Structure from Motion(从运动中恢复结构,简称SfM) 算法。项目作者 Yashas120 基于传统图像处理技术,完整实现了一套增量式SfM pipeline,在学术界数据集上验证了方法的有效性,并附带了一篇详细的论文说明原理。

图1:Door 场景的3D点云重建效果,彩色点代表从不同视角三角化得出的三维坐标点。
近年来,深度学习方法在单目深度估计(Monocular Depth Estimation)领域突飞猛进,NeRF、Gaussian Splatting 等神经渲染技术也备受关注。但在 无纹理/弱纹理场景、缺乏大规模训练数据 的情况下,传统SfM凭借其坚实的几何理论基础,依然是可靠的baseline方案。
SfM的核心思想是:通过不同视角拍摄的图像,找出同名特征点,利用对极几何约束恢复相机位姿,再通过三角测量恢复三维结构。优势在于:
Multiview-3D-Reconstruction 项目正是这一技术路线的教学级实现,代码结构清晰,适合作为学习SfM的入门教材。
代码中使用了 SIFT(尺度不变特征变换) 算法检测图像特征点。SIFT在尺度空间中寻找极值点,生成128维描述子,对旋转和尺度变化具有很强的鲁棒性。
sift = cv2.xfeatures2d.SIFT_create()
key_points_0, desc_0 = sift.detectAndCompute(
cv2.cvtColor(image_0, cv2.COLOR_BGR2GRAY), None)
通过 KNN(K近邻)匹配 + Lowe's ratio test(距离比小于0.70)过滤误匹配,是该流程的标准做法。
拿到匹配点对后,利用 RANSAC(随机抽样一致性) 求解本质矩阵(Essential Matrix),进而分解出两视图间的旋转矩阵和平移向量。
essential_matrix, em_mask = cv2.findEssentialMat(
feature_0, feature_1, self.img_obj.K,
method=cv2.RANSAC, prob=0.999, threshold=0.4)
_, rot_matrix, tran_matrix, em_mask = cv2.recoverPose(
essential_matrix, feature_0, feature_1, self.img_obj.K)
recoverPose 函数根据本质矩阵恢复了相机的相对运动,这是增量SfM的第一步。
对于后续新加入的视角,代码使用 PnP(Perspective-n-Point) 算法,通过已知的3D-2D对应关系求解相机位姿:
_, rot_vector_calc, tran_vector, inlier = cv2.solvePnPRansac(
obj_point, image_point, K, dist_coeff, cv2.SOLVEPNP_ITERATIVE)
三角测量(Triangulation)则将两视图的射线交点计算出来,形成新的3D点:
pt_cloud = cv2.triangulatePoints(P1, P2, proj1, proj2)
Bundle Adjustment 是SfM中最精华、也最耗时的步骤。它将所有相机位姿和三维点联合优化,最小化重投影误差:
values_corrected = least_squares(
self.optimal_reprojection_error, opt_variables, gtol=r_error).x
scipy.optimize.leasts_squares 实现非线性最小二乘优化,代码中展示了如何将相机内参、外参和三维点坐标打包成优化变量。

图2:Bundle Adjustment 开启与关闭的对比效果图。上半部分为未做BA的结果,下半部分为BA优化后的结果,可见误差明显收敛。
项目仅有一个主文件 sfm.py(约450行),但结构组织得相当合理:
| 类 | 职责 |
|---|---|
Image_loader | 加载图像和相机内参矩阵K,支持图像降采样 |
Sfm | 核心SfM pipeline:特征检测、位姿恢复、三角测量、BA、点云导出 |
代码导出的 .ply 文件可直接用 MeshLab、CloudCompare 等工具打开查看,支持从 .csv 导出相机位姿用于后续分析。
依赖栈:OpenCV(图像处理)、NumPy(矩阵运算)、SciPy(优化)、tqdm(进度条)、Matplotlib(可视化)。
# 安装依赖
pip install opencv-python opencv-contrib-python numpy scipy tqdm matplotlib tomlkit
# 指定数据集路径运行
python sfm.py
数据集目录必须包含 K.txt(相机内参矩阵)和一组同尺寸的 JPG/PNG 图像。项目内置了 5 个标准测试集(GustavIIAdolf、Herz-Jesus-P8、castle、entry、fountain),均来自学术界公开的SfM评测数据集。
\\ 反斜杠路径分隔符,在Linux/Mac上运行需修改。尽管如此,这个项目在以下场景依然有价值:
142颗GitHub stars 虽不算高,但该项目在SfM教学开源领域有一定辨识度。
从两张图像的匹配,到Bundle Adjustment的全局优化,Multiview-3D-Reconstruction 展示了传统3D重建pipeline的核心流程。对于想入门SfM、理解多视图几何原理的开发者来说,这是一个值得细读的"活教材"——代码量不大,但每一步都踩在经典算法的脚印上。唯一的遗憾是没有容器化封装,且路径兼容性限制了它的开箱即用体验,但作为学习素材,它已经足够真诚了。