ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

从零自制3DGS数据集:Colmap相机位姿估计与稀疏点云生成全流程指南

从零自制3DGS数据集:Colmap相机位姿估计与稀疏点云生成全流程指南 简介这是一份面向计算机视觉开发者和3DGS研究者的项目源码包聚焦如何借助Colmap完成3D Gaussian Splatting数据集的自制流程解决从图像采集到模型训练前数据准备的关键环节。压缩包共12个文件以Python脚本如colmap_config.py、dense_reconstruction.py、format_converter.py、示例图片5张jpg和说明文档Markdown、HTML等为主总大小仅379KB轻量且结构清晰。目前已吸引306人学习适合刚接触3DGS或希望低成本构建场景数据的入门与进阶用户。通过源码中的配置、稠密重建和格式转换脚本读者可以快速复现稀疏重建、稠密点云生成及数据格式转换等步骤同时结合示例图片和操作说明避开常见坑点为后续3DGS训练提供规范的数据集基础。1. 项目概述为什么需要自制3DGS数据集Colmap和3DGS3D Gaussian Splatting三维高斯泼溅这两个关键词放在一起基本就锁定了一个方向——你想训练自己的3DGS模型并且打算从零开始采集数据而不是直接去下载现成的公开数据集。这个需求最近在三维视觉和图形学社区里非常常见因为3DGS虽然开源模型一大堆但真正要落地到自己的场景比如室内房间、户外雕塑、某个商品物件第一个绕不开的坎就是怎么把你自己拍的照片变成3DGS能直接吃进去的数据。这里需要先明确一个基本概念3DGS训练时需要的不是“一张张照片”而是“一组带有精确相机位姿的照片 一个能初始化高斯位置的稀疏点云”。这两个东西从哪来最主流的开源方案就是Colmap。Colmap通过特征提取、特征匹配、增量式重建能够同时估计出每张图像的相机内外参数位姿和场景的稀疏三维点云恰好就是3DGS训练脚本要求的标准输入。换句话说Colmap就是3DGS数据生产链里的“前处理工厂”。这篇博文适合谁两类人一是刚接触3DGS、跑通了官方Demo但想用自己的数据训练却被Colmap的界面和参数弄得一头雾水的初学者二是已经跑过几次Colmap但经常遇到重建失败、点云稀烂、训练效果差等问题想知道问题出在哪的进阶玩家。我会从环境搭建、图像采集规范、Colmap实操、数据格式转换、3DGS训练验证到常见问题的排查完整走一遍流程。这次不是泛泛科普而是把可以照抄的命令、参数和操作步骤全部摆出来。2. 整体设计思路与方案选型2.1 为什么选Colmap而不是其他方案在3DGS生态里生成相机位姿和稀疏点云的工具不止Colmap一个比如还有OpenMVG、COLMAP的替代品GLOMAP以及基于深度学习的位姿估计方案如Relocator、DPT等。但是在3DGS社区里Colmap仍然是最稳妥的默认选择原因很实际官方gaussian-splatting仓库里的convert.py脚本就是针对Colmap的输出格式写的训练脚本也是直接读取Colmap的sparse/0目录。这意味着你用Colmap产出数据几乎不需要写额外的格式转换逻辑。GLOMAP在速度和鲁棒性上确实有优势尤其在图像数量大、场景复杂的情况下GLOMAP的重建速度能比Colmap快一个数量级而且在大场景下不容易漂移。但GLOMAP输出的是它自己的格式需要额外转换而且某些情况下点云质量和Colmap有差异。我的建议是你如果只是想快速验证想法、图像数量少于300张直接用Colmap就够了如果是上千张图的大场景可以考虑GLOMAP生成结果后再转成Colmap格式。3DGS训练脚本的输入数据本质上就三样图像序列、每张图像对应的相机参数内参外参、一个稀疏点云用于初始化高斯分布。Colmap的重建结果天然包含这三样东西。数据结构上Colmap会在输出目录下生成sparse/0/文件夹里面有cameras.bin或.txt、images.bin、points3D.bin三个关键文件这几个文件恰好就是3DGS训练时需要的相机参数和点云来源。图像就是你自己拍的原始照片。所以整个流程的逻辑闭环就是拍照片 → Colmap重建 → 生成稀疏模型 → 喂给3DGS训练。2.2 硬件与软件环境的合理配置在做这个项目之前先把环境理清楚否则后面会到处碰壁。我自己常用的环境配置是这样的组件推荐配置说明操作系统Ubuntu 20.04/22.04Windows也能跑但Linux踩坑少GPUNVIDIA RTX 3060以上显存≥8GB3DGS训练至少需要8GB推荐12GB以上CUDA11.8或12.1需要与PyTorch版本匹配Python3.8-3.103.11部分依赖编译容易出问题Colmap3.8以上版本建议用源码编译或官方Release图像数量50-300张太少重建不稳太多训练时间剧增有一个容易忽略的点Colmap本身也支持GPU加速特征提取和匹配阶段所以显卡性能不只是影响3DGS训练在数据生产阶段同样重要。如果你的显卡在Colmap阶段就能把特征提取速度提升好几倍整个流程会顺畅很多。3DGS训练还有一个隐藏依赖项——diff-gaussian-rasterization这是3DGS官方实现的高斯光栅化器需要在训练前从源码编译。这个编译过程对CUDA版本和PyTorch版本非常敏感很多人的训练跑不起来不是因为数据有问题而是这个子模块编译失败。后面我会专门说怎么正确编译。3. 数据采集决定最终重建质量的第一道关口3.1 图像采集的硬性规范很多人拿到Colmap后直接拍几十张照片就开跑结果重建出来一团糟然后抱怨Colmap不好用。实际上80%的糟糕结果都出在照片采集阶段。Colmap是典型的“看照片吃饭”的算法照片质量直接决定了重建上限后面再怎么调参数都救不回来。我总结了一套比较实用的拍摄规范分享给大家作为参考图像数量室内小物件40-80张室内大场景100-200张室外场景200-300张。不是越多越好而是“在保证覆盖的前提下越精炼越好”。重叠率相邻照片之间的重叠区域至少要60%以上。想象一下你拿着手机围着物体转一圈每次转动角度不要超过15-20度。分辨率建议统一使用2000-4000像素的长边。太高了内存吃紧太低了特征点不够。手机默认拍摄的分辨率通常够用但注意不要开启HDR或夜景模式。光照条件自然光或均匀室内光最好避免强烈的阴影和反光。玻璃、镜面、纯白墙面这类材质是特征提取的重灾区容易导致匹配失败。拍摄轨迹围绕目标物体做圆周运动或者按网格路径移动保证每个面都被覆盖。如果场景里有大面积的无纹理区域比如白墙、纯色地面可以适当贴一些标定板或者纹理丰富的标记物帮助Colmap找到特征点。这一点在做室内场景时特别实用。3.2 图像预处理技巧有些情况下你手里的照片不一定适合直接输入Colmap需要先做一些预处理。最常见的两个问题是图片太大和镜头畸变严重。对于图片太大我习惯先用Python脚本批量resize到合适尺寸再进Colmap。这样不只是为了省显存更重要的是太高的分辨率会导致特征点数量爆炸海量的误匹配反而让重建更慢更不稳定。import cv2 import os from pathlib import Path input_dir Path(raw_images) output_dir Path(input_images) output_dir.mkdir(exist_okTrue) target_long_edge 3200 for img_path in sorted(input_dir.iterdir()): if img_path.suffix.lower() not in [.jpg, .jpeg, .png]: continue img cv2.imread(str(img_path)) h, w img.shape[:2] max_edge max(h, w) if max_edge target_long_edge: scale target_long_edge / max_edge new_w, new_h int(w * scale), int(h * scale) img cv2.resize(img, (new_w, new_h), interpolationcv2.INTER_AREA) cv2.imwrite(str(output_dir / img_path.name), img, [cv2.IMWRITE_JPEG_QUALITY, 95])至于镜头畸变目前的手机和相机在默认设置下畸变通常不大Colmap的相机模型本身也能在重建过程中估计畸变参数所以一般不需要单独做去畸变。除非你用的是广角镜头或者运动相机比如GoPro畸变严重到画面边缘明显弯曲这种情况下建议先用OpenCV或Lightroom做一次去畸变再送入Colmap。4. Colmap完整实操从特征提取到稀疏点云导出4.1 特征提取与匹配的关键参数Colmap有图形界面GUI和命令行两种使用方式。做数据生产这种重复性任务推荐用命令行方便记录参数和复现。下面这套参数是我经过多次实验后觉得比较稳的配置。首先是特征提取colmap feature_extractor \ --database_path database.db \ --image_path input_images \ --ImageReader.single_camera 1 \ --ImageReader.camera_model SIMPLE_RADIAL \ --SiftExtraction.use_gpu 1 \ --SiftExtraction.max_num_features 8192 \ --SiftExtraction.first_octave -1 \ --SiftExtraction.num_octaves 4这里的几个参数值得解释一下。--ImageReader.single_camera 1表示假设所有图片都是用同一个相机拍的这通常成立而且能显著提升匹配质量因为相机内参共享匹配时的几何约束更强。--ImageReader.camera_model SIMPLE_RADIAL是针孔相机模型加一个径向畸变参数适合大多数手机和普通相机。如果你的图像已经预先去过畸变可以用PINHOLE模型。--SiftExtraction.first_octave -1可以让特征提取在放大一倍的图像上进行能提取到更多细粒度特征对于纹理较弱的场景很有帮助。特征匹配用下面的命令colmap exhaustive_matcher \ --database_path database.db \ --SiftMatching.use_gpu 1 \ --SiftMatching.max_num_matches 32768 \ --SiftMatching.guided_matching 1exhaustive_matcher适合图像数量在200张以内的情况它会做全两两匹配效果最稳。超过200张建议参考官方文档改用sequential_matcher或者vocab_tree_matcher否则匹配时间会爆炸。--SiftMatching.guided_matching 1是开启引导匹配用几何约束过滤掉误匹配这个对提升重建成功率很有帮助。如果图像数量较多其实可以跳过exhaustive_matcher的全局匹配改用sequential_matcher配合--SiftMatching.overlap_num参数只匹配相邻若干张图像。这个对于按顺序拍摄的视频帧序列尤其高效。4.2 稀疏重建与模型选择匹配做完之后进入稀疏重建阶段colmap mapper \ --database_path database.db \ --image_path input_images \ --output_path sparse \ --Mapper.min_num_matches 15 \ --Mapper.absolute_pose_min_num_inliers 30 \ --Mapper.init_min_num_inliers 100 \ --Mapper.ba_refine_focal_length 1 \ --Mapper.ba_refine_extra_params 1稀疏重建的输出会在sparse/下生成0/、1/、2/等多个子目录每个子目录对应一个独立的重建模型。如果场景很复杂或者拍照时有断裂Colmap会输出多个模型。这时候用下面命令看一下每个模型的质量图像数量和点云数量colmap model_analyzer \ --path sparse/0选择图像数量最多的那个模型作为主模型。如果每个模型的图像数量都很少比如10张、20张说明拍照轨迹有问题图像之间连贯性不够建议补拍。一个很常见的教训不要在sparse重建后直接就用原始结果。Colmap的重建模型中可能会包含一些外点outlier或者漂浮在场景之外的孤立点云点这些噪声点对3DGS训练会引入不必要的初始化噪声轻则让训练收敛变慢重则让生成的高斯分布在错误位置堆积导致渲染出现飞絮状伪影。建议先做一次点云清洗colmap model_merger \ --input_path1 sparse/0 \ --input_path2 sparse/0 \ --output_path sparse/0_clean不过上面这只是把模型复制一份真正的清洗其实是用model_cleaner来去除孤立点和匹配数过少的点colmap model_cleaner \ --input_path sparse/0 \ --output_path sparse/0_clean \ --min_observations 3 \ --max_reproj_error 4.0--min_observations 3表示每个三维点至少要被3张图像观测到才保留--max_reproj_error 4.0表示去除重投影误差大于4像素的点。这两个参数是我实践下来效果不错的默认值如果你的场景噪声特别大可以适当放宽。5. 从Colmap输出到3DGS训练格式转换与启动训练5.1 把稀疏模型转换为3DGS所需的格式3DGS官方仓库里其实已经自带了一个转换脚本但很多人跑的时候会踩坑。官方训练代码期望的数据结构是data/ ├── images/ # 训练图像 │ ├── 00000.jpg │ ├── 00001.jpg │ └── ... └── sparse/ └── 0/ ├── cameras.bin ├── images.bin └── points3D.bin注意Colmap默认输出的虽然也是sparse/0/结构但里面同时包含.bin和.txt文件取决于你重建时的设置。官方训练代码只认.bin如果你的sparse/0里只有.txt需要先转换成.bin。Colmap自带转换工具colmap model_converter \ --input_path sparse/0 \ --output_path sparse/0 \ --output_type BIN如果你的Colmap版本较老也可以直接删掉.txt文件只保留.bin文件训练代码一样能读。接下来是图像文件的准备。官方训练代码会从data/images目录读取图像然后根据sparse/0/images.bin里记录的图像文件名来匹配。这里有一个容易出错的地方Colmap重建时图像路径是相对于--image_path的如果你的图像文件名或者目录结构变了训练时会报“找不到图像”的错误。所以从采集到训练图像文件名最好一直保持不变。5.2 启动3DGS训练数据集准备好之后训练就比较简单了。官方仓库的train.py是标准入口python train.py \ -s /path/to/your/data \ -m /path/to/output/ \ --iterations 30000 \ --test_iterations 7000 30000 \ --save_iterations 7000 30000 \ --densify_until_iter 15000 \ --densify_grad_threshold 0.0002 \ --sh_degree 3这里面的参数值得逐一说一下。--iterations 30000是默认值大多数场景30000次迭代已经足够如果你的图像质量很好可以减到20000反之如果场景复杂可以加到40000。--densify_until_iter 15000控制高斯点云稠密化的截止迭代数太早停止会导致细节不足太晚则可能过拟合到噪声。--densify_grad_threshold是稠密化的梯度阈值值越小越容易触发稠密化点云增长更快但也更容易产生冗余。我一般从默认的0.0002开始效果不好再调整。这里插一句关于“远→近绘制”和硬件光栅化的细节。3DGS渲染的核心算法本质上是对成千上万个高斯点按深度排序然后从远到近依次进行alpha混合。这个过程在GPU上的光栅化器中实现每一帧都需要对高斯点做排序和混合。远近视点的差异会影响排序的稳定性如果场景深度跨度过大比如既有近处的物体又有很远的背景排序误差会变得明显画面上可能出现闪烁或者漏画。这也是为什么3DGS对相机轨迹的均匀性比较敏感——如果你的照片集中在一小段深度范围内训练出的模型在这个范围内的表现会很好但一旦跳出这个深度范围去渲染新视角质量就会明显下降。所以拍摄时尽量在不同距离、不同高度都取一些照片让场景深度分布更均匀。这个对最终模型在新视角下的泛化能力非常重要。5.3 训练结果的量化评估与可视化训练结束后输出目录下会生成一系列结果文件。除了训练日志和检查点最关键的是test/ours_30000/目录下的渲染结果和评估指标。官方代码会计算PSNR、SSIM、LPIPS三个指标。我自己习惯的做法是先看PSNR如果小于20基本上数据有问题检查Colmap重建是否完整。PSNR在20-26之间属于正常范围比较依赖场景复杂度。纯色墙面区域多的场景PSNR天然会低一些因为像素值本身差异小。再看渲染视频train/ours_30000/video.mp4重点看有没有漂浮的“云雾状”伪影、有没有某个视角下物体形变严重。如果你训练出来的模型在视频里能看到明显的高斯点漂移或者场景抖动大概率是稀疏点云初始化不好或者Colmap的相机位姿不够精确。遇到这种情况回头重新做Colmap重建适当调高--Mapper.ba_refine_focal_length的迭代精度可能比在训练参数上花时间更有效。6. 常见问题与排查技巧实录6.1 问题速查表我把实际操作中遇到的高频问题整理成一个速查表方便各位对照排查问题现象可能原因解决方案Colmap匹配图像很少图像重叠率不足 / 纹理弱补拍照片增加纹理标记物重建出多个模型拍摄轨迹断裂找出断裂位置补拍过渡图像训练时找不到图像文件图像文件名或路径与sparse记录不一致保持文件结构不变检查大小写训练显存溢出OOM图像分辨率过高 / 高斯点数量过大降低分辨率减少初始点云数量PSNR极低且画面模糊照片本身模糊 / 相机位姿错误删掉模糊照片重新做Colmap渲染出现白色飞絮稀疏点云有外点用model_cleaner清洗点云diff-gaussian-rasterization编译失败CUDA与PyTorch版本不匹配重装匹配的CUDA/PyTorch版本新视角渲染效果差照片深度覆盖不均衡从不同距离/高度补拍照片6.2 几个可以大幅提效的小技巧第一在Colmap特征提取时可以用--ImageReader.camera_mask_path指定mask目录把天空、地面等干扰区域遮掉。这个mask是黑色背景、白色有效区域的图片同名匹配到每张图像上。Mask掉大面积天空之后特征匹配的准确率会提升非常多尤其适合户外场景。第二如果你用手持拍摄难免有些照片有运动模糊。不要偷懒直接删掉这些模糊照片。模糊照片产生的特征点位置不精确会拉低整组数据的位姿精度。判断方法很简单在文件管理器里把照片缩略图放大看边缘是否清晰。第三关于3DGS的--sh_degree参数。默认是3对应64个球谐系数用于表达视角相关的颜色。如果你的场景大多是漫反射表面无高光、无金属光泽降低到2甚至1可以加快训练速度且视觉效果差异不大。反过来如果场景里有很多镜面反光的物体保持3或者更高能更好地还原视角高光变化。第四如果你打算用“3DGS硬件混合远→近绘制”这类优化思路来加速渲染那在训练阶段就要注意控制高斯点的总数量。3DGS的渲染耗时会随着高斯点数量线性增长特别是从远到近排序和混合的开销很大。优化的思路通常是把远处的高斯点合并、近处的高斯点细化训练时可以通过调节--densify_grad_threshold和--densify_until_iter来影响最终高斯点分布。我的经验是室内场景控制在50-200万个高斯点渲染帧率比较理想超过300万个点普通消费级GPU实时渲染就会吃力了。7. 写在最后的一点个人体会这套Colmap 3DGS的流程我前后跑了几十次从最开始照片拍得乱七八糟、Colmap重建出一堆碎片模型到现在基本一次跑通。我最想强调的一点是这个流程中真正决定最后效果上限的永远是拍摄环节。Colmap和3DGS只是把你的照片变成模型它们不会创造信息只会利用信息。如果你按这篇博客的采集规范认真拍照后面的过程会格外顺畅如果你随手拍一堆照片就想出好结果那再厉害的参数调优也救不回来。另外补一句关于新方向的观察。最近社区里比较热的“逐像素优化”“硬件混合远近视点绘制”等方向本质上都是在缓解3DGS在大深度跨度、高分辨率场景下的渲染压力。对普通用户来说短期内最可靠的仍然是保证数据质量再考虑渲染优化。等这些优化方案成熟了开源工具链会进一步简化到时候自制数据集的门槛还会更低。但目前这个时间点按最基础、最稳定的流程去操作是效率最高的选择。本文还有配套的精品资源点击获取
返回列表