无人机航拍三维重建Python源码实战:COLMAP位姿与NeRF深度图

发布时间:2026/10/12 15:59:16
无人机航拍三维重建Python源码实战:COLMAP位姿与NeRF深度图
简介本资源面向计算机、人工智能、自动化等专业的在校学生与开发者提供一套基于无人机航拍数据的三维场景重建完整项目源码可用于毕业设计、课程大作业或项目初期立项演示。项目围绕多角度地面图像采集、COLMAP位姿估计与Behindthescenes深度图生成构建数据集并给出训练与测试脚本覆盖数据预处理、模型训练、位姿评估与三维渲染等环节。压缩包共54个文件以41个Python源码为核心辅以3个yaml配置、2个ipynb笔记本、2个txt说明及png、mp4、gif等可视化结果整体约20.65MB目录结构清晰便于按模块阅读与二次开发。目前已有776人学习下载。读者可据此掌握从航拍数据到三维重建的完整流程理解深度估计、轨迹对齐与ATE评估等关键实现并可在现有代码基础上修改扩展完成自己的课题或作业。1. 无人机航拍三维重建从一份能跑通的 Python 源码包说起手头有一批无人机航拍图想重建出带纹理的三维场景还要能算体积、出正射影像这事听起来像要攒一整套摄影测量流水线。实际上这份「基于无人机航拍数据的三维场景重建 python 源码 项目说明 无人机数据集.zip」把链路拆得比较清楚用 COLMAP 估位姿当基准用 Behind the Scenes 那套思路拿深度图再喂给一个带畸变建模的 NeRF 类网络训练最后在 evaluation 和 scripts 里做位姿误差、正射投影、体积计算。它适合计算机、人工智能、自动化方向的在校生做毕业设计或课程大作业也适合想快速摸清「航拍图怎么变成三维场景」这条链路的工程师。下面按我拆包复现的顺序讲重点放在参数、命令和那些不跑一遍根本不知道的坑上。2. 拆包先看结构数据流、模块划分与依赖关系2.1 目录里藏着一条完整流水线把压缩包解开根目录大致分四块。第一块是轨迹评估工具align_trajectory.py、transformations.py、trajectory_utils.py、align_utils.py、compute_trajectory_errors.py、results_writer.py这几个文件配合utils_poses/lie_group_helper.py、vis_cam_traj.py、align_traj.py、comp_ate.py负责把估计轨迹和 COLMAP 基准对齐并算 ATE。第二块是数据预处理preprocess/dpt_depth.ipynb、dpt_depth.py、get_log_to_txt.py以及configs/Tanks/wurenji.yaml、preprocess2.yaml、default.yaml。第三块是模型本体model/下的network.py、training.py、losses.py、distortions.py、intrinsics.py、poses.py、official_nerf.py、rendering.py、checkpoints.py、extracting_images.py、eval_images.py、eval_pose_one_epoch.py加上dataloading/的dataset.py、dataloading.py、common.py、configloading.py。第四块是评估与脚本evaluation/eval.py、eval_poses.pyscripts/下的get_orthographic_by_arcgis.ipynb、get_depth.py、get_volume.py、get_volume2.py、get_matrix_by_sfm.py、get_volume_by_surface_reconstruction.py。third_party/pytorch_ssim是图像质量评估依赖results/里放了wuren_test.png、wurenji_small_resolution.mp4、正射投影.png、mountain2.gif、gaoqing.mp4这些结果样例。这条链路的核心逻辑是COLMAP 给出相机内外参作为「真值基准」Behind the Scenes 风格的方法从航拍图里估计深度网络在训练时同时优化颜色和深度最后用轨迹对齐脚本量化位姿精度。理解了这个数据流后面调参和排错才有方向。2.2 环境依赖与版本约束项目是纯 Python 实现深度学习部分依赖 PyTorch图像和位姿处理依赖 NumPy、OpenCV、SciPySSIM 用的是third_party里自带的 pytorch_ssim。dpt_depth.py用到了 DPT 深度估计模型需要单独装对应权重。常见做法是建一个干净的 conda 环境Python 3.8 到 3.10 之间比较稳PyTorch 选 1.12 以上带 CUDA 的版本。装依赖时先把torch、torchvision按官方命令装好再补numpy、opencv-python、scipy、matplotlib、tqdm、pyyaml。pytorch_ssim不用 pip 装直接把third_party/pytorch_ssim加进sys.path或按项目里的 import 路径引用即可。# 建环境Python 版本别太新3.8~3.10 兼容性最好 conda create -n uav3d python3.9 -y conda activate uav3d # 按自己 CUDA 版本装 PyTorch这里以 cu118 为例 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 # 其余依赖 pip install numpy opencv-python scipy matplotlib tqdm pyyaml参数说明python3.9是经验值太新的 3.12 容易在编译扩展时翻车PyTorch 的 index-url 要和自己显卡驱动匹配装完用python -c import torch; print(torch.cuda.is_available())验证返回True才算通。这一步不通后面训练全是 CPU 硬扛基本没法看。2.3 配置文件怎么读configs/Tanks/wurenji.yaml是主训练配置preprocess2.yaml管预处理default.yaml是默认参数底座。打开wurenji.yaml重点看几个字段数据根目录、图像分辨率、训练轮数、学习率、深度损失权重、畸变参数开关。dataloading/configloading.py负责把这些 yaml 解析成运行时对象dataloading/common.py里通常放着路径拼接和数据集划分逻辑。改配置时不要直接动default.yaml在wurenji.yaml里覆盖对应键这样换数据集时只改一个文件。提示yaml 对缩进敏感用空格不要用 Tab改完先用python -c import yaml; yaml.safe_load(open(configs/Tanks/wurenji.yaml))过一遍语法能省掉很多「配置没生效」的玄学排查。3. 数据准备与预处理COLMAP 位姿、深度图与数据集组织3.1 用 COLMAP 估位姿作为训练基准项目说明里写得很直白先拿地面多角度图片用 COLMAP 估计位姿作为模型训练的一个基准。这一步是整个重建的地基位姿不准后面网络再强也白搭。常见做法是把航拍图按images/放好跑 COLMAP 的 feature extractor、matcher 和 mapper导出cameras.txt、images.txt、points3D.txt。项目里scripts/get_matrix_by_sfm.py就是用来从 SfM 结果里提取相机矩阵的utils_poses/lie_group_helper.py则提供李群李代数转换方便后续对齐。# COLMAP 命令行典型流程具体路径按自己数据改 colmap feature_extractor \ --database_path ./colmap.db \ --image_path ./images \ --ImageReader.single_camera 1 colmap exhaustive_matcher --database_path ./colmap.db colmap mapper \ --database_path ./colmap.db \ --image_path ./images \ --output_path ./sparse参数说明--ImageReader.single_camera 1表示所有图共用一台相机内参无人机同一镜头拍的一般都这么设exhaustive_matcher适合图片数量不多几百张以内的情况图多了换成sequential_matcher更快。跑完检查sparse/0/下三个 txt 是否齐全points3D.txt点数太少说明匹配质量差得回头看看是不是重叠度不够或者光照变化太大。3.2 Behind the Scenes 思路拿深度图项目说明提到「通过 Behind the Scenes 算法来获得航拍图像的深度图」对应代码在preprocess/dpt_depth.py和dpt_depth.ipynb。DPT 是密集预测 Transformer用来做单目深度估计输出和原图同分辨率的深度图。get_log_to_txt.py负责把训练日志转成文本方便记录。深度图的质量直接决定网络学到的几何是否合理所以这一步别图快分辨率尽量保持原图级别。# preprocess/dpt_depth.py 的核心调用逻辑示意按实际接口调整 import torch from dpt_depth import load_dpt_model, infer_depth model load_dpt_model(ckpt_pathweights/dpt_hybrid.pth, devicecuda) depth infer_depth(model, image_pathimages/0001.jpg, target_size(1080, 1920)) # depth 是归一化后的相对深度保存时按项目约定命名 save_depth(depth, depths/0001.npy)逻辑说明load_dpt_model加载 DPT 权重infer_depth做前向推理并把输出 resize 回原图尺寸。参数上target_size要和训练配置里的分辨率一致否则深度图和 RGB 对不齐训练时 loss 会异常震荡。保存格式项目里用的是.npy方便dataloading/dataset.py直接np.load读取。3.3 数据集目录组织与划分无人机数据集含深度图按项目说明是单独放在网盘里的下载后要和代码里的路径对上。典型组织方式是data/wurenji/images/放原图data/wurenji/depths/放深度图data/wurenji/sparse/放 COLMAP 结果data/wurenji/poses/放提取好的位姿。dataloading/dataset.py会按配置里的data_root去拼这些子目录dataloading/common.py里通常有 train/val 划分逻辑。目录内容对应代码images/航拍原图dataset.py 读取 RGBdepths/DPT 深度图 .npydataset.py 读取深度监督sparse/COLMAP 三个 txtget_matrix_by_sfm.py 解析poses/提取后的位姿矩阵poses.py 加载注意路径里尽量别带中文和空格Windows 下解压出来的中文目录名经常让cv2.imread返回 None排查半天以为是代码问题其实是路径编码的锅。4. 训练与评估train.py 跑通、eval.py 验证与 ATE 对齐4.1 启动训练与关键参数项目说明给的训练命令是python train.py configs/Tanks/wurenji.yaml。train.py会读配置、建 dataset、实例化model/network.py里的网络、挂上model/losses.py的损失然后进model/training.py的训练循环。model/distortions.py处理镜头畸变model/intrinsics.py管内参model/poses.py管位姿model/rendering.py做体渲染model/checkpoints.py负责存盘。# 训练建议先小分辨率跑通再放大 python train.py configs/Tanks/wurenji.yaml # 训练日志会写到 loss.txt方便画曲线 tail -f loss.txt参数说明配置里learning_rate一般从 5e-4 起太大 loss 直接飞太小收敛慢到怀疑人生num_epochs看数据量几百张图通常几十到上百轮深度损失权重depth_loss_weight是调重建几何质量的关键调大几何更准但颜色可能发糊调小反之。loss.txt和psnr.txt是项目自带的日志文件训练时会被追加写入用matplotlib画出来能直观看到收敛情况。4.2 测试与图像质量评估训练完按项目说明跑python evaluation/eval.py configs/Tanks/wurenji.yaml。evaluation/eval.py会加载 checkpoint在测试视角上渲染图像eval_images.py算 PSNR 和 SSIMeval_poses.py和eval_pose_one_epoch.py评估位姿精度。third_party/pytorch_ssim在这里派上用场。results/里的wuren_test.png、wurenji_small_resolution.mp4就是渲染结果样例可以拿来和自己跑出来的对比。# evaluation/eval.py 里图像指标计算的核心逻辑示意 from third_party.pytorch_ssim import ssim import torch def compute_metrics(rendered, gt): mse torch.mean((rendered - gt) ** 2) psnr 10 * torch.log10(1.0 / mse) ssim_val ssim(rendered.unsqueeze(0), gt.unsqueeze(0)) return psnr.item(), ssim_val.item()逻辑说明PSNR 基于 MSE 算对亮度敏感SSIM 看结构相似度更贴近人眼。两个指标一起看PSNR 高但 SSIM 低往往是渲染整体偏亮或偏暗但结构还行。参数上注意输入要归一化到 [0,1]否则 PSNR 数值会离谱。4.3 轨迹对齐与 ATE 计算这是这个项目比较硬核的一块。align_trajectory.py、align_utils.py、trajectory_utils.py、compute_trajectory_errors.py、results_writer.py配合utils_poses/align_traj.py、comp_ate.py把网络估计的相机轨迹和 COLMAP 基准对齐算绝对轨迹误差 ATE。transformations.py提供四元数、旋转矩阵、欧拉角互转lie_group_helper.py提供 SE3 上的操作。# 对齐轨迹并算 ATE python align_trajectory.py \ --est_poses poses/estimated.txt \ --gt_poses poses/colmap_gt.txt \ --output results/ate_result.txt # 可视化相机轨迹 python utils_poses/vis_cam_traj.py --pose_file poses/estimated.txt参数说明--est_poses是网络输出的位姿--gt_poses是 COLMAP 基准两者坐标系可能差一个相似变换align_trajectory.py会先做 Umeyama 对齐再算误差。ATE 的 RMSE 越小越好一般对齐后能到厘米级说明位姿估计靠谱。vis_cam_traj.py画出来的轨迹图能直观看出估计轨迹和真值是否贴合results/里的可视化样例可以对照。5. 避坑与排查那些不跑一遍不知道的坑5.1 现象训练 loss 一直不降PSNR 卡在十几原因最常见是深度图和 RGB 没对齐或者 COLMAP 位姿坐标系和网络假设的坐标系不一致。dataloading/dataset.py读深度时如果 resize 方式和 RGB 不一致监督信号就是错的。解决先单独可视化一对 RGB 和深度图确认边缘对齐再检查poses.py里位姿的坐标系约定是相机到世界还是世界到相机和 COLMAP 导出的images.txt对齐。项目里get_matrix_by_sfm.py就是干这个的别跳过。5.2 现象eval.py 报 checkpoint 找不到或 key 不匹配原因model/checkpoints.py存盘时的 key 和加载时的网络结构对不上通常是改了network.py后没重新训练或者配置里checkpoint_path指到了旧文件。解决确认configs/Tanks/wurenji.yaml里的 checkpoint 路径指向最新训练产物加载时用strictFalse先看哪些 key 缺失缺的是不是关键层。改过网络结构就老老实实重训别指望旧权重能直接套。5.3 现象COLMAP 跑完 points3D 只有几十个点原因航拍图重叠度不够或者exhaustive_matcher在纹理重复区域比如大片农田、水面匹配失败。解决提高航拍重叠率到 70% 以上或者换sequential_matcher并调--SequentialMatching.overlap。纹理弱的区域可以先用get_depth.py的深度先验辅助但根本还是拍摄时保证重叠和纹理。5.4 现象scripts 里的体积计算脚本结果离谱原因get_volume.py、get_volume2.py、get_volume_by_surface_reconstruction.py依赖重建出的表面网格或点云如果深度尺度没对齐到真实尺度体积就是错的。解决先用get_matrix_by_sfm.py把尺度对齐到 COLMAP 基准再跑体积计算。get_orthographic_by_arcgis.ipynb出正射投影时也要确认地理参考不然正射投影.png那种结果只能看个形状量不了实际距离。5.5 现象显存不够训练中途 OOM原因wurenji.yaml里分辨率设太高或者 batch size 太大model/rendering.py的体渲染采样点数多时显存吃得很凶。解决先把分辨率降到wurenji_small_resolution.mp4那个级别跑通再逐步放大rendering.py里的采样数num_samples和num_importance可以适当调小用精度换显存。实在不够就减 batch size梯度累积补回来。6. 进阶玩法正射投影、体积计算与结果验证的实操技巧把训练和评估跑通只是及格线这份资源真正有意思的是scripts/里那套下游应用。get_orthographic_by_arcgis.ipynb用 ArcGIS 出正射投影get_volume.py和get_volume2.py算体积get_volume_by_surface_reconstruction.py走表面重建路线算体积get_depth.py单独抽深度。我一般会按「先验证几何尺度再算量」的顺序走因为体积和正射对尺度误差极其敏感尺度差 1%体积就差 3%。验证方法上拿results/正射投影.png和results/mountain2.gif当参照自己跑出来的正射图先叠到原航拍图上看地物边缘是否重合。重合了再量已知尺寸的地物比如一段已知长度的跑道或建筑反推尺度系数。这一步用get_matrix_by_sfm.py输出的矩阵做基准最稳。# 体积计算前的尺度校验思路示意 import numpy as np def check_scale(recon_points, known_distance, p1_idx, p2_idx): d_recon np.linalg.norm(recon_points[p1_idx] - recon_points[p2_idx]) scale known_distance / d_recon print(f尺度系数: {scale:.6f}) return scale # 用已知地物两点距离反推尺度再乘到所有重建点上 scale check_scale(points, known_distance50.0, p1_idx100, p2_idx250) points_scaled points * scale逻辑说明known_distance是实地量出来的两点距离p1_idx、p2_idx是重建点云里对应的点索引。算出的scale乘到整个点云上体积计算才有物理意义。参数上known_distance越准尺度越可靠建议选两个在图像里清晰、实地好量的点。提示get_volume2.py和get_volume.py的区别通常在积分方式或表面重建策略上跑之前先看两个脚本的 docstring 或注释选适合自己数据密度的那版别两个混着用。从那以后我每次拿到这类重建结果都强制先走一遍「尺度校验 → 正射叠图 → 体积复算」三步少一步后面全是后悔药。这份资源把训练、评估、下游脚本都配齐了按上面的顺序拆一遍基本能把无人机航拍三维重建这条链路摸透。希望帮到你。本文还有配套的精品资源点击获取