1. 使用sdfstudio 运行Neus
命令解释:
- 这个Command 解释 针对是否是indoor scene; 当设置为True 的时候,camera 处于sphere 内部时候SDF存在 positive value ; 否则 设置为False
–pipeline.model.sdf-field.inside-outside True
运行命令:
ns-train neus --pipeline.model.sdf-field.inside-outside False sdfstudio-data --data DATA_PATH
Neus 参数解析包括其他methods (volsdf、neus 和monodepth ) 的Dataparser 的指令主要是在 sdfstudio_dataparser.py 文件中:
不同的SDF 方法需要的Input 不一样,他们的input 读取都被集成在了_generate_dataparser_outputs 函数里面。 针对不同的 surface reconstruction 方法设置了一些参数:
- self.config.include_mono_prior 如果该属性被激活,那么需要用到 单目的 prior,需要 depth map和 normal map
- self.config.include_foreground_mask 如果该属性被激活,那么需要每一帧还需要mask 图像, foreground_mask.png
- self.config.include_sfm_points 如果该属性被激活,那么需要sfm_sparse_points_view.txt 文件
- self.config.load_pairs, 该属性的功能还没有看到,在Neus 中是没有这一项的,设置为False
分析_generate_dataparser_outputs 函数 解析参数的过程:
Neus 中主要 用到的rgb图 和位姿矩阵T。没有用到的是normal图和depth 图像.
需要注意的是Neus 中的 rgb源图像是1200*1600 的图像,但是sdfstudio 中的 DTU 数据集 对应的 noraml map 和 depth map 都是 384×384 的图像。且生成的Camera 的 height and width 都是384.
cameras = Cameras(
fx=fx,
fy=fy,
cx=cx, ##198
cy=cy, ## 198
height=height,
width=width,
camera_to_worlds=camera_to_worlds[:, :3, :4],
camera_type=CameraType.PERSPECTIVE,
)
所以dtu 的图像肯定在之后进行了 crop 且和 normal 图像还有depth 图像对齐。
-
- pipeline.model.near-plane 指定near 和 far 的采样远近。
指定的是 在一条Ray上开始采样的距离 near 和 far
- pipeline.model.near-plane 指定near 和 far 的采样远近。
–pipeline.model.near-plane=0
–pipeline.model.far-plane=6
-
- pipeline.model.collider-params 描述的是Scene 的near 和 far, Scene 和Ray 相交的边界?
他们描述的都是采样的距离的 Near 和 Far 只是最后 Scene 的 near 和 Far 才会送到 Raybundle 类的 near 和 far,成为真正的 Near 和 Far
- pipeline.model.collider-params 描述的是Scene 的near 和 far, Scene 和Ray 相交的边界?
–pipeline.model.collider-params near_plane 0.0 far_plane 6.0
ns-train neus --pipeline.model.sdf-field.inside-outside False --pipeline.model.near-plane=0 --pipeline.model.far-plane=6 --pipeline.model.collider-params near_plane 0.0 far_plane 6.0 --vis tensorboard sdfstudio-data --data datasets/kitti360_Neus/
运行monosdf 需要mono_prior的信息:
ns-train monosdf --pipeline.model.sdf-field.inside-outside False --trainer.load_dir outputs/datasets-kitti360_mono_priors/monosdf/2023-02-05_162207/sdfstudio_models --trainer.steps_per_eval_image=1000 sdfstudio-data --data datasets/kitti360_mono_priors/ --include-mono-prior True
Dataloader 代码阅读:
创立了 traindataset 之后,读取了位姿和imgae_filename 但是还没有读取图像变成tensor。
self.train_dataset = self.create_train_dataset()
self.eval_dataset = self.create_eval_dataset()
GeneralizedDataset 函数可以读取图像:
其中track 函数,相当于tqdm 一样的python 库,可以显示读取图像的进度。
Neus 在sdfstudio 中读取的图像并非是dtu 中的 1200*1600 的图像,而是其经过处理之后的384×384 的图像。
Neus 在读取datasets 的时候,读取rgb 图像;c2w 位姿,相机的一些参数就可以了。
neus 运行在sdfstudio 的命令:
先指定需要训练的GPU 的编号:
export CUDA_VISIBLE_DEVICES=0
如果在pycharm 中,把 CUDA_VISIBLE_DEVICES=0 加到前面 Environment variables
需要使用预加载的训练权重参数 : –trainer.load-dir {None}|PATH]
ns-train neus --trainer.load-dir outputs/datasets-kitti360_Neus/neus/2023-01-30_160720/sdfstudio_models/ --pipeline.model.sdf-field.inside-outside False --viewer.skip_openrelay True sdfstudio-data --data datasets/kitti360_Neus/
将数据分成trainset 和 valset验证在NVS合成的质量
在sdfstudio 中,trainset 和 Valset 是同一批数据,为了验证在新视角的synthetic viewpoint 的合成质量,需要修改sdfstudio_dataparser.py 文件,将图像分成trainset 和 valset.
思路:通过控制Train 和 Test 对应着不同的indice来spilt两个不同的数据集
Code 如下所示:
num_images = len(image_filenames)
num_train_images = math.ceil(num_images * self.config.train_split_percentage)
num_eval_images = num_images - num_train_images
i_all = np.arange(num_images)
i_train = np.linspace(
0, num_images - 1, num_train_images, dtype=int
) # equally spaced training images starting and ending at 0 and num_images-1
i_eval = np.setdiff1d(i_all, i_train) # eval images are the remaining images
assert len(i_eval) == num_eval_images
if split == "train":
indices = i_train
elif split in ["val", "test"]:
indices = i_eval
else:
raise ValueError(f"Unknown dataparser split {split}")
sdf 方法中对Ray 进行 Sample 并且进行渲染
在 base_surface.py 文件当中
在base_surface_model.py 的模型中,实现了 sampleing 和对于各个采样点的weight的求解。
collider_type 一共应该有3中形式:
-
Near_far collider
-
box collider
-
sphere collider
Neus 中默认开启了 self.config.background_model = mlp 对于背景采集了 [6,1000] 32个采样点
区分 collider.near_far 和 Scenebox.near_far
当设置 collider 设置为 【2,6】的时候, Scene_box 的Near 和 Far 设置为 【0,6】的时候.。但是代码最后是采用的 Scene_box 的near 和 Far
Code 如下,near 和 Far 使用的是 ray_bundle 的 near 和 Far, 表示将【0,1】 之间的数字映射到 【near,far】之间:
计算公式如下:
计算斜率:k = (far-near)/(1-0)
映射的数值为 mapped_x = x*k + near = x *far + (1-x)*near
s_near, s_far = (self.spacing_fn(x) for x in (ray_bundle.nears.clone(), ray_bundle.fars.clone()))
spacing_to_euclidean_fn = lambda x: self.spacing_fn_inv(x * s_far + (1 - x) * s_near)