simplerecon
SimpleRecon 是一款专注于多视图立体深度估计的开源算法,旨在通过输入的带姿态 RGB 图像序列,高效生成目标图像的高精度深度图。它主要解决了传统 3D 重建方法中依赖计算密集型的 3D 卷积操作这一痛点,从而在保持甚至提升重建质量的同时,显著降低了硬件资源消耗并提升了运行速度。
该工具的核心技术亮点在于其独特的架构设计:完全摒弃了昂贵的 3D 卷积层,转而利用高效的 2D 卷积网络配合精心设计的代价体构建策略来完成三维信息推理。这种“去 3D 卷积”的思路不仅简化了模型结构,还使其在扫描网(ScanNet)等标准数据集上取得了极具竞争力的评估分数,包括更低的绝对误差和更高的 F-Score。
SimpleRecon 非常适合计算机视觉领域的研究人员、算法工程师以及需要部署轻量化 3D 重建方案的开发者使用。对于希望深入理解现代多视图几何深度学习,或需要在有限算力环境下实现高质量点云融合与网格重建的专业人士来说,这是一个极具参考价值的基准实现。项目提供了完整的训练、测试及预训练模型支持,便于用户快速复现论文结果或进行二次开发。
使用场景
某自动驾驶初创团队正在构建城市街道的高精度 3D 地图,需要利用车载摄像头采集的视频流快速重建道路环境的深度信息。
没有 simplerecon 时
- 硬件成本高昂:传统 3D 重建方法依赖昂贵的激光雷达(LiDAR)或专用深度传感器,导致车辆改装成本居高不下。
- 计算资源消耗大:现有基于 3D 卷积的算法对显存和算力要求极高,难以在边缘设备或普通工作站上实时运行。
- 重建精度受限:在纹理缺失区域(如白墙、路面)或光照剧烈变化时,生成的深度图噪点多,细节模糊,影响后续路径规划。
- 部署流程复杂:模型训练和推理环境配置繁琐,不同版本的依赖库冲突频繁,严重拖慢研发迭代速度。
使用 simplerecon 后
- 纯视觉低成本方案:simplerecon 仅需普通的 RGB 摄像头图像即可输出高质量深度图,彻底摆脱了对激光雷达的依赖,大幅降低硬件门槛。
- 高效轻量级推理:通过摒弃耗时的 3D 卷积操作,该工具显著减少了显存占用,使得在消费级 GPU 上也能流畅进行高分辨率深度估计。
- 细节还原更精准:得益于先进的多视图立体几何(MVS)策略,simplerecon 在弱纹理区域仍能保持边缘锐利,生成的点云密度和准确度显著提升。
- 开箱即用的体验:提供预训练模型和标准化的环境配置文件,开发人员可快速复现论文效果,将精力集中于业务逻辑而非环境调试。
simplerecon 通过“去 3D 卷积”的创新架构,让高精度 3D 重建从昂贵的实验室技术变成了可大规模落地的普惠型视觉方案。
运行环境要求
- Linux
需要 NVIDIA GPU,显存至少 2.6GB(标准模式)或 5.7GB(速度优化模式),CUDA 11.3
未说明

