3dgs项目详解 :convert.py
这个脚本的核心作用是自动化数据预处理流程。它调用了著名的三维重建软件 COLMAP,将用户提供的一组图片转换成 3D Gaussian Splatting 训练时所需要的格式,即包含相机位姿、稀疏点云和无畸变图像的数据集。
1.脚本参数如下:
--no_gpu
: 一个开关参数,如果使用此参数,则告诉COLMAP不要使用GPU。
--skip_matching
: 开关参数,如果提供,则跳过特征提取和匹配步骤(适用于已经有COLMAP项目的情况)。
--source_path
/ -s
: 必需参数,指定包含输入图片(在input
子目录中)的源文件夹路径。
--camera
: 指定COLMAP在处理图像时使用的相机模型,默认为OPENCV
,这是一个通用且强大的模型。
--colmap_executable
: 指定COLMAP可执行文件的路径。如果COLMAP已经在系统环境变量中,则无需指定。
--resize
: 开关参数,如果使用此参数,则在处理完成后,额外创建缩小版的图片。
--magick_executable
: 指定ImageMagick可执行文件的路径,仅在--resize
时需要。
2.调用colmap处理图片生成初始点云一共有四步如下:
特征提取
feat_extracton_cmd = ...
: 构造colmap feature_extractor
命令。这个命令会遍历input
文件夹下的所有图片,提取SIFT特征点,并将它们存入一个SQLite数据库 (database.db
) 中。
--ImageReader.single_camera 1
这个参数出现在 feature_extractor
(特征提取) 步骤中。
作用:它告诉 COLMAP,输入的所有图片都是由同一台相机(和同一个镜头)拍摄的。
含义:
ImageReader
是 COLMAP 中负责读取和解释图像数据的模块。single_camera
是这个模块下的一个选项。1
在这里是布尔值True
的意思。
--ImageReader.camera_mode l
作用:它指定了 COLMAP 在分析图像时应该使用哪一种相机数学模型。
含义:
相机模型是一组数学方程,用来描述真实世界中的三维点是如何通过相机镜头投影到二维图像传感器上的。
真实世界的镜头存在各种光学畸变(比如鱼眼镜头边缘的弯曲)。不同的相机模型用不同数量和类型的参数来描述这些畸变。
convert.py
中的默认值:脚本中默认使用--camera OPENCV
。OPENCV
模型是一个非常通用且强大的模型,它使用8个参数来描述各种常见的径向和切向畸变。它能很好地适用于大多数消费级相机和手机摄像头。
特征匹配
feat_matching_cmd = ...
: 构造colmap exhaustive_matcher
命令。这个命令会对数据库中所有图像对进行特征匹配,找出不同图像中对应相同三维点的特征点
三维重建
mapper_cmd = ...
: 构造colmap mapper
命令。这是COLMAP最核心的一步,它会根据特征匹配结果,通过“从运动中恢复结构”(Structure from Motion, SfM)算法,同时估算出相机的精确位姿(旋转和平移)和场景的稀疏三维点云。结果保存在/distorted/sparse
目录中
--Mapper.ba_global_function_tolerance=0.000001
这个参数出现在 mapper
(建图) 步骤中。
作用:它用于控制全局光束法平差 (Global Bundle Adjustment, BA) 的收敛精度,可以理解为设置一个更严格的“优化停止条件”。
含义:
Mapper
是 COLMAP 中负责增量式三维重建的模块。ba_global_function_tolerance
是其中关于光束法平差的一个高级参数。光束法平差是 SfM 流程中的一个核心优化步骤,它会同时微调所有相机位姿和所有三维点的坐标,使得三维点重投影回二维图像上的位置与最初检测到的特征点位置之间的误差(重投影误差)最小。
这个参数设置了当优化过程中成本函数(总体误差)的变化量小于
0.000001
时,就认为优化已经收敛,可以停止了。
图像去畸变
img_undist_cmd = ...
: 构造colmap image_undistorter
命令。Gaussian Splatting的渲染管线假设相机是理想的针孔模型(没有镜头畸变)。因此,这一步至关重要:它会读取之前重建的结果(包含畸变参数),然后生成一套不带畸变的图片(保存在/images
目录)和与之对应的新的相机参数和点云(保存在/sparse
目录)。这才是最终用于训练的数据
--output_type COLMAP
这个参数出现在 image_undistorter
(图像去畸变) 步骤中。
作用:它指定了去畸变过程的输出格式。
含义:
output_type
决定了image_undistorter
在生成无畸变图像的同时,如何组织和保存与之配套的相机参数和点云数据。COLMAP
是一个选项,表示输出应该是一个完整的、自包含的 COLMAP 项目。
为什么需要它:
当设置为
COLMAP
时,image_undistorter
不仅会生成去畸变后的图像(保存在images
文件夹),还会生成一个新的sparse
文件夹。这个新的
sparse
文件夹里包含了更新后的cameras.bin
,images.bin
和points3D.bin
文件。最关键的是,
cameras.bin
中的相机模型已经被转换成了理想的SIMPLE_PINHOLE
或PINHOLE
模型,并且images.bin
中每个相机的位姿和观测到的点云信息也相应地更新了。这正是 3D Gaussian Splatting 训练脚本所期望的输入格式:无畸变的图像 + 对应的理想针孔相机模型和位姿。
总结:这个参数确保了去畸变步骤的输出是一个可以直接用于下游任务(如此处的 Gaussian Splatting 训练)的、格式规范、数据一致的 COLMAP 项目
什么是畸变和去畸变?
1. 什么是畸变 (Distortion)?
想象一下你透过一个猫眼(门上的那种广角观察孔)看外面的世界。你看到的景象是不是边缘被严重拉伸和弯曲了?这就是一种非常夸张的畸变。
在摄影中,虽然没有猫眼那么夸张,但几乎所有的相机镜头(尤其是手机、运动相机和广角镜头)都会在不同程度上使图像产生变形,而不是完美地“横平竖直”。这种变形就叫做镜头畸变。
最常见的两种畸变类型是:
桶形畸变 (Barrel Distortion):
现象:图像的边缘向外凸出,看起来像一个木桶的侧面。直线,特别是靠近画面边缘的直线,会向外弯曲。
原因:这在广角镜头中非常常见。
枕形畸变 (Pincushion Distortion):
现象:与桶形畸变相反,图像的边缘向内凹陷,看起来像一个枕头。边缘的直线会向内弯曲。
原因:这在长焦镜头中比较常见。
为什么会产生畸变? 这是由镜片的物理特性决定的。为了将广阔的三维空间景象聚焦到一块平坦的二维图像传感器上,镜片必须是凸透镜。复杂的镜头由多个镜片组合而成,但无法做到在整个画面上都实现完美、线性的投影,因此畸变就产生了。
2. 什么是去畸变 (Undistortion)?
去畸变,顾名思义,就是通过数学计算矫正上述的镜头畸变,将一张“弯曲”的图片“拉直”,让它看起来像是用一个**理想的、不存在任何畸变的“针孔相机”**拍摄的一样。
(左:有畸变的原图,右:去畸变后的图)
3. 在这个项目中,是如何处理畸变和去畸变的?
这个项目的最终目标(3D Gaussian Splatting)需要一个非常精确的数学模型来描述场景。这个模型假设所有的输入图像都来自于理想的针孔相机。如果直接使用带有畸变的原始照片,会导致三维重建的严重错误——计算出的相机位置会不准,三维点云会变形,最终训练出的模型也会出现模糊、重影等问题。
因此,convert.py
脚本中有一套专门的流程来处理畸变:
第一步:用一个强大的模型来“描述”畸变
在
feature_extractor
(特征提取)阶段,脚本告诉 COLMAP 使用--ImageReader.camera_model OPENCV
。OPENCV
相机模型非常强大,它使用一组(通常是8个)数学参数来精确地描述桶形、枕形以及其他更复杂的畸变。在随后的
mapper
(建图)阶段,COLMAP 在计算相机位姿和三维点云的同时,也会估算出这一组精确的畸变参数。
第二步:根据描述“反向操作”来矫正畸变
在重建完成后,脚本调用
colmap image_undistorter
命令。这个工具会读取上一步估算出的畸变参数。
然后,它对每一张原始图片应用一个“反向”的数学变换,将因畸变而扭曲的像素“推回”到它们在理想针孔相机模型下应该在的位置。
这个过程会生成一套全新的、无畸变的图像,并保存在
images
文件夹中。同时,它还会生成一套与之匹配的、使用理想针孔相机模型(PINHOLE
)的相机参数文件。
总结一下:
畸变是相机镜头固有的物理缺陷,它让照片中的直线变弯。
去畸变是一个修正过程,它把弯曲的图像拉直,变成数学上完美的图像。
在这个项目中,去畸变是至关重要的预处理步骤。它通过 COLMAP 先建模畸变,再移除畸变,确保了提供给后续 3D Gaussian Splatting 训练算法的是干净、标准的输入数据,从而保证了最终三维重建的质量和真实感。
为什么项目还生成了一个stereo的文件夹?
在运行 convert.py
之后看到一个 stereo
文件夹,而代码里又没有明确创建它,这确实会让人困惑。
这个 stereo
文件夹是 COLMAP 自身工作流程的一部分,特别是为其**“稠密重建”(Dense Reconstruction)阶段准备的。虽然本项目没有使用**稠密重建,但 COLMAP 的某些命令会自动创建这个目录结构。
下面是详细的解释:
1. COLMAP 的两个核心阶段
COLMAP 的完整三维重建流程通常分为两个主要阶段:
稀疏重建 (Sparse Reconstruction / Structure-from-Motion, SfM):
目标:从图片中估算出相机的位姿(位置和方向)和一个稀疏的三维点云。这个点云只包含场景中最稳定、最明确的几千或几万个特征点,像是场景的“骨架”。
convert.py
中执行的步骤:feature_extractor
,exhaustive_matcher
,mapper
就是在执行这个阶段的任务。输出:生成
sparse
文件夹,里面包含了相机位姿和稀疏点云,这正是本项目所需要的全部内容。
稠密重建 (Dense Reconstruction / Multi-View Stereo, MVS):
目标:利用稀疏重建的结果,为图像中的几乎每一个像素都计算出其深度信息,从而生成一个包含数百万甚至上亿个点的稠密的、细节丰富的点云,更像是给“骨架”附上了“血肉”。
convert.py
中未执行的步骤:这个阶段通常需要调用patch_match_stereo
和stereo_fusion
等命令。工作目录:
stereo
文件夹就是 COLMAP 专门为这个阶段准备的工作空间。
2. stereo
文件夹里有什么?
如果执行了完整的稠密重建,stereo
文件夹会包含以下子目录和文件:
depth_maps
: 存放为每张(去畸变后的)输入图像生成的深度图。深度图记录了图像中每个像素距离相机的远近。normal_maps
: 存放为每张图像生成的法线贴图。法线贴图记录了每个像素所在表面的朝向。consistency_graphs
: 存放用于检查和过滤不同视图之间深度估计一致性的数据。
这些都是生成最终稠密点云(如 fused.ply
)所必需的中间产物。
3. 为什么本项目会生成 stereo
文件夹,但又不用它?
这是关键所在。convert.py
脚本的最后一步是调用 colmap image_undistorter
。
这个命令的一个主要目的,就是为后续的稠密重建(MVS)准备好输入数据。因此,当它运行时,它不仅会生成无畸变的图像和更新后的稀疏模型,还会贴心地提前创建好标准的MVS工作区目录结构,其中就包括了这个 stereo
文件夹。
然而,3D Gaussian Splatting 技术的巧妙之处在于,它不需要一个预先计算好的稠密点云。它直接从稀疏点云开始,通过自身的优化和自适应致密化过程来“生长”出覆盖整个场景的数百万个高斯球。
总结一下:
stereo
文件夹是 COLMAP 用于稠密重建的工作目录。convert.py
中的image_undistorter
命令为了方便后续可能的稠密重建流程,会自动创建这个文件夹。对于本项目(3D Gaussian Splatting)的训练来说,
stereo
文件夹是一个“副产品”,它的内容是完全用不上的。你可以安全地忽略甚至删除它。项目真正依赖的只有image_undistorter
生成的images
文件夹和sparse/0
文件夹里的内容。