简介本资源面向计算机视觉与三维重建方向的研究者、开发者及高年级学生提供一套在雨、雾、雪等恶劣天气条件下实现室外场景三维重建的完整项目实战包。核心采用高斯Splatting算法通过高斯核函数的平滑与插值处理有效抑制天气元素对图像质量的干扰提升重建模型的精度与稳定性可应用于城市规划、交通监控、环境监测及灾害现场快速建模等场景。压缩包共37个文件约3MB以24个Python源码文件为主体涵盖训练、渲染、损失计算、相机与数据集读取等模块另含9张png效果图、yml环境配置、sh运行脚本及md说明文档目录结构清晰便于按模块查阅与复现。目前已有275人学习下载。读者可获得可直接运行的算法源码、从数据采集到模型输出的流程教程以及针对恶劣天气的排错与调参思路适合作为三维重建进阶学习与项目落地的参考。1. 恶劣天气下室外三维重建高斯Splatting为什么值得你花时间雨雾天气拍一圈室外场景拿回来看照片挺清楚一跑传统摄影测量或者 NeRF 就露馅雨丝被当成高频纹理、雾让远景对比度塌掉、地面反光让匹配点飘。高斯Splatting3D Gaussian Splatting这两年在三维重建圈子里热度很高核心原因是它把场景表示成一堆带位置、协方差、颜色和透明度的三维高斯球用光栅化而不是体渲染来出图训练和渲染都快了一个量级。但把高斯Splatting直接套到恶劣天气的室外场景上你会发现它并不天然抗雨抗雾——它只是把重建速度提上来了鲁棒性还得自己补。这篇要讲的就是在雨、雾、弱光这类室外条件下怎么用高斯Splatting搭出一条能跑通、能复现、效果还能看的三维重建流程从数据采集、预处理、训练参数到排错一步步落到命令和代码上。适合已经跑过原始3DGS、想把它推到真实室外场景的从业者也适合刚接触三维重建、想找一个完整实战方向入手的新手。源码和流程教程我会按常见工程做法拆开讲重点放在“为什么这么设”和“哪里会翻车”。2. 高斯Splatting在恶劣天气下的原理与选型为什么不是直接上NeRF2.1 高斯Splatting的表示与渲染机制高斯Splatting把场景显式表示为一组三维高斯分布。每个高斯有均值 μ三维位置、协方差 Σ决定椭球形状和朝向、不透明度 α以及球谐系数SH表示视角相关的颜色。渲染时把这些高斯投影到图像平面按深度排序做 alpha 混合得到像素颜色。和 NeRF 的隐式 MLP 不同它是显式点云式的表示梯度直接作用在高斯参数上收敛快、渲染快。协方差矩阵通常拆成 Σ R S Sᵀ RᵀR 是旋转四元数S 是缩放对角阵。这样优化时能保证 Σ 半正定。球谐系数一般用 3 阶共 16 个系数能表达一定的高光变化。这套表示对室外场景的适配点在于它不依赖稠密体采样对纹理弱、对比度低的区域雾天远景不会像 NeRF 那样因为采样不足直接糊掉但前提是初始点云得靠谱。2.2 恶劣天气给重建带来的三类退化雨、雾、弱光对重建的破坏可以归成三类。第一类是高频噪声注入雨丝、雨滴在图像上是随机亮线SfM 会把这些当特征点导致位姿估计抖动。第二类是低频对比度衰减雾和霾让远处物体对比度下降暗通道先验失效深度估计偏浅。第三类是光照不一致雨天云层散射光让同一物体在不同视角下颜色差异大球谐系数拟合会过拟合到某几个视角。这三类退化里第一类靠预处理能压住大半第二类需要深度先验或去雾补偿第三类只能靠训练时的正则和视角均衡。选高斯Splatting而不是 NeRF主要看中它的训练速度——室外场景动辄几百张图NeRF 训几天3DGS 几十分钟到几小时能出结果迭代调参的成本低得多。但代价是它对初始点云和位姿精度更敏感位姿一飘高斯球就散成一片。2.3 整体流程与工具链选型常见做法是COLMAP 做 SfM 拿位姿和稀疏点云 → 预处理去雨去雾 → 用稀疏点云初始化高斯 → 训练 3DGS → 导出 ply 做后处理。工具链上3DGS 官方实现graphdeco-inria/gaussian-splatting是基线室外场景建议配一个去雨网络如 Restormer 或 MPRNet 的预训练权重和去雾模块暗通道或 AOD-Net。COLMAP 用 3.8 以上版本CUDA 11.8 配 PyTorch 2.0 以上比较稳。提示不要一上来就换自定义 CUDA 算子先把官方实现跑通确认位姿和点云没问题再动渲染管线。3. 数据采集与预处理把雨雾从输入里剥掉3.1 采集参数与拍摄策略室外恶劣天气采集核心是保证重叠率和曝光一致。建议相邻视角重叠 70% 以上绕场景走两圈一圈平视一圈略俯避免只拍一个高度导致高斯球在垂直方向塌陷。曝光用手动模式固定 ISO 和快门避免自动曝光让不同帧亮度跳变。雨天拍摄尽量选雨势小的间隙或者用偏振镜压掉部分反光。分辨率不要超过 1920×1080太高 COLMAP 匹配慢且容易过拟合噪声。如果只能拍到雨雾很重的素材采集时多拍近景细节远景靠去雾补。快门速度建议 1/250 以上减少雨丝拖影。每张照片记录 GPS 或至少记录拍摄顺序方便后续检查位姿连续性。3.2 去雨去雾预处理脚本预处理用 Python 调预训练模型下面是一个去雨的最小示例基于 Restormer 的推理接口实际使用时替换成你本地权重路径。import torch import cv2 import numpy as np from restormer import Restormer # 假设已按官方仓库搭好模型定义 # 加载去雨权重权重文件放本地不要在线拉 model Restormer() state torch.load(./weights/restormer_derain.pth, map_locationcpu) model.load_state_dict(state) model model.cuda().eval() def derain_image(img_path, out_path): img cv2.imread(img_path) # BGR img cv2.cvtColor(img, cv2.COLOR_BGR2RGB) tensor torch.from_numpy(img).float().permute(2,0,1).unsqueeze(0) / 255.0 tensor tensor.cuda() with torch.no_grad(): out model(tensor) # 输出同尺寸 out out.squeeze(0).permute(1,2,0).cpu().numpy() out np.clip(out * 255.0, 0, 255).astype(np.uint8) cv2.imwrite(out_path, cv2.cvtColor(out, cv2.COLOR_RGB2BGR)) if __name__ __main__: derain_image(./raw/frame_001.jpg, ./clean/frame_001.jpg)这段代码的逻辑是读图转 RGB、归一化到 [0,1]、送进网络、输出再转回 uint8 存盘。参数上输入尺寸建议保持原图Restormer 对尺寸不敏感但太大显存吃紧可以切成 512×512 的块再拼。去雾可以用暗通道先验做快速版或者 AOD-Net暗通道的窗口半径设 15、omega 设 0.95 是常用值。注意去雨去雾会引入伪影如果伪影比雨本身还重宁可不去靠训练时的鲁棒损失扛。预处理后一定要人工抽检 10% 的图确认没有把细节抹掉。3.3 COLMAP位姿估计与稀疏点云导出预处理完的图送 COLMAP。命令行流程如下colmap feature_extractor \ --database_path ./colmap/database.db \ --image_path ./clean \ --ImageReader.single_camera 1 \ --SiftExtraction.max_num_features 8192 colmap exhaustive_matcher \ --database_path ./colmap/database.db \ --SiftMatching.guided_matching 1 colmap mapper \ --database_path ./colmap/database.db \ --image_path ./clean \ --output_path ./colmap/sparse colmap model_converter \ --input_path ./colmap/sparse/0 \ --output_path ./colmap/sparse/0/points.ply \ --output_type PLYsingle_camera 1表示所有图共用内参室外同一设备拍摄时开这个能减少自由度。max_num_features 8192提高特征数雾天纹理弱时有用。guided_matching 1在匹配阶段用几何引导能压掉一部分雨丝造成的误匹配。mapper 输出后检查sparse/0里的相机数和注册率注册率低于 80% 说明位姿估计有问题回去查重叠率和去雨效果。4. 训练高斯Splatting参数怎么设、损失怎么调4.1 从稀疏点云初始化高斯3DGS 官方实现用 COLMAP 的稀疏点云初始化高斯位置颜色用 SH 的 0 阶即 RGB 均值初始化缩放用最近邻距离估计。室外场景点云稀疏建议把初始点云做一次统计滤波去掉离群点否则离群点会变成漂浮的高斯球。import open3d as o3d pcd o3d.io.read_point_cloud(./colmap/sparse/0/points.ply) # 统计滤波每个点看 20 个邻居标准差倍数 2.0 cl, ind pcd.remove_statistical_outlier(nb_neighbors20, std_ratio2.0) o3d.io.write_point_cloud(./colmap/sparse/0/points_filtered.ply, cl)nb_neighbors设 20 是平衡速度和效果点云大可以降到 10。std_ratio越小去得越狠2.0 是常用起点雾天点云噪声大可以降到 1.5。滤波后点数会掉 10% 到 30%正常。4.2 训练命令与关键参数官方训练入口是train.py室外场景常用参数如下python train.py \ -s ./data/outdoor_rain \ -m ./output/outdoor_rain \ --iterations 30000 \ --position_lr_init 0.00016 \ --position_lr_final 0.0000016 \ --densify_until_iter 15000 \ --densify_grad_threshold 0.0002 \ --opacity_reset_interval 3000 \ --white_background 0iterations 30000是官方默认室外场景可以加到 40000 但收益递减。position_lr_init和final控制高斯位置学习率室外大场景可以适当调大初始值加快收敛。densify_until_iter 15000表示 15000 步后停止增密雾天噪声多的话可以提前到 10000避免高斯球被噪声撑爆。densify_grad_threshold是增密梯度阈值调小会增更多高斯显存吃紧就调大。opacity_reset_interval 3000定期重置不透明度防止高斯球在雾区堆积。提示white_background 0在室外场景必须设 0否则背景会被当成白色天空区域重建会发灰。4.3 针对雨雾的损失与正则调整官方损失是 L1 加 D-SSIM权重 0.8 和 0.2。恶劣天气下建议加两项一是对远景区域加深度平滑正则二是对高不透明度高斯加稀疏正则。深度平滑可以用 COLMAP 的稀疏深度做弱监督稀疏正则直接对 α 加 L1。# 在 train.py 的 loss 计算处插入 loss_l1 l1_loss(rendered, gt) loss_dssim 1.0 - ssim(rendered, gt) loss_sparse 1e-4 * torch.mean(torch.abs(gaussians.get_opacity)) total_loss 0.8 * loss_l1 0.2 * loss_dssim loss_sparse1e-4是稀疏正则权重太大会让高斯球变透明导致画面发虚建议从 1e-5 试起。深度平滑需要额外读 COLMAP 深度图实现复杂如果位姿够准可以跳过。训练时盯loss曲线如果 5000 步后还在 0.1 以上多半是位姿或去雨没做好。5. 避坑与排查室外恶劣天气重建的五个血泪教训5.1 现象高斯球在雾区糊成一团远景全白原因雾天图像对比度低COLMAP 在远景匹配不到足够特征点稀疏点云在远处几乎为空高斯球只能靠增密硬撑结果在雾区堆出一片低透明度高斯。解决去雾预处理必须做且去雾后重新跑 COLMAP训练时把densify_until_iter降到 10000减少雾区增密必要时手动在远景补一些点云。5.2 现象雨丝被重建成立体线条画面出现悬浮细丝原因去雨不彻底残留雨丝在 SfM 里被当成特征生成对应的高斯球。解决去雨网络换更强的权重或者对去雨后图像做一次中值滤波3×3压掉细线COLMAP 匹配时开guided_matching并提高max_num_features让真实特征压过雨丝。5.3 现象训练到 10000 步后 loss 突然跳升画面出现大片黑斑原因opacity_reset_interval触发时部分高斯球不透明度被重置如果此时增密还在进行新老高斯混在一起导致渲染不稳定。解决把opacity_reset_interval设成 5000 或干脆关掉设很大等增密结束后再重置或者把densify_until_iter和重置间隔错开。5.4 现象同一场景不同视角颜色差异大球谐系数过拟合原因雨天光照不一致球谐系数为了拟合每个视角的颜色把高频变化学进去了换视角就崩。解决降低球谐阶数到 1 阶或 0 阶牺牲一点视角相关效果换稳定性训练时对颜色加 TV 正则或者把曝光不一致的帧剔除。5.5 现象显存爆掉训练到一半 OOM原因室外场景高斯数量容易冲到几百万加上去雨模型占显存。解决训练前把去雨模型挪到 CPU 或单独跑3DGS 训练时把densify_grad_threshold调大如 0.0004限制高斯数量分辨率降到 1600×900 以下用--resolution 2降采样。6. 进阶技巧用深度先验和分块训练把室外场景做扎实室外恶劣天气重建想再上一个台阶单靠 3DGS 官方管线不够得补深度先验和分块策略。深度先验可以用单目深度估计模型如 Depth Anything 或 MiDaS生成稠密深度图和 COLMAP 稀疏深度做一致性检查把不一致的区域标记出来训练时对这些区域降权。具体做法是对每张图跑深度估计得到相对深度再用 COLMAP 的稀疏点做尺度对齐对齐后算每个像素的深度置信度置信度低于阈值的像素在 L1 损失里乘 0.3。分块训练针对大场景。把场景按 COLMAP 相机位置聚成若干块每块单独训一个 3DGS最后用块间重叠区域做对齐合并。合并时用 ICP 对齐点云再统一球谐系数。这样单块显存可控且每块可以单独调参。分块数量按场景大小定一般 4 到 8 块块间重叠 20% 以上。验证方法上除了看 PSNR/SSIM室外场景更该看几何一致性用留出的测试视角渲染深度图和激光或深度先验比看边缘是否对齐。我一般会抽 5 个视角做人工检查重点看地面和建筑边缘有没有漂浮高斯。下面是一个深度置信度加权的损失片段# depth_prior: 单目深度对齐后的深度图, conf: 置信度图 def weighted_l1(rendered, gt, conf): diff torch.abs(rendered - gt) return torch.mean(diff * conf) # conf 低于阈值的像素权重已置 0.3 loss weighted_l1(rendered, gt, conf) 0.2 * (1.0 - ssim(rendered, gt))conf的生成是关键对齐尺度用最小二乘拟合scale * mono_depth shift sparse_depth拟合残差大的像素置信度低。这套做法我踩过的坑是单目深度在雾天本身就不准置信度会整体偏低这时候阈值要放宽否则有效像素太少损失没梯度。最后说个习惯每次改完预处理或训练参数先跑 3000 步看 loss 和渲染图别一上来就 30000 步省下来的时间够你多试三组参数。室外恶劣天气重建没有银弹去雨、去雾、位姿、增密、正则每个环节都得盯。希望帮到你。本文还有配套的精品资源点击获取