快速开始
SimpleRecon:无需3D卷积的3D重建
这是使用以下论文中描述的方法训练和测试MVS深度估计模型的参考PyTorch实现:
SimpleRecon:无需3D卷积的3D重建
Mohamed Sayed、John Gibson、Jamie Watson、Victor Adrian Prisacariu、Michael Firman 和 Clément Godard
https://github.com/nianticlabs/simplerecon/assets/14994206/ae5074c2-6537-45f1-9f5e-0b3646a96dcb
此代码仅供非商业用途;详细条款请参阅许可证文件。如果您发现本代码库中的任何部分对您有所帮助,请使用下面的BibTex引用我们的论文,并链接到此仓库。谢谢!
🆕 更新
2023年5月25日:修复了llvm-openmp、clang和protobuf的软件包版本。如果您在运行代码时遇到困难,或者数据加载被限制为单线程,请使用这个新的环境文件。
2023年3月9日:在环境文件中添加了kornia版本,以修复kornia的类型问题。(感谢@natesimon!)
2023年1月26日:许可证已修改,以便更方便地出于学术目的运行模型。具体细节请参阅LICENSE文件。
2022年12月31日发布了一个更新,修复了略微错误的内参、代价体积的翻转增强以及投影中的数值精度 bug。所有指标均有所提升。您需要更新您的分支并使用新的权重。详情请参阅Bug Fixes。
用于在线默认帧的预计算扫描在此处:https://drive.google.com/drive/folders/1dSOFI9GayYHQjsx4I_NG0-3ebCAfWXjV?usp=share_link
目录
- 🗺️ 概述
- ⚙️ 设置
- 📦 模型
- 🚀 速度
- 📝 待办事项:
- 🏃 开箱即用!
- 💾 ScanNetv2 数据集
- 🖼️🖼️🖼️ 帧组
- 📊 测试与评估
- 👉☁️ 点云融合
- 📊 网格指标
- ⏳ 训练
- 🔧 其他训练和测试选项
- ✨ 可视化
- 📝🧮👩💻 变换矩阵表示法
- 🗺️ 世界坐标系
- 🐜🔧 Bug Fixes
- 🗺️💾 COLMAP 数据集
- 🙏 致谢
- 📜 BibTeX
- 👩⚖️ 许可证
🗺️ 概述
SimpleRecon以带有位姿信息的RGB图像作为输入,输出目标图像的深度图。
⚙️ 设置
假设您已经安装了全新的Anaconda发行版,您可以使用以下命令安装依赖项:
conda env create -f simplerecon_env.yml
我们使用PyTorch 1.10、CUDA 11.3、Python 3.9.7和Debian GNU/Linux 10进行了实验。
📦 模型
将预训练模型下载到weights/文件夹中。
我们提供了以下模型(分数基于在线默认关键帧):
--config |
模型 | 绝对误差↓ | 均方相对误差↓ | delta < 1.05↑ | Chamfer↓ | F-Score↑ |
|---|---|---|---|---|---|---|
hero_model.yaml |
元数据 + Resnet匹配 | 0.0868 | 0.0127 | 74.26 | 5.69 | 0.680 |
dot_product_model.yaml |
点积 + Resnet匹配 | 0.0910 | 0.0134 | 71.90 | 5.92 | 0.667 |
hero_model是我们论文中使用的模型,标记为Ours。
🚀 速度
--config |
模型 | 推理速度 (--batch_size 1) |
推理GPU内存 | 大致训练时间 |
|---|---|---|---|---|
hero_model |
英雄,元数据 + Resnet | 130ms / 70ms(速度优化) | 2.6GB / 5.7GB(速度优化) | 36小时 |
dot_product_model |
点积 + Resnet | 80ms | 2.6GB | 36小时 |
使用更大的批量时,速度会显著提高。在未优化速度的模型上,当批量大小为8时,延迟降至约40毫秒。
📝 待办事项:
- 提供一个简单的扫描数据,方便大家快速试用代码,而不用下载ScanNetv2的测试场景。已完成
- ScanNetv2数据提取,
预计10月10日已完成 - FPN模型权重。
[ ] 如何使用Scanniverse数据的教程,预计10月5日、10月10日、10月20日目前尚无公开可用的方式从Scanniverse导出扫描数据。您需要使用ios-logger;NeuralRecon有一个很好的教程在这里,并且接受处理后格式的数据加载器位于datasets/arkit_dataset.py。更新:现在有一个简短的说明文档data_scripts/IOS_LOGGER_ARKIT_README.md,介绍如何使用data_scripts/ios_logger_preprocessing.py脚本处理并运行ios-logger扫描的推理。
🏃 开箱即用!
我们现在已经在代码中包含了两个扫描数据集,供大家立即试用。你可以从这里下载这些扫描数据。
步骤:
- 将
hero_model的权重文件下载到 weights 目录中。 - 下载扫描数据并解压到你选择的目录中。
- 修改
configs/data/vdr_dense.yaml文件中dataset_path选项的值,将其设置为解压后的 vdr 文件夹的根路径。 - 现在你应该可以运行了!以下命令应该可以正常工作:
CUDA_VISIBLE_DEVICES=0 python test.py --name HERO_MODEL \
--output_base_path OUTPUT_PATH \
--config_file configs/models/hero_model.yaml \
--load_weights_from_checkpoint weights/hero_model.ckpt \
--data_config configs/data/vdr_dense.yaml \
--num_workers 8 \
--batch_size 2 \
--fast_cost_volume \
--run_fusion \
--depth_fuser open3d \
--fuse_color \
--dump_depth_visualization;
这将会在 OUTPUT_PATH 下生成网格、快速深度可视化以及与 LiDAR 深度对比的评估分数。
该命令使用的是 vdr_dense.yaml 配置文件,它会为每一帧生成深度图,并将它们融合成一个网格。而在论文中,我们报告的是基于关键帧融合的结果,你可以使用 vdr_default.yaml 来运行这些任务。此外,如果你需要处理密集离线帧对,则可以使用 vdr_dense_offline.yaml。
请参阅下方的测试与评估部分,确保为不同的数据集使用正确的配置参数。
💾 ScanNetv2 数据集
请按照 这里 的说明下载数据集。这个数据集非常大(超过 2TB),因此请确保你有足够的存储空间,尤其是在解压文件时。
下载完成后,使用此 脚本 将原始传感器数据导出为图像和深度文件。
我们编写了一个简短的教程,并附上了修改过的脚本,以帮助你下载和提取 ScanNetv2 数据。你可以在 data_scripts/scannet_wrangling_scripts/ 找到这些内容。
你需要将 configs/data/ 中 ScanNetv2 数据配置文件中的 dataset_path 参数修改为你的数据集所在路径。
代码库期望 ScanNetv2 数据具有以下格式:
dataset_path
scans_test (测试扫描)
scene0707
scene0707_00_vh_clean_2.ply (真实世界网格)
sensor_data
frame-000261.pose.txt
frame-000261.color.jpg
frame-000261.color.512.png (可选,分辨率为 512x384 的图像)
frame-000261.color.640.png (可选,分辨率为 640x480 的图像)
frame-000261.depth.png (全分辨率深度图,存储时乘以 1000)
frame-000261.depth.256.png (可选,分辨率为 256x192 的深度图,同样经过缩放)
scene0707.txt (扫描元数据及图像尺寸)
intrinsic
intrinsic_depth.txt
intrinsic_color.txt
...
scans (验证和训练扫描)
scene0000_00
(见上文)
scene0000_01
....
在这个例子中,scene0707.txt 应该包含扫描的元数据:
colorHeight = 968
colorToDepthExtrinsics = 0.999263 -0.010031 0.037048 ........
colorWidth = 1296
depthHeight = 480
depthWidth = 640
fx_color = 1170.187988
fx_depth = 570.924255
fy_color = 1170.187988
fy_depth = 570.924316
mx_color = 647.750000
mx_depth = 319.500000
my_color = 483.750000
my_depth = 239.500000
numColorFrames = 784
numDepthFrames = 784
numIMUmeasurements = 1632
frame-000261.pose.txt 应该包含姿态信息,格式如下:
-0.384739 0.271466 -0.882203 4.98152
0.921157 0.0521417 -0.385682 1.46821
-0.0587002 -0.961035 -0.270124 1.51837
frame-000261.color.512.png 和 frame-000261.color.640.png 是原始图像的预缓存缩放版本,用于在训练和测试过程中节省加载和计算时间。同样地,frame-000261.depth.256.png 也是深度图的预缓存缩放版本。
所有预缓存的缩放版本的深度图和图像都是有益的,但并非必需。如果不存在这些预缓存版本,系统将直接加载全分辨率的版本,并在运行时进行下采样。
🖼️🖼️🖼️ 帧对
默认情况下,我们会为每个扫描中的关键帧估计一张深度图。我们使用 DeepVideoMVS 的启发式方法来分离关键帧,并构建相应的帧对。我们利用这些关键帧上的深度图进行深度融合。对于每个关键帧,我们还会关联一个源帧列表,用于构建代价体积。此外,我们还使用密集帧对,即为数据中的每一帧都预测一张深度图,而不仅仅是特定的关键帧;这些主要用于可视化目的。
我们会在所有扫描中生成并导出一列帧对,作为数据集的基本元素。这些列表已经预先计算好,可在每个数据集的 data_splits 目录下找到。对于 ScanNet 的测试扫描,它们位于 data_splits/ScanNetv2/standard_split。我们的核心深度指标是通过 data_splits/ScanNetv2/standard_split/test_eight_view_deepvmvs.txt 计算得出的。
以下是测试用帧对类型的简要分类:
default:遵循 DeepVideoMVS 规则的每帧关键帧对,所有源帧都在当前帧之前。除非另有说明,否则所有深度和网格评估都使用此类型。对于 ScanNet,请使用data_splits/ScanNetv2/standard_split/test_eight_view_deepvmvs.txt。offline:扫描中每一帧的帧对,其中源帧既可以是当前帧之前的,也可以是之后的。这类帧对在场景是离线拍摄时非常有用,因为可以获得最高的精度。使用在线帧对时,随着相机移动,代价体积中会出现空白区域,因为所有源帧都落后于当前帧;而使用离线帧对时,代价体积的两端都会被填满,从而获得更好的尺度(和度量)估计。dense:类似于 default 类型的在线帧对,但适用于扫描中的每一帧,且所有源帧都在当前帧之前。对于 ScanNet,这对应于data_splits/ScanNetv2/standard_split/test_eight_view_deepvmvs_dense.txt。offline:扫描中每一帧的关键帧离线帧对。
对于训练和验证集,我们采用与 DeepVideoMVS 相同的帧对增强策略,并使用相同的生成脚本。
如果你想自己生成这些帧对,可以使用 data_scripts/generate_train_tuples.py 脚本生成训练帧对,或使用 data_scripts/generate_test_tuples.py 脚本生成测试帧对。这些脚本遵循与 test.py 相同的配置格式,并会使用你构建的任何数据集类来读取姿态信息。
测试示例:
默认元组
python ./data_scripts/generate_test_tuples.py --data_config configs/data/scannet_default_test.yaml --num_workers 16
密集元组
python ./data_scripts/generate_test_tuples.py --data_config configs/data/scannet_dense_test.yaml --num_workers 16
训练示例:
```bash
# 训练
python ./data_scripts/generate_train_tuples.py
--data_config configs/data/scannet_default_train.yaml
--num_workers 16
# 验证
python ./data_scripts/generate_val_tuples.py
--data_config configs/data/scannet_default_val.yaml
--num_workers 16
这些脚本会首先检查数据集中的每一帧,确保其包含有效的RGB图像、深度图像(如果数据集适用),以及有效的位置姿态文件。它会将这些“有效帧”保存到每个扫描文件夹下的文本文件中;但如果目录为只读模式,则会忽略保存“valid_frames”文件,但仍会生成元组。
📊 测试与评估
您可以使用 test.py 进行深度图推理与评估,并进行网格融合。
所有结果将存储在基础结果目录(results_path)下,路径为:
opts.output_base_path/opts.name/opts.dataset/opts.frame_tuple_type/
其中 opts 是 options 类。例如,当 opts.output_base_path 为 ./results,opts.name 为 HERO_MODEL,opts.dataset 为 scannet,opts.frame_tuple_type 为 default 时,输出目录将是:
./results/HERO_MODEL/scannet/default/
请确保将 --opts.output_base_path 设置为您适合存储结果的目录。
--frame_tuple_type 是用于多视图立体视觉(MVS)的图像元组类型,应在您使用的 data_config 文件中指定。
默认情况下,test.py 会尝试计算每帧的深度评分,并提供帧平均和场景平均指标。这些评分(按场景及总计)将被保存在 results_path/scores 目录下。
我们已尽力修复匹配编码器中的批处理错误,通过禁用该编码器的图像批处理,以实现精度达到 (<10^-4) 的准确测试。如有疑问,最多可运行 --batch_size 4;若希望获得尽可能稳定的结果并避免 PyTorch 的潜在问题,请使用 --batch_size 1 进行对比评估。
如果您希望提高速度,可将 --fast_cost_volume 设置为 True。这将启用匹配编码器的批处理,并使用 einops 优化的特征体积。
# 示例命令:仅计算评分
CUDA_VISIBLE_DEVICES=0 python test.py --name HERO_MODEL \
--output_base_path OUTPUT_PATH \
--config_file configs/models/hero_model.yaml \
--load_weights_from_checkpoint weights/hero_model.ckpt \
--data_config configs/data/scannet_default_test.yaml \
--num_workers 8 \
--batch_size 4;
# 如果需要超快速版本:
CUDA_VISIBLE_DEVICES=0 python test.py --name HERO_MODEL \
--output_base_path OUTPUT_PATH \
--config_file configs/models/hero_model.yaml \
--load_weights_from_checkpoint weights/hero_model.ckpt \
--data_config configs/data/scannet_default_test.yaml \
--num_workers 8 \
--fast_cost_volume \
--batch_size 2;
该脚本还可用于执行一些辅助任务,包括:
TSDF 融合
要运行 TSDF 融合,请添加 --run_fusion 标志。您有两种融合器可供选择:
--depth_fuser ours(默认)将使用我们的融合器,其生成的网格常用于大多数可视化和评分。此融合器不支持颜色。我们提供了 scikit-image 的自定义分支,其中包含我们对measure.matching_cubes的自定义实现,支持单壁网格。我们使用单壁网格进行评估。如果您对此不关心,可在调用test.py中的export_mesh函数时将export_single_mesh设置为False。--depth_fuser open3d将使用 Open3D 深度融合器。此融合器支持颜色,可通过使用--fuse_color标志启用。
默认情况下,用于融合的深度图会被裁剪至 3 米,且 TSDF 分辨率为 0.04 m³,但您可以通过修改 --max_fusion_depth 和 --fusion_resolution 来调整这些参数。
您还可以选择在没有有效 MVS 信息时,对用于融合的预测深度进行掩码处理,方法是使用 --mask_pred_depths。此功能默认未启用。
此外,您还可以在引入强图像先验的代价卷积编码解码之前,融合来自代价体积的最佳猜测深度。只需使用 --fusion_use_raw_lowest_cost 即可。
网格将存储在 results_path/meshes/ 目录下。
# 示例命令:融合深度以获取网格
CUDA_VISIBLE_DEVICES=0 python test.py --name HERO_MODEL \
--output_base_path OUTPUT_PATH \
--config_file configs/models/hero_model.yaml \
--load_weights_from_checkpoint weights/hero_model.ckpt \
--data_config configs/data/scannet_default_test.yaml \
--num_workers 8 \
--run_fusion \
--batch_size 8;
缓存深度
您也可以通过提供 --cache_depths 标志来选择性地存储深度图。它们将被保存在 results_path/depths 目录下。
# 示例命令:计算评分并缓存深度
CUDA_VISIBLE_DEVICES=0 python test.py --name HERO_MODEL \
--output_base_path OUTPUT_PATH \
--config_file configs/models/hero_model.yaml \
--load_weights_from_checkpoint weights/hero_model.ckpt \
--data_config configs/data/scannet_default_test.yaml \
--num_workers 8 \
--cache_depths \
--batch_size 8;
# 示例命令:融合深度以获取彩色网格
CUDA_VISIBLE_DEVICES=0 python test.py --name HERO_MODEL \
--output_base_path OUTPUT_PATH \
--config_file configs/models/hero_model.yaml \
--load_weights_from_checkpoint weights/hero_model.ckpt \
--data_config configs/data/scannet_default_test.yaml \
--num_workers 8 \
--run_fusion \
--depth_fuser open3d \
--fuse_color \
--batch_size 4;
快速可视化
虽然有其他脚本可用于更深入的输出深度和融合可视化,但若需快速导出深度图可视化效果,可使用 --dump_depth_visualization。可视化结果将被保存在 results_path/viz/quick_viz/ 目录下。
# 示例命令,用于输出快速深度可视化
CUDA_VISIBLE_DEVICES=0 python test.py --name HERO_MODEL \
--output_base_path OUTPUT_PATH \
--config_file configs/models/hero_model.yaml \
--load_weights_from_checkpoint weights/hero_model.ckpt \
--data_config configs/data/scannet_default_test.yaml \
--num_workers 8 \
--dump_depth_visualization \
--batch_size 4;
👉☁️ 点云融合
我们还允许使用3DVNet仓库中的融合器将深度图与点云进行融合。链接。
# 示例命令,用于将深度信息融合到点云中。
CUDA_VISIBLE_DEVICES=0 python pc_fusion.py --name HERO_MODEL \
--output_base_path OUTPUT_PATH \
--config_file configs/models/hero_model.yaml \
--load_weights_from_checkpoint weights/hero_model.ckpt \
--data_config configs/data/scannet_dense_test.yaml \
--num_workers 8 \
--batch_size 4;
如果您不想等待太久,可以将 configs/data/scannet_dense_test.yaml 改为 configs/data/scannet_default_test.yaml,这样就只使用关键帧了。
📊 网格指标
我们使用TransformerFusion的网格评估代码来生成主要的结果表格,但在随机采样网格时,为了保持一致性,我们将随机种子设置为固定值。此外,在补充材料中,我们还报告了使用NeuralRecon的评估代码得到的网格指标。
对于点云的评估,我们同样使用TransformerFusion的代码,但会加载点云数据,而不是对网格表面进行采样。
⏳ 训练
默认情况下,模型和TensorBoard事件文件会被保存到 ~/tmp/tensorboard/<model_name>。可以通过 --log_dir 参数来更改保存路径。
我们在默认的ScanNetv2划分上,使用两块A100显卡以16的批量大小和16位精度进行训练。
使用两块GPU训练的示例命令如下:
CUDA_VISIBLE_DEVICES=0,1 python train.py --name HERO_MODEL \
--log_dir logs \
--config_file configs/models/hero_model.yaml \
--data_config configs/data/scannet_default_train.yaml \
--gpus 2 \
--batch_size 16;
该代码支持任意数量的GPU进行训练。您可以通过 CUDA_VISIBLE_DEVICES 环境变量指定要使用的GPU。
我们所有的训练都在两块NVIDIA A100显卡上完成。
不同的数据集
您可以通过编写一个新的数据加载器类来训练自定义的MVS数据集,该类需要继承 datasets/generic_mvs_dataset.py 中的 GenericMVSDataset 类。您可以参考 datasets/scannet_dataset.py 中的 ScannetDataset 类,或者 datasets 目录下的其他任何类作为示例。
🎛️ 微调预训练模型
要进行微调,只需加载一个检查点(不要恢复训练!)并从那里开始训练:
CUDA_VISIBLE_DEVICES=0 python train.py --config configs/models/hero_model.yaml
--data_config configs/data/scannet_default_train.yaml
--load_weights_from_checkpoint weights/hero_model.ckpt
只需将数据配置更改为您想要微调到的数据集即可。
🔧 其他训练和测试选项
有关学习率、消融实验设置等其他训练选项以及测试选项,请参阅 options.py 文件。
✨ 可视化
除了在 test.py 脚本中进行的快速深度可视化之外,还有两个脚本可用于可视化深度输出。
第一个是 visualization_scripts/visualize_scene_depth_output.py。该脚本会生成一段视频,其中包含参考帧和源帧的彩色图像、深度预测结果、代价体积估计、真实深度以及根据深度估算的法线。该脚本假设您已经使用 test.py 脚本缓存了深度输出,并且接受与 test.py 相同的命令格式:
# 示例命令,用于获取密集帧的可视化效果
CUDA_VISIBLE_DEVICES=0 python ./visualization_scripts/visualize_scene_depth_output.py --name HERO_MODEL \
--output_base_path OUTPUT_PATH \
--data_config configs/data/scannet_dense_test.yaml \
--num_workers 8;
其中 OUTPUT_PATH 是 SimpleRecon 的基础结果目录(即您最初用于测试的目录)。您还可以选择在运行此脚本之前先运行 .visualization_scripts/generate_gt_min_max_cache.py,以获取场景平均的最小和最大深度值,用于颜色映射;如果这些值不可用,则脚本会使用0米和5米作为颜色映射的最小值和最大值。
第二个脚本则允许实时可视化网格重建过程。如果已有缓存的深度图,脚本将直接使用;否则,它会先通过模型预测深度图,然后再进行融合。脚本会迭代地加载深度图,将其融合,保存当前步骤的网格文件,并将该网格与俯视视角的摄像机标记一起渲染,同时还会从摄像机视角生成第一人称视角的视频。
# 示例命令,用于获取网格重建的实时可视化效果
CUDA_VISIBLE_DEVICES=0 python visualize_live_meshing.py --name HERO_MODEL \
--output_base_path OUTPUT_PATH \
--config_file configs/models/hero_model.yaml \
--load_weights_from_checkpoint weights/hero_model.ckpt \
--data_config configs/data/scannet_dense_test.yaml \
--num_workers 8;
默认情况下,脚本会将网格保存到一个中间位置,您也可以选择传递 --use_precomputed_partial_meshes 参数,以便在再次可视化相同网格时节省时间。不过,只有在前一次运行中计算过的中间网格才能被重复使用。
📝🧮👩💻 变换矩阵的表示法
简而言之: world_T_cam == world_from_cam
本仓库使用“cam_T_world”表示从世界坐标系到相机坐标系的变换矩阵(外参)。其目的是使变量在从右向左相乘时,两侧的坐标系名称能够匹配:
cam_points = cam_T_world @ world_points
world_T_cam 表示相机姿态(从相机坐标系到世界坐标系)。ref_T_src 表示从源视图到参考视图的变换。
最后,这种表示法既可以表示旋转,也可以表示平移,例如:world_R_cam 和 world_t_cam。
🗺️ 世界坐标系
本仓库主要针对ScanNet设计,因此虽然其功能理论上适用于任何坐标系(可通过输入参数指定),但我们提供的模型权重默认假设使用的是ScanNet坐标系。这一点非常重要,因为我们在元数据中包含了光线信息。如果使用这些权重处理其他数据集,应将其转换为ScanNet坐标系。我们包含的数据集类会自动执行相应的坐标变换。
🐜🔧 错误修复
更新 2022年12月31日:
本次更新修复了几个 bug。您需要更新您的代码分支,并使用本 README 开头表格中的新权重文件。此外,还需确保已使用读取工具正确提取了内参文件。
- 我们最初在 ScanNet 数据集中使用了一组略有偏差的内参数据。现在仓库已切换到
intrinsics文件夹中的内参。 - 成本体积中的 MLP 没有应用翻转变换增强,导致边缘附近出现偏差。因此,我们在基础数据集类中加入了基于几何的翻转变换,但仅在训练集上启用。
- 投影过程中存在一个 bug,导致成本体积中的掩码无法正常工作。为此,我们现已改用与 OpenCV 和 Kornia 相同的归一化方法。
感谢所有指出问题并耐心等待我们修复的人。
应用这些修复后,各项指标均有提升,相关权重也已上传至此。如需查看旧版指标、代码和权重,请参考此 commit hash:7de5b451e340f9a11c7fd67bd0c42204d0b009a9。
修复 bug 后的模型完整指标:
深度估计
--config |
绝对差↓ | 绝对相对误差↓ | 平方相对误差↓ | RMSE↓ | log RMSE↓ | delta < 1.05↑ | delta < 1.10↑ |
|---|---|---|---|---|---|---|---|
hero_model.yaml, 元数据 + Resnet |
0.0868 | 0.0428 | 0.0127 | 0.1472 | 0.0681 | 74.26 | 90.88 |
dot_product_model.yaml, 点积 + Resnet |
0.0910 | 0.0453 | 0.0134 | 0.1509 | 0.0704 | 71.90 | 89.75 |
网格融合
--config |
准确率↓ | 完整性↓ | 距离误差↓ | 召回率↑ | 精确率↑ | F1 分数↑ |
|---|---|---|---|---|---|---|
hero_model.yaml, 元数据 + Resnet |
5.41 | 5.98 | 5.69 | 0.695 | 0.668 | 0.680 |
dot_product_model.yaml, 点积 + Resnet |
5.66 | 6.18 | 5.92 | 0.682 | 0.655 | 0.667 |
对比:
--config |
模型 | 绝对差↓ | 平方相对误差↓ | delta < 1.05↑ | 距离误差↓ | F1 分数↑ |
|---|---|---|---|---|---|---|
hero_model.yaml |
元数据 + Resnet 匹配 | 0.0868 | 0.0127 | 74.26 | 5.69 | 0.680 |
OLD hero_model.yaml |
元数据 + Resnet 匹配 | 0.0885 | 0.0125 | 73.16 | 5.81 | 0.671 |
dot_product_model.yaml |
点积 + Resnet 匹配 | 0.0910 | 0.0134 | 71.90 | 5.92 | 0.667 |
OLD dot_product_model.yaml |
点积 + Resnet 匹配 | 0.0941 | 0.0139 | 70.48 | 6.29 | 0.642 |
帧数的小 bug:
最初,该仓库为默认的 DVMVS 风格关键帧生成了 tuple 文件,其中 ScanNetv2 测试集多出了 9 帧,总数为 25599 帧。这是一个处理跟踪丢失时的小 bug,现已修复。现在,该仓库应能完全复现 DVMVS 的关键帧缓冲区,测试集的关键帧数量为 25590 帧。该 bug 的唯一影响是多出了 9 帧,其余 tuple 文件与 DVMVS 完全一致。出错的帧位于以下扫描场景中:
扫描场景 原始帧数 新帧数
--------------------------------------
scene0711_00 393 392
scene0727_00 209 208
scene0736_00 1023 1022
scene0737_00 408 407
scene0751_00 165 164
scene0775_00 220 219
scene0791_00 227 226
scene0794_00 141 140
scene0795_00 102 101
默认测试集的 tuple 文件已更新。由于额外帧的数量差异很小(约 3e-4),因此指标未发生变化。
🗺️💾 COLMAP 数据集
简而言之: 缩放位姿并裁剪图像。
我们确实提供了一个用于从 COLMAP 稀疏重建中加载图像的数据加载器。为了使 SimpleRecon 正常工作,您需要将图像裁剪至与 ScanNet 视场角大致相同的范围(类似于 iPhone 视频模式下的视场角),并根据已知的真实世界测量值缩放位姿的位置。如果未执行这些步骤,成本体积将无法正确构建,网络也无法准确估计深度。
🙏 致谢
我们感谢 TransformerFusion 的 Aljaž Božič、Neural Recon 的 Jiaming Sun,以及 DeepVideoMVS 的 Arda Düzçeker,他们迅速提供了有用的基准信息,并在短时间内开放了自己的代码库。
tuple 文件生成脚本大量使用了 DeepVideoMVS 的 关键帧缓冲区 的修改版本(再次感谢 Arda 及其团队)。
torch_point_cloud_fusion 中的 PyTorch 点云融合模块代码借用了 3DVNet 的 repo。感谢 Alexander Rich!
我们还要感谢 Niantic 的基础设施团队在我们需要时提供的快速支持。谢谢大家!
Mohamed 得到了微软研究院博士奖学金(MRL 2018-085)的支持。
📜 BibTeX
如果您在研究中使用了我们的工作,请考虑引用我们的论文:
@inproceedings{sayed2022simplerecon,
title={SimpleRecon: 无 3D 卷积的 3D 重建},
author={Sayed, Mohamed and Gibson, John and Watson, Jamie and Prisacariu, Victor and Firman, Michael and Godard, Cl{\'e}ment},
booktitle={欧洲计算机视觉大会 (ECCV) 论文集},
year={2022},
}
👩⚖️ 许可证
版权所有 © Niantic, Inc. 2022。专利申请中。 保留所有权利。 详细条款请参阅 许可证文件。
常见问题
相似工具推荐
openclaw
OpenClaw 是一款专为个人打造的本地化 AI 助手,旨在让你在自己的设备上拥有完全可控的智能伙伴。它打破了传统 AI 助手局限于特定网页或应用的束缚,能够直接接入你日常使用的各类通讯渠道,包括微信、WhatsApp、Telegram、Discord、iMessage 等数十种平台。无论你在哪个聊天软件中发送消息,OpenClaw 都能即时响应,甚至支持在 macOS、iOS 和 Android 设备上进行语音交互,并提供实时的画布渲染功能供你操控。 这款工具主要解决了用户对数据隐私、响应速度以及“始终在线”体验的需求。通过将 AI 部署在本地,用户无需依赖云端服务即可享受快速、私密的智能辅助,真正实现了“你的数据,你做主”。其独特的技术亮点在于强大的网关架构,将控制平面与核心助手分离,确保跨平台通信的流畅性与扩展性。 OpenClaw 非常适合希望构建个性化工作流的技术爱好者、开发者,以及注重隐私保护且不愿被单一生态绑定的普通用户。只要具备基础的终端操作能力(支持 macOS、Linux 及 Windows WSL2),即可通过简单的命令行引导完成部署。如果你渴望拥有一个懂你
stable-diffusion-webui
stable-diffusion-webui 是一个基于 Gradio 构建的网页版操作界面,旨在让用户能够轻松地在本地运行和使用强大的 Stable Diffusion 图像生成模型。它解决了原始模型依赖命令行、操作门槛高且功能分散的痛点,将复杂的 AI 绘图流程整合进一个直观易用的图形化平台。 无论是希望快速上手的普通创作者、需要精细控制画面细节的设计师,还是想要深入探索模型潜力的开发者与研究人员,都能从中获益。其核心亮点在于极高的功能丰富度:不仅支持文生图、图生图、局部重绘(Inpainting)和外绘(Outpainting)等基础模式,还独创了注意力机制调整、提示词矩阵、负向提示词以及“高清修复”等高级功能。此外,它内置了 GFPGAN 和 CodeFormer 等人脸修复工具,支持多种神经网络放大算法,并允许用户通过插件系统无限扩展能力。即使是显存有限的设备,stable-diffusion-webui 也提供了相应的优化选项,让高质量的 AI 艺术创作变得触手可及。
everything-claude-code
everything-claude-code 是一套专为 AI 编程助手(如 Claude Code、Codex、Cursor 等)打造的高性能优化系统。它不仅仅是一组配置文件,而是一个经过长期实战打磨的完整框架,旨在解决 AI 代理在实际开发中面临的效率低下、记忆丢失、安全隐患及缺乏持续学习能力等核心痛点。 通过引入技能模块化、直觉增强、记忆持久化机制以及内置的安全扫描功能,everything-claude-code 能显著提升 AI 在复杂任务中的表现,帮助开发者构建更稳定、更智能的生产级 AI 代理。其独特的“研究优先”开发理念和针对 Token 消耗的优化策略,使得模型响应更快、成本更低,同时有效防御潜在的攻击向量。 这套工具特别适合软件开发者、AI 研究人员以及希望深度定制 AI 工作流的技术团队使用。无论您是在构建大型代码库,还是需要 AI 协助进行安全审计与自动化测试,everything-claude-code 都能提供强大的底层支持。作为一个曾荣获 Anthropic 黑客大奖的开源项目,它融合了多语言支持与丰富的实战钩子(hooks),让 AI 真正成长为懂上
ComfyUI
ComfyUI 是一款功能强大且高度模块化的视觉 AI 引擎,专为设计和执行复杂的 Stable Diffusion 图像生成流程而打造。它摒弃了传统的代码编写模式,采用直观的节点式流程图界面,让用户通过连接不同的功能模块即可构建个性化的生成管线。 这一设计巧妙解决了高级 AI 绘图工作流配置复杂、灵活性不足的痛点。用户无需具备编程背景,也能自由组合模型、调整参数并实时预览效果,轻松实现从基础文生图到多步骤高清修复等各类复杂任务。ComfyUI 拥有极佳的兼容性,不仅支持 Windows、macOS 和 Linux 全平台,还广泛适配 NVIDIA、AMD、Intel 及苹果 Silicon 等多种硬件架构,并率先支持 SDXL、Flux、SD3 等前沿模型。 无论是希望深入探索算法潜力的研究人员和开发者,还是追求极致创作自由度的设计师与资深 AI 绘画爱好者,ComfyUI 都能提供强大的支持。其独特的模块化架构允许社区不断扩展新功能,使其成为当前最灵活、生态最丰富的开源扩散模型工具之一,帮助用户将创意高效转化为现实。
gemini-cli
gemini-cli 是一款由谷歌推出的开源 AI 命令行工具,它将强大的 Gemini 大模型能力直接集成到用户的终端环境中。对于习惯在命令行工作的开发者而言,它提供了一条从输入提示词到获取模型响应的最短路径,无需切换窗口即可享受智能辅助。 这款工具主要解决了开发过程中频繁上下文切换的痛点,让用户能在熟悉的终端界面内直接完成代码理解、生成、调试以及自动化运维任务。无论是查询大型代码库、根据草图生成应用,还是执行复杂的 Git 操作,gemini-cli 都能通过自然语言指令高效处理。 它特别适合广大软件工程师、DevOps 人员及技术研究人员使用。其核心亮点包括支持高达 100 万 token 的超长上下文窗口,具备出色的逻辑推理能力;内置 Google 搜索、文件操作及 Shell 命令执行等实用工具;更独特的是,它支持 MCP(模型上下文协议),允许用户灵活扩展自定义集成,连接如图像生成等外部能力。此外,个人谷歌账号即可享受免费的额度支持,且项目基于 Apache 2.0 协议完全开源,是提升终端工作效率的理想助手。
markitdown
MarkItDown 是一款由微软 AutoGen 团队打造的轻量级 Python 工具,专为将各类文件高效转换为 Markdown 格式而设计。它支持 PDF、Word、Excel、PPT、图片(含 OCR)、音频(含语音转录)、HTML 乃至 YouTube 链接等多种格式的解析,能够精准提取文档中的标题、列表、表格和链接等关键结构信息。 在人工智能应用日益普及的今天,大语言模型(LLM)虽擅长处理文本,却难以直接读取复杂的二进制办公文档。MarkItDown 恰好解决了这一痛点,它将非结构化或半结构化的文件转化为模型“原生理解”且 Token 效率极高的 Markdown 格式,成为连接本地文件与 AI 分析 pipeline 的理想桥梁。此外,它还提供了 MCP(模型上下文协议)服务器,可无缝集成到 Claude Desktop 等 LLM 应用中。 这款工具特别适合开发者、数据科学家及 AI 研究人员使用,尤其是那些需要构建文档检索增强生成(RAG)系统、进行批量文本分析或希望让 AI 助手直接“阅读”本地文件的用户。虽然生成的内容也具备一定可读性,但其核心优势在于为机器