
简介本资源面向计算机、人工智能、自动化等专业的在校学生与教师以及从事三维重建方向的技术人员提供一套基于无人机航拍数据的三维场景重建Python实现方案可作为毕业设计、课程设计或项目立项的参考。压缩包共54个文件约20.66MB以41个Python源码为核心辅以yaml配置、ipynb实验笔记、txt说明及png、mp4、gif等结果展示文件覆盖数据加载、模型网络、损失函数、位姿估计与评估等模块。数据集建设流程完整包含多角度地面图片采集、colmap位姿估计、Behindthesences深度图生成并附百度网盘无人机数据集下载方式。训练与测试入口清晰通过train.py与evaluation/eval.py配合Tanks配置即可复现results目录提供正射投影与重建效果预览。目前已有149人学习适合希望快速上手NeRF类三维重建并在此基础上二次开发的学习者。1. 无人机航拍三维重建这套 Python 源码到底能不能直接跑通如果你手头正好有一批无人机倾斜摄影的图片想从零搭出一套能训练、能评估、能出深度图和正射投影的三维重建流程那这套「基于无人机航拍数据的三维场景重建 Python 实现源码 数据集 部署说明」值得先拆开看看。它不是单纯丢一个 NeRF 脚本给你而是把数据预处理、位姿估计、深度图生成、训练、ATE 轨迹对齐、PSNR 评估、正射投影和体积计算串成了一条完整链路。对做毕业设计、课程设计或者项目初期立项演示的人来说最怕的是代码跑不通、缺依赖、缺数据、缺说明这套资源把train.py、evaluation/eval.py、configs/Tanks下的 yaml 配置、preprocess里的深度处理 notebook 都放进来了还附了使用说明.txt和结果图。适合谁计算机、人工智能、通信、自动化方向的在校学生和刚接触三维重建的工程师前提是你愿意先花时间把 COLMAP、PyTorch 环境和数据路径这三件事理清楚。2. 从航拍图到可训练数据COLMAP 位姿与深度图预处理链路2.1 为什么不能直接拿原图去训 NeRF无人机拍回来的图本质是一堆没有空间关系的 JPG。NeRF 类方法训练时需要每张图的相机内参、外参和对应的深度先验否则网络根本不知道这张图是从哪个角度拍的、场景尺度有多大。资源里preprocess目录下的dpt_depth.ipynb和dpt_depth.py就是干这个的用单目深度估计模型给每张航拍图生成深度图再配合 COLMAP 估计出来的位姿构成训练样本。get_matrix_by_sfm.py和get_depth.py则负责把 SfM 结果和深度结果整理成网络能读的格式。常见做法是先用 COLMAP 做一遍稀疏重建导出cameras.txt、images.txt、points3D.txt再用脚本转成 NeRF 常用的transforms.json或类似结构。这一步没做好后面训练 loss 不降、PSNR 上不去基本都是这里埋的雷。2.2 COLMAP 跑完后的目录该长什么样资源里没有把 COLMAP 命令写死但按get_matrix_by_sfm.py的读取逻辑你至少需要准备一个标准的 COLMAP 稀疏重建输出目录。我一般会这样组织# 假设原始航拍图放在 data/wurenji/images # COLMAP 稀疏重建输出放在 data/wurenji/sparse/0 data/wurenji/ ├── images/ # 原始航拍图命名建议无中文、无空格 ├── sparse/ │ └── 0/ │ ├── cameras.txt │ ├── images.txt │ └── points3D.txt └── depth/ # dpt_depth.py 生成的深度图与 images 同名get_matrix_by_sfm.py会去读sparse/0下的三个文件把每张图的旋转矩阵、平移向量和内参提取出来。参数上要特别注意images.txt里的四元数顺序COLMAP 用的是QW QX QY QZ而很多 Python 库默认QX QY QZ QW顺序反了相机轨迹会飞到天上去。transformations.py和lie_group_helper.py里封装了四元数转旋转矩阵、SE3 插值这些操作建议先单独跑一遍小脚本验证位姿方向别等训练完才发现相机全在场景外面。2.3 深度图生成dpt_depth.py 怎么接进流程dpt_depth.py和dpt_depth.ipynb是这套资源里比较实用的部分。它调用 DPT 类模型对每张航拍图做单目深度估计输出和原图同名的深度图。实际操作时我一般会先确认输入图片的尺寸和模型输入尺寸是否匹配不匹配就做 resize但 resize 后要同步修改内参否则深度和位姿对不上。代码里通常会有类似这样的调用逻辑# dpt_depth.py 中常见的处理流程 import cv2 import numpy as np from transformers import DPTImageProcessor, DPTForDepthEstimation processor DPTImageProcessor.from_pretrained(Intel/dpt-large) model DPTForDepthEstimation.from_pretrained(Intel/dpt-large) image cv2.imread(data/wurenji/images/DJI_0001.JPG) image cv2.cvtColor(image, cv2.COLOR_BGR2RGB) inputs processor(imagesimage, return_tensorspt) outputs model(**inputs) depth outputs.predicted_depth.squeeze().cpu().numpy() # 深度图归一化后保存文件名与原始图保持一致 depth_norm (depth - depth.min()) / (depth.max() - depth.min() 1e-8) cv2.imwrite(data/wurenji/depth/DJI_0001.png, (depth_norm * 255).astype(np.uint8))这里的关键参数是predicted_depth的输出尺度。单目深度是相对深度不是真实米制距离所以后面get_volume.py和get_volume2.py做体积计算时必须用 COLMAP 的稀疏点云或者已知地面控制点做尺度对齐。如果你直接拿相对深度去算体积结果只能看个趋势不能当真实数据用。get_volume_by_surface_reconstruction.py走的是另一条路用表面重建结果算体积适合对精度要求更高的场景。3. 训练与评估train.py 配置项、PSNR 与 ATE 轨迹误差怎么读3.1 configs/Tanks 下的 yaml 到底改了哪些东西资源里给了configs/Tanks/preprocess2.yaml和default.yaml训练命令是python train.py configs/Tanks/wurenji.yaml。虽然 wurenji.yaml 没在文件列表里单独出现但按 Tanks 目录的命名习惯它大概率是从preprocess2.yaml或default.yaml复制修改来的。我一般会重点看这几项配置项常见值作用data_dirdata/wurenji指向 images、sparse、depth 的根目录batch_size1 或 2航拍图分辨率高显存不够就降到 1num_epochs20 到 50小场景 20 轮左右能看出趋势learning_rate5e-4 到 1e-3太大 loss 震荡太小收敛慢near/far0.1 / 10.0深度采样范围要按场景尺度调use_depthTrue是否启用深度监督资源里默认应该是开的configloading.py和common.py负责解析这些 yamltraining.py里是训练主循环。如果你发现训练一开始 loss 就是 NaN先查near和far是不是设成了 0 或者负数再查深度图里有没有全黑或全白的异常样本。3.2 训练命令与断点续跑训练入口很直接# 在项目根目录下执行 python train.py configs/Tanks/wurenji.yaml但实际跑的时候我建议加两个习惯第一先把batch_size设成 1 跑通一个 epoch确认数据加载、深度读取、位姿变换都没报错再往上加第二checkpoints.py里通常有保存和加载逻辑如果训练中断看看能不能从results或checkpoints目录恢复。资源里results目录下有wuren_test.png、wurenji_small_resolution.mp4、正射投影.png、mountain2.gif、gaoqing.mp4这些是作者跑出来的参考结果你可以拿自己的输出和它们对比快速判断是训练没收敛还是渲染代码有问题。3.3 PSNR 和 ATE两个评估指标别混着看psnr.txt和loss.txt是训练过程的记录文件evaluation/eval.py和eval_poses.py负责测试。PSNR 衡量的是渲染图像和真实图像的像素级差异数值越高说明画面越像。但三维重建光看 PSNR 不够因为相机轨迹可能整体偏了画面依然能对上。这时候就要看 ATE也就是绝对轨迹误差。资源里ATE目录下的align_trajectory.py、compute_trajectory_errors.py、align_utils.py、trajectory_utils.py就是专门算这个的。comp_ate.py和align_traj.py提供了对齐和比较的入口。常见做法是先用align_trajectory.py把估计轨迹和 COLMAP 基准轨迹做相似变换对齐再算 RMSE。如果 ATE 很大但 PSNR 还行说明场景几何整体漂了得回头查位姿转换和尺度对齐。# 评估命令示例 python evaluation/eval.py configs/Tanks/wurenji.yaml # 轨迹对齐与 ATE 计算 python ATE/align_trajectory.py --est results/est_traj.txt --gt data/wurenji/gt_traj.txt python ATE/compute_trajectory_errors.py --aligned results/aligned_traj.txt --gt data/wurenji/gt_traj.txtvis_cam_traj.py可以把相机轨迹画出来肉眼看一下估计轨迹和真实轨迹是不是大致重合。如果两条轨迹形状完全不一样别急着调网络先回去检查images.txt的读取顺序和四元数格式。4. 避坑与排查航拍三维重建里最容易翻车的五件事4.1 现象训练 loss 一直不降PSNR 卡在 10 左右原因深度图尺度和 COLMAP 位姿尺度不一致或者near/far设得太离谱。航拍场景动辄几十米范围如果far只设了 1.0采样全在相机跟前网络学不到东西。解决先用get_depth.py检查深度图数值范围再根据 COLMAP 稀疏点云的包围盒估算场景尺度把near和far设成覆盖整个场景的值。我一般会先跑get_volume_by_surface_reconstruction.py看看点云范围心里有个数再改配置。4.2 现象渲染出来的画面全是糊的或者颜色发灰原因dpt_depth.py生成的深度图被归一化到 0 到 255 后保存成 PNG但训练时读取又做了一次归一化导致深度值被压缩了两次。解决统一深度图的存储格式和读取方式。要么存成 16 位 PNG 保留精度要么存成 npy 文件直接读浮点。资源里dataloading.py和dataset.py决定了读取逻辑改的时候两边要同步。4.3 现象ATE 算出来特别大但轨迹图看着还行原因align_trajectory.py做相似变换时尺度因子估计错了。航拍场景如果 COLMAP 重建本身尺度就不准对齐后的 ATE 会虚高。解决先用get_matrix_by_sfm.py导出位姿和 COLMAP 的images.txt逐帧对比确认转换没出错。如果 COLMAP 尺度本身有问题考虑加地面控制点或者用已知尺寸的物体做尺度约束。4.4 现象train.py报显存不足batch_size 降到 1 还是 OOM原因航拍图分辨率太高比如 4000x3000直接送进网络显存扛不住。解决在dataloading.py里加 resize或者用preprocess2.yaml里可能已经有的下采样参数。我一般会把长边限制在 1000 到 1600 之间同时同步修改内参。资源里wurenji_small_resolution.mp4说明作者也做过小分辨率版本可以参考他的处理方式。4.5 现象eval.py跑完没有输出 PSNR或者报文件找不到原因results_writer.py和checkpoints.py的路径依赖没配好或者configs/Tanks/wurenji.yaml里的data_dir写的是相对路径但执行目录不对。解决统一在项目根目录下执行命令检查 yaml 里的路径是相对根目录还是相对配置文件。使用说明.txt里如果有路径说明以它为准如果没有就按train.py里os.path.join的基准目录反推。5. 进阶技巧正射投影、体积计算与结果验证的实操习惯5.1 用 get_orthographic_by_arcgis.ipynb 做正射投影资源里scripts/get_orthographic_by_arcgis.ipynb这个 notebook 挺有意思它把重建结果和 ArcGIS 的正射投影流程接起来了。正射投影的本质是把三维点云或网格按垂直方向投影到平面生成没有透视变形的二维图。如果你做的是农田、建筑或者地形类项目正射投影图比透视图更有说服力。操作上我一般会先把 NeRF 导出的点云或者深度图转成带地理坐标的栅格再在 ArcGIS 里做投影变换。notebook 里应该包含了坐标转换和栅格导出的代码注意检查投影坐标系是否和无人机 GPS 信息一致否则正射图会整体偏移。5.2 体积计算get_volume.py 和 get_volume2.py 的差别get_volume.py、get_volume2.py、get_volume_by_surface_reconstruction.py三个脚本对应不同的体积计算策略。前两个大概率是基于深度图或点云的积分方法第三个是基于表面重建的封闭网格体积。我实测下来的经验是如果场景是堆体、土方这类有明确底面的对象用表面重建算体积更稳如果是地形起伏用深度图积分更合适。参数上要特别注意底面高程的设定设错了体积能差出百分之几十。建议先用get_volume_by_surface_reconstruction.py跑一遍再用get_volume.py交叉验证两个结果差太多就回去查深度尺度和点云滤波参数。5.3 结果验证别只看 PSNR把轨迹和正射图一起看我自己的习惯是训练完先看psnr.txt的收敛曲线再看vis_cam_traj.py画出来的轨迹最后看正射投影图。三个都对了才认为这次重建是可信的。如果 PSNR 高但轨迹飘说明画面过拟合了如果轨迹对但正射图糊说明深度监督不够。资源里results目录下的参考结果可以当基准但要注意作者用的数据集和你的可能不一样PSNR 绝对值没有可比性看趋势就行。从那以后我每次跑航拍三维重建都强制先走一遍「COLMAP 位姿检查 → 深度图范围确认 → 小分辨率试跑 → 轨迹对齐验证」这四步不再一上来就开大分辨率硬训。希望帮到你。本文还有配套的精品资源点击获取