简介YoloV8无人机检测完整工程资料面向深度学习课程设计、毕业设计及期末大作业场景覆盖智慧交通与安防监控领域的目标检测实践需求。资源共18个文件包括8个Python脚本、2个YAML配置、类别定义清单与数据集配置并附有训练结果CSV和可视化PNG图表压缩包约283KB结构紧凑便于快速上手。其中yolo2coco.py负责标注格式转换merge_data.py完成数据集融合以扩充训练样本model_train.py启动模型训练配合dataset.yaml与classes.txt设置数据路径与类别QT界面与tracker模块实现检测结果实时显示与目标追踪README.md提供完整使用说明串联起数据预处理、模型训练到系统部署的闭环流程。目前已有27人学习使用适合高校学生、毕业设计者及初入目标检测领域的研究者参考既能帮助理解YoloV8在实际项目中的调用方法与参数调优思路也可作为课程或毕设项目直接复用的工程模板。1. 基于 YOLOv8 的无人机检测这套资源能帮你少走三段弯路先给结论用 YOLOv8 做一个无人机检测项目真正卡住人的往往不是模型结构而是三件事——数据组织、训练参数、最后验证。这套资源把这三件事打包到一起可替换的数据集目录、写好的 data.yaml、训练和推理脚本还有一个训练好的 best.pt 权重。它对课程设计、期末大作业和本科毕设都适用尤其适合“想复现完整检测流程但不想从零搭环境”的同学。拿到之后要做的第一件事不是立刻跑训练而是先检查数据集目录把图片和标签的格式对齐。我见过太多人在这步翻车后面全乱。2. 数据与配置先行数据集组织、data.yaml 和模型选型无人机检测和普通目标检测有一个本质区别视角。无人机拍出来的目标通常很小很多只有几十甚至十几个像素常规的行人检测框数据拿来就用小目标预测会非常不稳定。所以准备数据时不能随便找一个“大体上差不多”的物体检测数据集替代最好直接选俯视场景。VisDrone 是这类场景里最常用的起点之一它是无人机视角采集的包含车、行人、自行车等类别图片中有大量远距离小目标。课程设计如果不想自己拍直接用它的图片转成 YOLO 标签是常见做法。如果题目限定“只检测无人机”更省事的路是自己在网上找无人机飞行画面然后用标注工具把每台无人机框出来每张图对应一个 txt。2.1 数据集从哪来VisDrone、自制数据与目录结构先交代目录结构。YOLOv8 训练时对图片和标签的存放方式有硬性要求不是随便放一个文件夹就能跑通。推荐按下面的方式组织drone_yolo/ ├── images/ │ ├── train/ │ │ ├── img001.jpg │ │ └── ... │ └── val/ │ ├── img101.jpg │ └── ... ├── labels/ │ ├── train/ │ │ ├── img001.txt │ │ └── ... │ └── val/ │ ├── img101.txt │ └── ... ├── data.yaml ├── train.py └── detect.py图片放 images 下同名 txt 放 labels 下YOLO 训练时按文件名前缀找 label图片和标签必须同名不同后缀否则训练时会报“No labels found”。标签不是 PASCAL 的 xml 格式每行是一个目标0 0.523438 0.421875 0.134375 0.081250第一个是类别的整数 id后面分别是 bbox 中心点的 x、y以及框的宽和高四个数值要除以原图宽高归一化到 0~1。对无人机这种小目标你可能以为 512 像素和 640 像素差不多实际差很多。尤其是颜色接近背景灰的无人机框的回归有一点偏差都会影响 mAP。标注工具我用得比较多的是 X-AnyLabeling它支持直接输出 YOLO 格式免去 json 转 txt 的步骤。如果你手里的数据本来就是 labelme 的 json那就得分两步先转成归一化坐标再按 images/labels 的结构摊开。2.2 data.yaml 怎么设置路径、类别索引与校验训练前要写一个 data.yamlYOLOv8 从这里面读数据路径和类别名。常见写法是path: /home/user/drone_yolo train: images/train val: images/val names: 0: drone 1: person 2: car这里有几个容易踩的细节path 建议写绝对路径在 Windows 上路径分隔符最好用正斜杠pytorch 对转义字符很敏感。train 和 val 都是相对 path 的路径不需要拼上整个数据集根目录。names 的键不能乱类别 id 必须从 0 开始并且和标签文件里的第一个字段一一对应。如果数据集中只有无人机就只写 0: drone前面那个数字 0 是类别 id不是“可以用 1 开始”的意思。我一般会在正式训练前写一行简单的统计代码把所有标签里的类别 id 扫一遍确认没有出现 data.yaml 之外的编号。再花半分钟随机抽几张图把框画到原图上人工看一眼。这个动作看起来多花时间实际能抵掉后面无数次“模型为什么不收敛”的玄学排查。注意data.yaml 不要塞额外字段。有人会把 train 写成绝对路径val 写成相对路径最后 path 又不存在训练报“Dataset not found”却看不到问题先查这三项。2.3 模型选型yolov8n/s/m/l 怎么选网络结构差异对无人机检测影响在哪YOLOv8 的网络结构和前代比最大区别是把 anchor-based 换成了 anchor-free检测头被解耦成分类和回归两个分支主干里的 C2f 模块提升了梯度流动。做课程设计不需要把每个模块背熟但要理解一件事小目标回归更依赖特征图分辨率模型参数量增加不直接等于小目标变好输入分辨率往往更关键。模型参数量显卡友好度建议场景yolov8n约3.1M好GTX 1660Ti 也能跑流程验证、初版yolov8s约11.2M中等16 batch 可跑课程设计默认yolov8m约25.9M需要更大显存或更小 batch追求精度、时间充裕yolov8l约43.7M不推荐入门卡跑毕设且愿意等如果手头是 GTX 1660Ti 这类 6GB 显卡我一般建议先用 yolov8n 把整个流程跑通确认数据没问题再换 yolov8s 多训一轮。不要一上来就用 m/l否则 batch 一压再压loss 曲线波动变大你根本分不清是模型问题还是优化问题。对于无人机小目标与其从 n 升到 l不如把 imgsz 从 640 提到 1280这个动作对小目标的收益通常比换大模型更直接代价是显存占用接近翻倍。3. 训练与调参把 yolo train 跑通再用损失曲线判断收敛数据没问题后训练命令本身非常简单难的是参数怎么设、输出怎么读。这一节我把训练命令拆开讲清楚再讲怎么看 results.csv 和损失曲线。3.1 第一条训练命令每个参数落点在哪确认数据和配置没问题后训练命令就是这一条yolo train \ modelyolov8s.pt \ data/home/user/drone_yolo/data.yaml \ epochs100 \ imgsz640 \ batch16 \ patience20 \ projectdrone_yolo \ nameexp1 \ device0modelyolov8s.pt 表示加载 COCO 预训练权重继续训练而不是从头开始。如果用 yolov8s.yaml那是不加载任何权重从头训练效果会差很多课程设计阶段没必要自虐。epochs100 是一个能出结果的起点实际跑下来 patience20 往往会自动提前停。如果只想快速过一遍代码可以把 epochs 改成 50。imgsz640 是输入边长YOLOv8 默认按正方形处理并保持长宽比。对无人机这种小目标640 适合快速验证960 或 1280 适合正式实验。batch16 在 6GB 显卡上配合 yolov8s 刚好处于边缘如果 OOM 就降到 8 或 4。batch 调小之后学习率也要跟着动我一般会默认 lr0 从 0.01 调低到 0.001 或 0.005否则梯度噪声大曲线会一直抖。project 和 name 控制输出目录训练结果落在 drone_yolo/exp1。同一份数据跑多组实验时每组 name 都要换不要覆盖不然后面想对比曲线就没了。3.2 训练输出文件weights 和 results.csv 怎么用训练过程中会生成一堆东西很多人只盯着终端输出忽略真正有用的文件。训练结束后到输出目录看一眼drone_yolo/exp1/ ├── weights/ │ ├── best.pt │ └── last.pt ├── results.csv ├── confusion_matrix.png ├── PR_curve.png └── train_batch0.jpgbest.pt 是验证集 mAP 最高的那一轮保存的权重last.pt 是最后一轮权重。推理、导出、写报告都用 best.pt不要用 last.pt。last.pt 只有在最佳权重出现过拟合时才偶尔备用。results.csv 记录每个 epoch 的各种指标画损失函数曲线图时主要靠这个文件。confusion_matrix.png 看类别混淆PR_curve.png 看召回和精确率之间的平衡。课程设计答辩时别人问你怎么判断模型收敛不是看终端一堆“Epoch 50/100”就完事而是把 results.csv 里的数据拉出来画图证明训练过程是健康的。3.3 画损失曲线判断收敛和过拟合的实操代码画损失曲线图是 YOLOv8 项目里必须做的一步。下面这段代码直接读 results.csv画出 box loss 和 mAP 两条曲线import pandas as pd import matplotlib.pyplot as plt import matplotlib matplotlib.use(Agg) df pd.read_csv(drone_yolo/exp1/results.csv) df[epoch] df[epoch].astype(int) plt.figure(figsize(12, 5)) plt.subplot(1, 2, 1) plt.plot(df[epoch], df[train/box_loss], labeltrain box_loss) plt.plot(df[epoch], df[val/box_loss], labelval box_loss) plt.xlabel(epoch) plt.ylabel(loss) plt.title(box loss) plt.legend() plt.subplot(1, 2, 2) plt.plot(df[epoch], df[metrics/mAP50(B)], labelmAP50) plt.plot(df[epoch], df[metrics/mAP50-95(B)], labelmAP50-95) plt.xlabel(epoch) plt.ylabel(value) plt.title(mAP) plt.legend() plt.tight_layout() plt.savefig(loss_curve_and_map.png, dpi200)逻辑说明train/box_loss 和 val/box_loss 应该一起下降。如果 val/box_loss 在某个 epoch 后打平甚至反弹说明过拟合。mAP 曲线出现阶梯式爬升是正常的只要不是突然归零就没问题。重点要盯的是 mAP50-95这一项评价的是预测框和真实框的 IoU 在 50% 到 95% 范围内的整体表现。无人机小目标场景里 mAP50 可能很高但 mAP50-95 很低说明框的位置和宽高偏差大模型还没有真正精确到可用的程度。如果论文里要画网络结构图不要截图网上的旧版 YOLOv5 结构图。YOLOv8 是 anchor-free检测头解耦结构图里一般要体现 C2f、SPPF、Detection Head 这三个关键部分。课程设计能把这几个地方说清楚已经比大多数直接抄模型的要强。3.4 mAP50-95 上不去先查输入尺寸再查标签质量loss 正常但 mAP 一直低是无人机检测项目里很常见的情况。我的排查顺序是先 imgsz 提到 960 或 1280 跑一个短 epoch看看 mAP50-95 是不是明显改善。无人机在图中可能只占百分之几像素经过主干网络降采样后只剩几个像素网络根本没法学这不是改 loss 能解决的。其次是标签。小目标标注很容易把框画大很多人会把无人机连同螺旋桨背景一起框进去模型学的目标区域就偏了。画框时尽量贴着机身主体四轴高速旋转的桨叶不要包进框里尤其是标注无人机类别时这个习惯直接影响回归精度。还要注意类别不平衡。如果无人机类别占了 90%person 占 10%模型会倾向把所有目标识别成无人机。常见做法是先统计类别分布对少的类别做重采样或者加入只有背景没有目标的空标签图片抑制误检。4. 无人机检测避坑五个高频问题与处理路径这一节写的是我在实际跑无人机检测项目时遇到过的坑每条都按“现象→原因→解决”来整理。希望你先记住这些问题别等训练完才后悔。4.1 训练 loss 变成 NaN或 val mAP 直接是 0现象训练能正常启动但 train/box_loss 几轮后变成 NaN或者验证集的 mAP 全输出 0看起来像没跑。原因常见有三种。第一标签坐标没有归一化比如标注工具导出的还是像素值跑到几千上万第二某些标注框超出图片边界宽高小于等于 0第三学习率设置过大或者混合精度 AMP 在旧显卡上不稳定。解决先跑一段标签清洗脚本把坐标越界的文件找出来import numpy as np import glob files glob.glob(labels/train/*.txt) for f in files: arr np.loadtxt(f).reshape(-1, 5) if arr[:, 1:].min() 0 or arr[:, 1:].max() 1: print(f, 坐标越界) if (arr[:, 3] 0).any() or (arr[:, 4] 0).any(): print(f, 宽度或高度 0)这段代码里arr 每一行是“类别 id、中心 x、中心 y、宽、高”。框的中心和宽高都必须落在 0 到 1 之间宽高不能小于等于 0。YOLOv8 在数据加载阶段不会对越界坐标直接报错而是会裁剪或过滤极端情况就表现为 loss 异常。找到异常文件后用之前的代码修正或直接删掉重标。修完标签再把 lr0 降到 0.001训练命令里加 ampFalse基本能解决这类问题。4.2 小目标无人机漏检严重现象验证集整体 mAP50 有 0.8但一部分几十像素的小型无人机模型完全检不出来尤其是远距离或画面边缘的目标。原因小目标在特征图上只占用几个像素输入 imgsz 越低降采样后保留的信息越少。另外无人机颜色和天空、地面背景接近时特征更弱模型很容易忽略。解决第一步把 imgsz 提高到 960 或 1280重新训一个短实验对比。第二步推理阶段采用切片推理把大图切成若干有重叠的 patch分别检测再合并结果常见做法是用 SAHI 库。如果不想引入切图逻辑至少要保证训练时不要用太强的 mosaic 和 mixup 增强因为小目标被裁剪拼接后更容易丢失。4.3 数据比例失衡模型只认一种目标现象验证时无人机全检出来了但同时也把许多汽车、行人误报成无人机别人一看结果就觉得模型没学会。原因数据里无人机样本远多于其它类别负样本不足。模型学到的是“图像里有一块和无人机相似的区域就直接报”而不是真正区分无人机和背景。解决先统计 label 里各类别的数量少的类别复制几份做重采样。再加入一些只有背景、没有任何目标的训练图片配一个空标签 txt 文件YOLOv8 支持空标签训练。这样模型有机会见到“没有目标”的样本误检会明显下降。注意空标签 txt 里不需要写任何内容但文件必须存在否则 YOLO 会认为该图没有标签而跳过。4.4 标签类别索引从 1 开始训练不报错但结果全错现象训练过程完全正常loss 也下降但检测结果类别对应混乱或者预测出 data.yaml 里根本不存在的类别。原因标注文件里的 class id 和 data.yaml 的 names 索引没有对齐。常见问题是最开始用 1 代表第一个类别而 YOLO 要求从 0 开始。一旦出现 id2 而 names 只有 0 和 1超出的 id 会被训练流程过滤掉相当于这一类目标全部没有参与训练。解决先统计所有标签文件里的类别 id再对照 data.yaml。如果确认需要把 id 整体减 1用下面这段重映射脚本import glob for f in glob.glob(labels/train/*.txt): with open(f) as fp: lines fp.readlines() with open(f, w) as fp: for line in lines: parts line.strip().split() if not parts: continue cls int(parts[0]) - 1 fp.write(f{cls} { .join(parts[1:])}\n)这段代码只适合“从 1 改成从 0”的情况具体减不减以你自己的标注规范为准。改完之后一定要抽一张图把框和类别写回图片上直观确认。我见过有人脚本跑完直接训练结果类别全部变成 -1最后还是得回头重做。4.5 验证集画不出框推理脚本一片空白现象best.pt 已经训练完成用 detect.py 跑测试图像结果图里一个框都没有终端也没有报错。原因一般是置信度阈值设得过高或者验证集图片和训练集分布差异太大。无人机目标本来就小置信度往往低于 0.5默认阈值很容易把所有预测都过滤掉。解决先用一个简单的测试脚本把 conf 降到 0.1 看一眼yolo predict modelbest.pt sourcetest.jpg conf0.1 iou0.5如果降到 0.1 能出框说明模型本身没坏后面再根据实际需求把 conf 调到 0.3 或 0.4。如果降到 0.1 还是空白那要回头查验证集图片是否和训练集完全不是一个场景或者标签格式有没有问题。5. 验证收尾画曲线、出热力图、留部署后路训练结束后我先做三件事顺序不换画损失曲线、导出 ONNX、检验热力图。损失曲线不是“给别人看训练过”是给自己确认模型没有过拟合导出 ONNX 是为了部署时不手忙脚乱热力图则是验证模型到底在看什么。画曲线用下面这段代码把 mAP 和 loss 压到一张图里import pandas as pd import matplotlib.pyplot as plt res pd.read_csv(drone_yolo/exp1/results.csv) plt.figure(figsize(10, 4)) plt.plot(res[epoch], res[metrics/mAP50(B)], labelmAP50) plt.plot(res[epoch], res[metrics/mAP50-95(B)], labelmAP50-95) plt.plot(res[epoch], res[train/box_loss], labeltrain box_loss) plt.legend() plt.savefig(final_check.png, dpi200)如果 val loss 尾段翘起我宁愿重新训一次也不把 best.pt 交出去。best.pt 是验证集上表现最好的权重但严格来说我还要看它对应的 val loss 是否已经过拟合如果最佳 epoch 出现在很靠后的位置通常说明数据不够或训练步长不合适。部署后路也很关键尤其是 yolov8 部署到 RK3588 这类边缘设备。我一般导出 ONNX 时不把 NMS 塞进网络只导出主干和检测头NMS 交给部署框架的后处理代码去写这样转 RKNN 时少踩不少兼容性坑。导出命令yolo export modelbest.pt formatonnx imgsz640 opset12导出之后先用 onnxruntime 跑一帧确认输出层的结构符合预期再做后续转模型。如果目标设备只支持特定 opset导出时还要调整。这个细节经常被忽略等到了板子上发现算子不支持再回头重导就晚了。热力图方面常见做法是用 GradCAM 系列方法看模型激活区域。如果热力图只照亮背景没照亮无人机先不急着怀疑模型回去查标签框是不是漏标了。从那以后我每次换数据集都会强制走一遍“画曲线、导 ONNX、看热力图”这整套流程确认没有隐藏问题才敢把结果交出去。希望帮到你。本文还有配套的精品资源点击获取