公司动态

YOLOv8固定翼无人机检测:从数据集制作到PyQt部署全流程

📅 2026/8/31 14:51:23
YOLOv8固定翼无人机检测:从数据集制作到PyQt部署全流程
简介本资源面向计算机视觉初学者与无人机应用开发者提供一套开箱即用的小型固定翼无人机YOLOv8检测解决方案解决目标检测模型训练难、数据集稀缺、部署界面缺失等实际问题。压缩包共2000个文件含1892个YOLO格式标注txt文件已划分train/val/test、90个Python脚本含PyQt检测界面、训练与推理逻辑、4个配置yaml文件含data.yaml明确标注nc:1与类别名FixedWing-Drone、6个Shell脚本及5份PDF/MD教程文档整体大小160.8MB。已有200人学习下载配套教程覆盖YOLOv5/v7/v8多版本环境配置、权重迁移训练及PyQt界面运行全流程支持图片、视频与实时摄像头检测数据集目录结构规范、标签格式统一可直接用于科研验证或课程实验。 做固定翼无人机检测有一阵子了圈子里最常看到的问题不是“该选哪个模型”而是搜遍全网找不到一套能直接落地的完整流程。权重、数据集、训练教程、界面封装四样东西往往得从四五个博主那里东拼西凑而且很多开源权重只针对大疆那种旋翼机换到固定翼场景效果立刻打折扣。这篇文章就把我这段时间攒下来的完整方案摊开讲YOLOv8训练固定翼无人机检测权重、2000张数据集的制作细节、从训练到PyQt界面部署的完整链路。适合刚接触YOLOv8但手里有明确检测需求的人也适合那些已经跑通过官方demo、但不知道怎么把模型做成一个像样桌面工具的朋友。1. 为什么固定翼无人机检测比旋翼机更棘手先聊点务虚的但这部分决定了你后面所有的技术选型。固定翼无人机和常见的四旋翼无人机在检测任务里有本质区别。大疆那类旋翼机飞行速度慢、悬停多、机体结构复杂四个机臂、云台、起落架都清晰可见中近距离下检测框很稳定。但固定翼无人机有几个非常头疼的特点尺寸小翼展通常在1到3米之间在几百米外拍摄时画面里往往只有十几个甚至几个像素。速度快巡航速度动辄每小时几十上百公里运动模糊严重帧与帧之间目标位移大。背景复杂固定翼多出现在天空、海面、山地等场景云层、海面反光、山体纹理造成的虚警率远比普通目标检测高。姿态多样转弯坡度、俯冲、拉升都会让目标外形产生剧烈变化侧面、背面、机头正对镜头时的特征完全不同。这些特点叠加在一起决定了你不能无脑套用COCO上训练出来的通用检测权重。COCO数据集里虽然有airplane类但那是客机、小型螺旋桨飞机为主和“小型固定翼无人机”在尺度、外观、拍摄角度上有很大差异。实测下来直接用COCO权重在固定翼无人机画面上推理漏检率能到40%以上虚警率也不低——云层边缘、飞鸟都会触发误报。所以自己准备数据集、自己训练一个专用权重不是“锦上添花”而是“必经之路”。这个项目里我用的是YOLOv8s作为基础模型。为什么选s而不是n或mn确实更快但在小目标场景下精度下降得厉害m精度好一些但训练和推理速度对1660Ti这类显卡不太友好。s在精度和速度之间是最平衡的实际测试下来单帧推理在GTX 1660Ti上大概20到30毫秒完全够用。2. 2000张训练集是如何从零建起来的数据是检测项目的命根子。很多人在这一步就放弃了因为标注枯燥、来源难找、整理麻烦。我分几个部分把这2000张数据集的完整构建过程讲清楚。2.1 数据来源自建拍摄公开数据集筛选这2000张图不是一次性从某个网站下载的而是三个来源的混合自建拍摄占600张左右。用无人机挂载摄像头从不同角度拍摄固定翼飞行画面同时在起降场附近拍摄地面停机、滑行状态。这部分数据的价值在于目标姿态、光照、背景完全贴近真实部署环境是模型精度的基石。公开数据集筛选占900张左右。VisDrone、Aeroscapes这些公开无人机视角数据集里有一定数量的固定翼目标把这些图片筛出来重新标注。注意VisDrone里的类别标签比较粗糙很多“固定翼”样本其实是直升机或者动力伞需要人工二次审查。网络搜索补充占500张左右。搜航空展、航模比赛等关键词搜集不同品牌、不同涂装的固定翼无人机图片填补自建数据里机型单一的问题。这里有个细节值得多说一句网络图片不要直接拿来训先做版权和清晰度筛选再统一分辨率和格式。图片尺寸差距过大会导致训练时resize后目标尺度分布不稳定影响收敛。2.2 标注策略小目标的标注方式决定模型上限标注是整个过程里最容易出问题、也最影响最终质量的环节。我用的标注工具是Labelme和LabelImgYOLOv8要求的是txt格式每个标注文件对应一张图片每一行格式是class_id x_center y_center width height注意坐标是归一化的且是相对于图片宽高的比例。用LabelImg可以直接导出成YOLO格式Labelme则需要通过脚本转换一次。标注时有几个关键原则单类别标注不区分机型。固定翼无人机不管型号、涂装、尺寸统一归为“fixed_wing”一个类别。类别越多、样本越稀疏训练越不稳定。小目标标注框宁准勿大。目标只有10个像素左右时标注框稍微偏大一点模型学到的就是“一个大黑点”检测框会严重偏大导致IoU计算偏低、AP值虚低。我的经验是把目标放大到200%后再精确描框。模糊目标也标注。运动模糊、远处小目标的确认度不高但这类样本恰恰是提升模型鲁棒性的关键。只要人眼能确认“是固定翼无人机”就标。负样本单独建一个noise目录。我额外准备了几百张没有固定翼无人机的天空、云层、海面图片在训练时混入作为负样本显著降低了虚警率。这一点很多人会忽略但对固定翼无人机这种“目标是天空中的小点”的场景特别重要。2000张图一个人标注每天投入3到4小时大概一周到十天能完成。为了不浪费时间标注前先按拍摄场景、天气、背景做一次预分类然后轮流标注避免同一批图片全部是晴天蓝天背景导致模型对阴天、海面背景泛化能力差。2.3 数据增强与数据平衡2000张图片直接训练不是不行但泛化能力会差一些。我在训练前做了以下几类增强几何增强随机翻转、随机旋转、随机缩放。色彩增强亮度、对比度、色调的小范围扰动模拟不同光线条件。Mosaic增强YOLOv8自带的mosaic增强把4张图拼成1张训练对小目标检测的提升非常明显相当于变相增加了数据量也让模型适应目标被裁切的情况。小目标专用策略对小于32x32像素的目标单独做2倍到3倍的子图放大增强让模型有更多机会“看清”小目标的特征。数据平衡方面我按目标尺寸做了分层统计确保“小目标样本”目标面积小于图片面积1%占比不低于总量的一半。否则训练出来的模型会对大目标过拟合部署时看远处的小目标就失效。3. YOLOv8训练调优与权重产出数据准备好之后就是训练。YOLOv8的训练链路非常简单但里面坑不少。3.1 环境配置与版本选择我用的环境是Python 3.9 PyTorch 2.0.x实测2.1、2.13版本对YOLOv8兼容性也都正常 ultralytics 8.0.x建议锁定版本新版本偶尔会改默认参数 CUDA 11.8 GTX 1660Ti 6GB显存安装ultralytics直接pip就行但注意它依赖的openCV版本在Windows上偶尔会有兼容问题如果出现cv2.error: OpenCV(4.7.0)之类的报错先升级或降级opencv-python试试。CPU版和GPU版不要混装否则PyTorch检测不到CUDA。3.2 数据集目录结构与配置文件YOLOv8对数据集目录结构有固定要求建议严格按这个来datasets/ fixed_wing/ images/ train/ # 1600张 val/ # 400张 labels/ train/ val/yaml配置文件fixed_wing.yamlpath: D:/datasets/fixed_wing # 这里是绝对路径相对路径在换机器跑时会报错 train: images/train val: images/val nc: 1 names: [fixed_wing]这里有一个常见坑path字段一定要写对。我见过无数人因为path写成了相对路径或者train/val路径写错训练时直接报空数据。3.3 训练命令与参数调优训练命令用的是ultralytics的标准CLIyolo train datafixed_wing.yaml modelyolov8s.pt epochs200 imgsz640 batch8 device0几个关键参数的选择思路modelyolov8s.pt直接加载COCO预训练权重做迁移学习而不是modelyolov8s.yaml从零训练。预训练权重能大幅加速收敛在小数据集上尤其明显。可以理解为模型已经见过真实世界的纹理、边缘等基础特征我们只教它“什么是固定翼无人机”这件新事。imgsz640这是速度和精度的平衡点。如果目标非常小可以考虑用imgsz960或1280但这会显著增加显存占用和推理时间1660Ti跑960基本是极限。我在640分辨率下配合切片推理后面会讲到效果已经不错。batch86GB显存下的安全值。如果batch16显存溢出调成8。但注意batch太小会导致batch normalization不稳定所以尽量不要低于4。epochs200对2000张数据来说160到200轮已经足够再长容易过拟合。训练过程中可以观察val精度曲线如果连续50轮没有提升就可以提前停。训练过程中的几个关键监控点观察train_batch*.jpg图片确认mosaic增强后的图片和标注框对齐正常。观察val_batch*.jpg预测结果看有没有漏检、框不贴合的问题。每轮结束看PR曲线和F1曲线如果P和R的平衡点比较好模型曲线下面积大说明正负样本分类比较清晰。3.4 训练常见问题排查训练时loss为nan大概率是学习率过大或batch太小导致梯度爆炸把lr0从0.01调低到0.001试试。显存不够imgsz降到480或者用yolov8n。训练很慢开AMP混合精度1660Ti虽然不支持完整的TensorCore加速但AMP仍然能有效省显存、提速度。验证集mAP很高但实际效果差检查是不是数据泄漏训练集和验证集里混入了同一个视频序列中高度相似的帧导致验证集“虚高”。3.5 模型评估与最终权重产出训练结束后ultralytics会在runs/train/目录下生成多个权重文件best.pt验证集上mAP最高的权重这个是我们最终部署要用的。last.pt最后一轮的权重一般不用。最终我在自己的验证集上测得的指标大概在mAP50-950.63、mAP500.91左右。注意2000张单类数据、目标尺度偏小的情况下这个指标是合理且可复现的。如果谁告诉你几千张数据mAP50-95能到0.9要么是验证集太简单要么是数据泄漏。4. PyQt5检测界面的设计与实现模型训练完只是完成了一半实际使用中不可能每次都在命令行里跑推理。我用PyQt5做了一个简单的桌面检测工具支持图片、视频和摄像头实时检测三种模式。这部分对不熟悉GUI编程的人来说门控比较大但跟着做也不难。4.1 整体架构界面线程与检测线程分离PyQt5界面开发最重要的一点不要在UI主线程里做推理计算。推理是耗时操作如果直接在主线程里跑界面会出现“未响应”状态用户体验极差。我用了一个很朴素的主线程QThread worker模式class DetectWorker(QThread): frame_ready pyqtSignal(object) result_ready pyqtSignal(object) def __init__(self): super().__init__() self.model YOLO(best.pt) self.cap None self.running True self.source None def run(self): if self.source camera: self.cap cv2.VideoCapture(0) elif self.source video: self.cap cv2.VideoCapture(self.video_path) elif self.source image: self.detect_image(self.image_path) return while self.running: ret, frame self.cap.read() if not ret: break results self.model(frame, imgsz640, conf0.35) annotated results[0].plot() self.frame_ready.emit(annotated) self.msleep(30) def stop(self): self.running False if self.cap: self.cap.release()Worker线程把检测结果画好之后通过信号发回主线程主线程只需要把QImage显示到QLabel上。def update_frame(self, frame): rgb_image cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) h, w, ch rgb_image.shape bytes_per_line ch * w qt_image QImage(rgb_image.data, w, h, bytes_per_line, QImage.Format_RGB888) self.video_label.setPixmap(QPixmap.fromImage(qt_image))4.2 界面布局与交互界面布局用QWidget作为主窗口左侧是控制面板右侧是画面显示区控制面板包含打开图片、打开视频、打开摄像头、停止、置信度阈值滑条。画面显示区QLabel显示检测结果下方状态栏显示FPS和当前检测到的目标数量。置信度阈值这个滑条很重要。固定翼无人机场景下远处小目标的置信度天然偏低。如果固定写死0.5很多真目标会被过滤掉但如果降到0.2又会产生大量虚警。做成滑条让用户根据实际场景动态调整是桌面工具实用的关键之一。4.3 推理速度优化实时性是这个界面工具的核心指标。我在1660Ti上针对不同输入做了以下优化摄像头模式跳帧处理。每读2帧才做一次推理但显示帧仍然保持原帧率这样视觉效果流畅GPU负载也降下来了。画面缩放推理前把大尺寸画面resize到640x640检测框坐标再映射回原图。这个YOLOv8内部已经处理了直接传大图也可以但会明显增加推理耗时建议在摄像头源上对原始帧先做一次不超过1280像素宽度的裁剪缩放。慢推理的原因排查如果FPS比预期低很多打开任务管理器确认GPU占用率。如果GPU占用率很低但CPU很高说明推理在CPU上执行了去检查PyTorch和CUDA版本配对。4.4 将界面封装成exePyQt5界面做好以后用PyInstaller打包成exe在自己电脑上跑没问题拿到别人电脑上却各种闪退这是新手最常见的坑。我的打包命令pyinstaller -w -F --add-data best.pt;. --add-data fixed_wing.yaml;. main.py打包完成后注意模型文件和yaml文件要放在exe同目录或者打包进exe否则程序找不到权重会直接崩溃。如果目标机器没有NVIDIA显卡要在代码里做cuda不可用时的CPU回退并适当降低检测优先级。CPU上YOLOv8s推理一张640图片大概100到200毫秒还是能用的。PyInstaller打包出来的exe首次启动会稍微慢一点因为要解压临时文件不要误以为程序卡死了。5. 部署到真实场景的坑与最终实测训练完成、界面也OK了但拿到实际场景中测试还是有一堆意想不到的问题。这些问题单独拿出来说清楚能省你很多时间。5.1 小目标检测的终极方案切片推理前面提到固定翼无人机在远景下可能只有几个像素这时就算用再好的权重YOLOv8直接整体推理也容易漏检。我实际验证过几个方案整图推理远距离目标检测率大概只有60%左右。图像金字塔多尺度缩放后分别推理再合并检测率有所提升但推理时间翻倍。切片推理把原图切成256x256或320x320的小块分别推理再把结果合并回原坐标系。检测率能提升到85%以上代价是推理时间增加。切片推理在固定翼检测场景特别有效因为它相当于把“远处的小目标”放大成了“近处的中目标”。具体实现上可以在PyQt工具的检测线程里加一个“精细模式”开关开启后在上屏前对原图做切片推理。注意切片之间要保留少量overlap比如20像素避免目标正好被切分到两块中间导致漏检。5.2 云层反光的虚警问题实际测试中我发现虚警主要来自两种场景云层边缘形状尖锐、亮度和天空差异大容易被模型误认为无人机轮廓。海面/湖面反光阳光直射下的水面波纹纹理和运动模糊后的无人机有点像。解决方案是收集这两种场景的负样本重新训练同时把推理置信度阈值从0.25提高到0.35。这个调整会稍微降低少量低置信度真目标的检出率但整体误报数量的下降幅度更值得。我最终的权重在晴天蓝天场景下的虚警率大概是每100帧1到2次阴天和海面场景稍高但已经在可接受范围内。5.3 模型导出与ONNX部署如果需要部署到没有PyTorch环境的机器上可以把best.pt导出成ONNX格式yolo export modelbest.pt formatonnx imgsz640ONNX推理可以用onnxruntime比直接加载PyTorch模型快一些尤其在CPU上import onnxruntime as ort session ort.InferenceSession(best.onnx) input_name session.get_inputs()[0].name pred session.run(None, {input_name: input_blob})在这个PyQt项目中我保留了双后端优先PyTorch GPU推理导出时用户可以自己勾选ONNX模式。ONNX模式在CPU上也能跑适合没有独显的笔记本。5.4 实测数据与经验总结最后放一组我在固定翼无人机实际飞行画面上的实测数据供你参考整图推理640分辨率平均单帧28毫秒远距离目标漏检率约35%。切片推理精细模式平均单帧120毫秒远距离目标漏检率降到15%以下但FPS只有8左右适合对实时性要求不高的场景。CPU推理ONNX无GPU平均单帧150毫秒勉强可用。检测框稳定性运动模糊帧会出现检测框抖动我加了一个简单的EMA框平滑画面稳定很多。整个项目做下来最深的感受是训练检测模型这件事真正拉开差距的不是网络结构、不是训练技巧而是数据质量和对实际场景的理解。你可以换各种backbone、加各种注意力模块、折腾十几天的调参但效果可能不如老老实实多标500张负样本、多测几个实际飞行场景。如果你也想做这个方向我的建议是先理清你的部署环境和目标距离再决定数据集规模和推理策略。如果目标距离很近50米以内2000张数据其实绰绰有余如果目标是几百米外的俯视小目标那切片推理、更高分辨率输入、以及专门的远距离样例数据才是真正的突破口。别一上来就追最新的改进模块先把基准链路跑通后续优化才有比较的基准。本文还有配套的精品资源点击获取