这是使用培训和测试MVS深度估计模型的参考Pytorch实现。
SimplereCon:3D重建而无需3D卷积
Mohamed Sayed,John Gibson,Jamie Watson,Victor Adrian Prisacariu,Michael Firman和ClémentGodard
论文,ECCV 2022(ARXIV PDF),补充材料,项目页面,视频

此代码用于非商业用途;请参阅许可证文件以获取条款。如果您确实找到了本代码库的任何部分,请使用下面的bibtex引用我们的论文,然后链接此仓库。谢谢!
25/05/2023:修复了llvm-openmp , clang和protobuf的固定包装方面。如果您在运行代码时遇到困难,请使用此新的环境文件,并且/或如果数据加载仅限于单个线程。
09/03/2023:将Kornia版本添加到环境文件中,以解决Kornia键入问题。 (谢谢@natesimon!)
26/01/2023:已修改了许可证,以使运行模型出于学术原因更容易。请提供确切详细信息的许可证文件。
截至2022年3月31日,有一个更新可以修复稍微错误的内在插图,成本量的翻转增强以及投影中的数值精度错误。所有分数都在提高。您需要更新叉子并使用新的权重。请参阅错误修复。
在线默认帧的预定扫描在这里:https://drive.google.com/drive/folders/1dsofi9gayyhqjsx4i_ng0-3ebcafwxjv?usp = share_link
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 | 模型 | ABS差异↓ | SQ Rel↓ | delta <1.05↑ | 倒角↓ | F-SCORE↑ |
|---|---|---|---|---|---|---|
hero_model.yaml | 元数据 +重新连接匹配 | 0.0868 | 0.0127 | 74.26 | 5.69 | 0.680 |
dot_product_model.yaml | 点产品 +重新连接匹配 | 0.0910 | 0.0134 | 71.90 | 5.92 | 0.667 |
hero_model是我们在论文中使用的那个
--config | 模型 | 推理速度( --batch_size 1 ) | 推理GPU内存 | 近似训练时间 |
|---|---|---|---|---|
hero_model | 英雄,元数据 +重新连接 | 130ms / 70ms(优化速度) | 2.6GB / 5.7GB(优化速度) | 36小时 |
dot_product_model | 点产品 +重新连接 | 80ms | 2.6GB | 36小时 |
随着较大的批次,速度大大提高。在非速度优化模型上,批量尺寸为8,潜伏期下降到约40ms。
datasets/arkit_dataset.py上。更新:现在有一个快速读取文件data_scripts/ios_logger_arkit_readme.md,用于使用data_scripts/ios_logger_preprocessing.py的脚本处理和运行iOS-Logger扫描。 现在,我们包括了两次扫描供人们立即尝试使用该代码的扫描。您可以从这里下载这些扫描。
步骤:
hero_model的权重下载到权重目录中。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 ;这将输出网格,快速深度和SOCRES在OUTPUT_PATH下对LIDAR深度进行基准测试时。
此命令使用vdr_dense.yaml ,该命令将为每个帧生成深度并将其融合到网格中。在论文中,我们改用Fuse KeyFrames报告得分,您可以使用vdr_default.yaml运行那些。您也可以通过使用vdr_dense_offline.yaml来使用dense_offline元组。
请参阅下面的测试和评估部分。确保为数据集使用正确的配置标志。
请在此处按照说明下载数据集。该数据集很大(> 2TB),因此请确保您有足够的空间,尤其是用于提取文件。
下载后,使用此脚本将原始传感器数据导出到图像和深度文件。
我们已经编写了一个快速教程,并包含了修改的脚本,以帮助您下载和提取ScannETV2。您可以在data_scripts/scannet_wrangling_scripts/可以找到它们
您应该更改configs/ data/ in configs/data/ config的数据dataset_path config参数,以匹配数据集所在的位置。
代码库希望ScannETV2处于以下格式:
dataset_path
scans_test (test scans)
scene0707
scene0707_00_vh_clean_2.ply (gt mesh)
sensor_data
frame-000261.pose.txt
frame-000261.color.jpg
frame-000261.color.512.png (optional, image at 512x384)
frame-000261.color.640.png (optional, image at 640x480)
frame-000261.depth.png (full res depth, stored scale *1000)
frame-000261.depth.256.png (optional, depth at 256x192 also
scaled)
scene0707.txt (scan metadata and image sizes)
intrinsic
intrinsic_depth.txt
intrinsic_color.txt
...
scans (val and train scans)
scene0000_00
(see above)
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上找到。对于扫描仪的测试扫描,它们在data_splits/ScanNetv2/standard_split上。我们的核心深度编号是使用data_splits/ScanNetv2/standard_split/test_eight_view_deepvmvs.txt计算的。
这是用于测试类型的类型的快速分类群:
default :遵循所有源框架过去的DeepVideOmvs的每个密钥帧的元组。除非另有说明,否则用于所有深度和网格评估。用于扫描,使用data_splits/ScanNetv2/standard_split/test_eight_view_deepvmvs.txt 。offline :扫描中的每个帧的元组,在过去和将来相对于当前帧都可以是源框架。当一个场景离线捕获时,这些都是有用的,您希望能够获得最佳准确性。使用在线元组,随着相机移开,所有源框架都落后时,成本量将包含空区域。但是,对于离线元组,两端的成本量都已饱满,从而实现了更好的规模(和度量)估计。dense :用于扫描中所有源框架的扫描中的每个帧的在线元组(如默认)。对于扫描,这将是data_splits/ScanNetv2/standard_split/test_eight_view_deepvmvs_dense.txt 。offline :用于扫描中每个密钥帧的每个密钥帧的离线元组。对于火车和验证集,我们遵循与DeepVideOMV中相同的元组增强策略,并使用相同的核心生成脚本。
如果您想自己生成这些元组,则可以在data_scripts/generate_train_tuples.py上使用train元组和data_scripts/generate_test_tuples.py进行测试元组。这些遵循与test.py相同的配置格式,并将使用您构建的任何数据集类别读取姿势Informaiton。
测试示例:
# default tuples
python ./data_scripts/generate_test_tuples.py
--data_config configs/data/scannet_default_test.yaml
--num_workers 16
# dense tuples
python ./data_scripts/generate_test_tuples.py
--data_config configs/data/scannet_dense_test.yaml
--num_workers 16火车的示例:
# train
python ./data_scripts/generate_train_tuples.py
--data_config configs/data/scannet_default_train.yaml
--num_workers 16
# val
python ./data_scripts/generate_val_tuples.py
--data_config configs/data/scannet_default_val.yaml
--num_workers 16这些脚本将首先检查数据集中的每个帧,以确保其具有现有的RGB帧,现有的深度帧(如果适用于数据集)以及现有和有效的姿势文件。它将这些valid_frames保存在每个扫描文件夹中的文本文件中,但是如果仅读取目录,它将忽略保存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)通过该编码禁用图像批处理进行(<10^-4)精确测试。运行--batch_size 4最多有疑问,如果您想获得尽可能稳定的数字并避免使用pytorch gremlins,请使用--batch_size 1进行比较评估。
如果您想将其用于速度,请设置--fast_cost_volume为true。这将启用通过匹配编码器进行批处理,并启用EINOPS优化的特征量。
# Example command to just compute scores
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 ;
# If you'd like to get a super fast version use:
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的自定义实现。Matching_cubes,允许单个围墙。我们使用单壁网格进行评估。如果这对您不重要,则可以将export_single_mesh设置为False in test.py中的export_mesh 。--depth_fuser open3d将使用Open3D深度定影。该定影器支持颜色,您可以使用--fuse_color标志来启用此功能。默认情况下,将使用深度图剪辑至3M以进行融合,将使用0.04m 3的TSDF分辨率,但是您可以通过更改--max_fusion_depth and --fusion_resolution更改)。
您可以选择使用--mask_pred_depths不存在VAIID MVS信息时,要求将用于融合的预测深度掩盖。默认情况下不启用这一点。
您还可以融合成本量编码器的成本量的最佳猜测深度,该成本量编码器引入了强大的图像。您可以使用--fusion_use_raw_lowest_cost来执行此操作。
网格将存储在results_path/meshes/下。
# Example command to fuse depths to get 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中。
# Example command to compute scores and cache 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 ;
# Example command to fuse depths to get color 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
--depth_fuser open3d
--fuse_color
--batch_size 4 ;快速
还有其他脚本可以更深入地可视化输出深度和融合,但是为了快速导出深度图可视化,您可以使用--dump_depth_visualization 。可视化将存储在results_path/viz/quick_viz/ 。
# Example command to output quick depth visualizations
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存储库中的Fuser进行深度图的点云融合。
# Example command to fuse depths into point clouds.
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的代码,但在点云中加载代替对网格表面进行采样。
默认情况下,将模型和张板事件文件保存到~/tmp/tensorboard/<model_name> 。可以使用--log_dir标志更改。
我们在默认的ScannETV2 Split上以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 。这将产生一个带有参考和源框架的颜色图像,深度预测,成本量估计,GT深度以及深度估计的正态的视频。脚本假设您使用test.py缓存了深度输出,并且接受与test.py相同的命令模板格式:
# Example command to get visualizations for dense frames
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在此脚本之前,以获取用于colormapping的最低和最大深度值的平均场景;如果这些不可用,则脚本将使用0m和5m用于Colomapping Min和Max。
第二个允许实时可视化网格链。该脚本将使用缓存的深度图(如果有),否则它将使用该模型在融合之前预测它们。该脚本将在深度图上迭代加载,融合它,在此步骤中保存网格文件,并将此网格与birdseye视频的相机标记呈现,以及从相机的角度来看FPV视频。
# Example command to get live visualizations for mesh reconstruction
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再次可视化相同的网格。所有中间网格都必须在先前的运行中计算才能正常工作。
tl; dr: 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
此存储库适用于扫描仪,因此尽管其功能应允许任何坐标系(通过输入标志发出信号),但我们提供的模型权重假定扫描仪坐标系。这很重要,因为我们将光线信息作为元数据的一部分。这些权重的其他数据集应转换为扫描仪系统。我们包括的数据集类将执行适当的转换。
此更新中有一些错误,您将需要更新叉子,并在此读数开头附近使用桌子上的新权重。您还需要确保使用阅读器提取了正确的内在文件。
感谢所有指出的内容,并在我们进行修复时耐心等待。
这些修复程序都可以提高所有分数,并且相关的权重在此处上传。对于旧分数,代码和权重,请检查此提交哈希:7DE5B451E340F9A11C7FD67BD0C42204D0B009A9
带有错误修复的模型的完整分数:
深度
--config | ABS差异↓ | ABS REL↓ | SQ Rel↓ | RMSE↓ | 日志RMSE↓ | delta <1.05↑ | delta <1.10↑ |
|---|---|---|---|---|---|---|---|
hero_model.yaml ,元数据 +重新连接 | 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 | ACC↓ | Comp↓ | 倒角↓ | 回想↑ | 精度↑ | F-SCORE↑ |
|---|---|---|---|---|---|---|
hero_model.yaml ,元数据 +重新连接 | 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 | 模型 | ABS差异↓ | SQ Rel↓ | delta <1.05↑ | 倒角↓ | F-SCORE↑ |
|---|---|---|---|---|---|---|
hero_model.yaml | 元数据 +重新连接匹配 | 0.0868 | 0.0127 | 74.26 | 5.69 | 0.680 |
旧的hero_model.yaml | 元数据 +重新连接匹配 | 0.0885 | 0.0125 | 73.16 | 5.81 | 0.671 |
dot_product_model.yaml | 点产品 +重新连接匹配 | 0.0910 | 0.0134 | 71.90 | 5.92 | 0.667 |
旧dot_product_model.yaml | 点产品 +重新连接匹配 | 0.0941 | 0.0139 | 70.48 | 6.29 | 0.642 |
最初,此存储库吐出元组文件,用于默认的DVMVS样式键框,用于ScannETV2测试集的9个额外的25599帧。现在有一个较小的错误,处理丢失的跟踪现在已经固定了。现在,此存储库应完全模仿DVMVS键帧缓冲区,并使用25590个密钥帧进行测试。该错误的唯一影响是包含9个额外的框架,所有其他元组都与DVMV完全相同。有问题的框架在这些扫描中
scan previous count new count
--------------------------------------
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
默认测试的元组文件已更新。由于这是额外评分的额外框架差异很小(〜3E-4),因此得分没有变化。
TL; DR:缩放您的姿势并裁剪图像。
我们确实提供了一个数据加载器,用于从Colmap稀疏重建中加载图像。为此,要与SimpleRecon一起使用,您需要裁剪图像以匹配扫描仪的FOV(大致类似于视频模式下的iPhone FOV),并使用已知的现实世界测量值来扩展姿势的位置。如果未采取这些步骤,则无法正确构建成本量,并且网络将无法正确估计深度。
我们感谢TransformerFusion的AljažBožič,Neural Recon的Jiaming Sun和DeepVideOmvs的ArdaDüzççeker迅速提供有用的信息来帮助基线并使其代码库随时可用,尤其是在短时间内。
元组一代脚本大量使用了DeepVideOmvs的KeyFrame Buffer的修改版本(再次感谢Arda and Co!)。
torch_point_cloud_fusion CODE上的Pytorch点云融合模块是从3DVNET的存储库中借用的。谢谢亚历山大·里奇!
我们还要感谢Niantic的基础设施团队在需要时采取的快速行动。谢谢伙计们!
Mohamed由Microsoft Research PhD奖学金(MRL 2018-085)资助。
如果您发现我们的工作对您的研究有用,请考虑引用我们的论文:
@inproceedings{sayed2022simplerecon,
title={SimpleRecon: 3D Reconstruction Without 3D Convolutions},
author={Sayed, Mohamed and Gibson, John and Watson, Jamie and Prisacariu, Victor and Firman, Michael and Godard, Cl{'e}ment},
booktitle={Proceedings of the European Conference on Computer Vision (ECCV)},
year={2022},
}
版权所有©Niantic,Inc。2022。申请专利。版权所有。请参阅许可证文件以获取条款。