基于YOLOV11的无人机地面垃圾检测系统搭建全流程
无人机在天上飞一圈地面上哪块区域有塑料瓶、纸盒、废弃建材甚至边角旮旯里的白色垃圾都能被自动标出来。这不是什么科幻演示而是我最近一直在折腾的一套基于深度学习YOLOV11的无人机地面垃圾检测系统。做这个项目的直接原因很实际无人机拍回来的航拍视频素材非常多靠人盯着屏幕一帧一帧找垃圾眼睛受不了效率也低而且高空俯拍视角下的垃圾目标又小又密普通目标检测模型根本扛不住。所以我把YOLOV11、航拍地面垃圾数据集、无人机采集这几个核心环节串起来从数据采集一直做到机载端推理跑通了一条完整链路。这篇文章不是什么学院派教程更像是我自己从零踩坑到跑通全流程的一份实操总结。适合准备入门目标检测的0基础纯小白也适合已经在用YOLO系列但没真正做过航拍小目标任务的开发者。我会把数据集怎么搞、YOLOV11怎么配环境、训练参数怎么调、无人机端怎么部署以及我踩过的各种奇怪问题都掰开揉碎讲一遍。1. 这个项目到底要解决什么问题1.1 无人机地面垃圾检测的真实应用场景先回答一个最基础的问题花那么多精力做一套无人机垃圾检测到底有什么用我把它分成三类最典型的落地场景。第一类是城市环卫巡检。传统环卫巡查基本靠人工骑电动车沿街看效率低而且绿化带、边坡、屋顶这些位置根本看不到。换上无人机之后一条两公里长的河道或者一片几平方公里的工业区十几分钟就能巡完而且能飞到人走不进去的地方。检测系统把垃圾位置框出来地面保洁人员按图索骥去清理工作量能省一大半。第二类是大型活动后的场地清理。演唱会、马拉松、露天音乐节结束后场地里会散落大量矿泉水瓶、纸杯、包装袋。我以前见过主办方雇几十个人排成一排拉网式捡垃圾那个场景真的非常原始。无人机快速扫一遍场地把垃圾密集区域生成一张热力图保洁力量就可以优先投放到对应区域。第三类是景区和自然保护区的常态化监测。游客乱扔垃圾一直是管理痛点靠巡逻发现太被动。固定航线每天自动飞一遍系统自动比对前后两天新增垃圾点马上就定位到新污染源还能辅助追责取证。这类项目的价值不在于“能识别垃圾”这个单一功能而在于它把无人机采集、视觉识别、定位标记、工单派发串成了一条自动化巡检链路。你只看检测算法会觉得挺单调但放到整个巡检闭环里它是信息入口价值就差远了。1.2 为什么偏偏选YOLOV11而不是Faster R-CNN或DETR选模型这件事我纠结过挺久的。当时摆在桌面上的选项有Faster R-CNN、YOLO系列、以及基于Transformer的DETR。Faster R-CNN精度确实不差但它两阶段的设计摆在边缘设备上就头大了。无人机机载端的算力往往就那么点Jetson Orin、RK3588这类平台对模型体积和推理速度极其敏感。Faster R-CNN推理一次要跑两个阶段一张图几百毫秒起步根本没法实时。DETR的思路很优雅不需要锚框、不需要NMS但训练收敛慢、对数据量要求高而且Transformer结构在低算力设备上做量化部署时坑非常多。我自认为不是神人不想给自己挖这么大的坑。YOLOV11作为Ultralytics家族最新的一代核心优势非常清晰结构上继续迭代了C3k2模块替代早期版本里的C3用更细粒度的卷积拆分保持特征提取能力的同时降低计算量检测头在Neck部分进一步强化了多尺度特征融合。我实测下来同样一批无人机数据YOLOV11的mAP比V8略高推理速度还快了一点几乎没有犹豫就选了它。还有一个现实原因Ultralytics的生态太完整了。训练、验证、导出ONNX、转TensorRT全都是一行命令搞定对入门玩家非常友好。哪怕你是零基础只要有Python环境跑起来并不算难。这在项目推进中省下的时间是非常可观的。1.3 方案选型背后的两个“为什么”第一个“为什么”是关于检测类别的定义。一开始我规划了十来种类别包括塑料瓶、纸盒、易拉罐、塑料袋、泡沫、烟盒等等结果标注工作量大到崩溃而且很多类别在航拍视角下长得几乎一样比如纸盒和泡沫箱。最后我按材质和使用场景合并成五类塑料类、纸质类、金属类、玻璃类、织物类。实践下来目标检测任务宁可类别少、特征区分度大也不要类别多但互相遮挡、互相混淆。对初学者我强烈建议一开始控制在3到5个类别先把整个链路跑通再说。第二个“为什么”是关于识别粒度。有人问为什么不用实例分割把每片垃圾的轮廓画出来。道理很朴素机载设备算力是硬约束分割模型的参数量和计算量比同级别检测模型高出一大截而实际业务中我只需要知道“哪里有垃圾、大概什么类型、坐标在哪”一个带旋转角的目标框完全够用。不要为了炫技给自己增加不必要的复杂度。2. 数据集这个系统的地基到底怎么打2.1 无人机航拍垃圾检测数据集的特殊性做这个项目之前我以为搞垃圾检测数据集和做普通路测数据集差不多多拍点照片标一标就行。真正上手以后才发现无人机视角带来的问题比想象中多得多。最大问题是目标尺度。一架无人机飞到80米高度地面上一张A4纸大小的垃圾在画面里可能只有十几个像素。即使飞低到30米一个常见的饮料瓶在1080P画面里往往也只有30×40像素左右。这种尺度特征导致模型特别容易漏检而且任何一点标注框偏移都可能让学习信号被噪声淹没。第二个问题是视角。航拍是纯粹的俯拍视角垃圾不是平视时那种直立状态而是“躺”在画面里的。同一个矿泉水瓶人站在地上看它是一回事无人机从正上方看它又是一回事模型的泛化能力没法直接迁移。所以那些从网上爬来的普通街景垃圾图片对航拍模型的帮助其实很有限。第三个问题是背景干扰。地面上的树叶、草丛、石头、斑驳的水泥地面在高分辨率航拍图像里纹理极其丰富模型很容易把阴影、积水、乱石误判成垃圾。这也是航拍垃圾检测比普通场景检测困难很多的直接原因。所以结论很明确航拍垃圾检测模型必须用航拍数据来训练这是绕不过去的前提。2.2 公开数据集可以用但必须自己补拍业内目前确实没有像COCO那样大规模、标准化的航拍垃圾检测公开数据集。DOTA是航拍旋转目标检测的经典但检测的是飞机、船只、车辆这些目标HRSC2016主要针对舰船CCPD是停车场场景的车辆检测。这些数据集可以用来做“预训练微调”粗粒度上帮模型学会提取航拍视角下的视觉特征但对垃圾检测的最终效果支撑非常有限。所以我的操作路径是先下载DOTA、HRSC2016这类航拍大场景数据做预训练或迁移学习基座然后自己用无人机采集真实的垃圾场景数据两者结合。自己采集这部分我讲一下具体方法。无人机选型方面大疆Mini系列、Mavic系列都够用关键是镜头素质建议不低于1200万像素且支持4K视频录制。飞行高度我控制在20到50米之间太高了垃圾目标太小太低了单帧覆盖范围又太小导致效率低。航线规划用飞控自带的任务航线功能按“弓”字形往返覆盖目标区域同时保持云台垂直向下减少倾斜遮挡。采集视频比采集照片效率高得多。我一般用4K/30帧飞一遍回来后在本地按固定间隔抽帧比如每隔15帧取一张。一小时的4K视频抽出来大概有7000到10000帧筛选掉大量重复帧和严重运动模糊帧后能留下2000到3000张有效图像足够一轮训练用了。2.3 标注工作流工具、规范与数据划分标注工具我推荐两个方向。纯手动打框用LabelImg简单但效率低。我后来换成了X-AnyLabeling支持自动标注辅助先用一个初版模型对未标注图片做预测生成伪标签再人工修正标注速度直接提升了一倍多。如果对数据隐私不敏感Roboflow也可以在线标注并自动做增强新手用起来特别方便。标注规范方面有几个容易被忽视的细节。边界遮挡物必须尽量框完整宁可稍微包含一些背景也不要切掉目标主体。过滤掉小于10×10像素的目标这样的标注对训练帮助不大反而会引入噪声。存在明显运动模糊、失焦的图片直接丢弃不要硬标。数据划分我采用7:2:170%训练、20%验证、10%测试。注意所有增强操作翻转、旋转、缩放、HSV扰动、马赛克只对训练集做验证集和测试集必须保持原始分布否则评估结果完全不客观。我这里还有个小习惯把同一场地不同航线的图片尽量放在同一分片里避免模型通过背景纹理“作弊”式地提升成绩。数据规模方面我的经验是每类起步1500到2000个实例5个类总共8000到10000个框时第一版模型的mAP0.5基本能到80%上下。低于这个量级也可以训但漏检会明显偏多。3. YOLOV11环境配置与训练实操3.1 零基础也能跟上的环境搭建我理解很多读者是真小白听到“深度学习环境配置”就头大所以我直接把我的安装过程完整复述一遍。需要说明的是这一步踩坑率特别高我因为CUDA版本不对、PyTorch装错浪费过两天时间。第一步安装Python。我用的3.10版本和Ultralytics的兼容性非常稳。建议直接用Miniconda创建独立环境不要让项目级依赖污染系统Python。创建环境的命令是conda create -n yolo python3.10然后每次跑实验前激活环境即可。第二步安装PyTorch。这里最关键的是CUDA版本匹配。在命令行输入nvidia-smi查看右上角的CUDA版本然后去PyTorch官网选择对应版本安装。我这边是CUDA 11.8装的是torch 2.0.1跑得没有任何问题。最稳的方式是用官网生成的那条pip命令不要自己凭感觉装。第三步安装Ultralytics。直接在激活后的环境中执行pip install ultralytics。我要强调一点不要装CPU版PyTorch航拍数据集的训练量虽然不算大但用CPU训练YOLOV11简直是灾难一个epoch能跑一天。显卡方面至少8GB显存起步推荐12GB以上。我用的是RTX 3060 12GB训练640分辨率、batch-size 8整体体验还算流畅。环境配置完后可以用一行命令简单验证yolo predict modelyolo11n.pt sourcehttps://ultralytics.com/images/bus.jpg。如果这行命令能正常跑出一张带预测框的图片说明环境基本OK了。3.2 数据集配置文件和训练命令环境装好之后先把数据集整理成YOLO格式。目录结构如下datasets/ ├── ground_garbage/ │ ├── images/ │ │ ├── train/ │ │ ├── val/ │ │ └── test/ │ └── labels/ │ ├── train/ │ ├── val/ │ └── test/每张图片对应一个同名txt文件每一行代表一个目标框类别ID、归一化中心x、归一化中心y、归一化宽度、归一化高度。然后创建一个data.yaml内容大概下面这样path: /home/yourname/datasets/ground_garbage train: images/train val: images/val test: images/test nc: 5 names: [plastic, paper, metal, glass, fabric]这里有个细节值得注意YOLO格式要求坐标是归一化的很多人第一次跑训练发现Loss不下降就是坐标忘记除以图片宽高了。训练命令也很简单yolo detect train dataground_garbage.yaml modelyolo11s.pt epochs100 imgsz640 batch8 device0 projectruns nameexp1我用的是yolo11s的预训练权重。不直接推荐用yolo11n因为它为了极致速度牺牲了精度在航拍小目标上表现很吃力也不推荐一上来就上yolo11x训练慢、部署难后期大概率还得蒸馏回来没必要。yolo11s是精度和速度最平衡的起步选择。3.3 关键训练参数怎么调超参数这块是很多人的知识盲区。我按实际操作中最重要的几个讲。imgsz是影响最大的参数。640能跑但在航拍任务里小目标多我建议条件允许就上1280。分辨率提升带来的是实打实的小目标结果改善代价是显存翻了两倍多。我的做法是先用640跑通全流程最后用1280做精度冲刺。epochs方面我的经验是100轮起步。航拍数据集通常只有几千张模型很容易出现过拟合所以早停法要开着Ultralytics默认会监控验证集loss连续patience轮没改善就停下来并自动保存最佳权重。先跑到150轮也不会浪费太多时间反正它会自己停。batch大小直接受显存限制。显存报错时优先减小batch而不是减小图片尺寸。我测试过batch从16降到8对精度影响微乎其微但图片从640降到320精度明显下降。优化器我直接用Ultralytics默认的SGD它内置了合理的动量参数。有些人一上来就换AdamW其实对YOLO系列来说收益有限甚至容易在训练后期震荡。老老实实用默认设置比频繁改参数效果好得多。3.4 训练日志怎么读训练过程会输出一张表格里面包括epoch、训练loss、验证loss、P、R、mAP50、mAP50-95这些指标。我教大家一套最简单的判断方法。看训练loss和验证loss是否同步下降如果训练loss一直降、验证loss在某个epoch开始反弹那就是过拟合明显标志是模型对训练集“背熟了”但没有泛化能力。看mAP50这个指标表示检测框和真实框的IoU超过0.5就算预测正确。对小目标密集的航拍场景来说mAP50能上80%已经很能说明问题了。mAP50-95变化趋势更重要但也更严苛对低分辨率小目标极不友好涨得慢是正常的不用因此焦虑。损失曲线的图片保存在runs/exp1目录下和训练日志配合看能让你快速定位训练是否健康。4. 无人机端部署与推理优化4.1 模型导出的细节训练完之后模型要部署到无人机端或地面边缘设备上。导出流程我用的是yolo export modelruns/exp1/weights/best.pt formatonnx imgsz640 opset12导出后再用TensorRT进一步转换为engine格式trtexec --onnxbest.onnx --saveEnginebest.engine --fp16TensorRT的FP16推理在Jetson平台上是标配。我实测同一个模型在Jetson Orin Nano上纯PyTorch推理只有8到10 FPSFP16优化后能跑到25 FPS以上。差距就是这么大别怕麻烦一定要转。在上一步导出过程中我会做一次计算图简化把NMS后处理留在推理脚本里不写进模型文件因为TensorRT对动态NMS支持不稳定还容易爆显存。4.2 航拍小目标检测的优化手段第2节说过航拍最大痛点是目标小。训练阶段的分辨率只是第一步部署阶段我试过最有效的手段是切图推理也常被称为Tile或SAHI方法。思路不复杂把一张大图切成若干有重叠的Patch比如把1920×1080切成6个640×640的块每块单独过模型最后把结果合并到大图的坐标系上重叠区域用NMS去重。这样做相当于变相放大了小目标的像素占比降低了对模型输入分辨率的压力。实测下来用切图推理配合640输入的模型检测效果能追平甚至超过直接1280输入而且单张图的显存消耗更可控。具体操作上我强推SAHI这个开源库它对Ultralytics的YOLO系列做了原生适配。跑起来的核心逻辑是先初始化切片预测再对结果做合并接口封装得很好。当然切图也有代价推理次数变多了速度下降。所以实战中我会根据地物复杂度决定切不切空旷草地不切复杂工业园区切。另一个方向是给模型增加注意力机制比如在颈部拼接HCANet这类高分辨率特征增强模块。我看过一些论文复现结果确实能提升小目标的召回率但代价是参数量和计算量同步上升。如果算力不是瓶颈你可以试如果在机载端跑我劝你先考虑切图后考虑加模块。4.3 机载端推理与数据回传方案整个系统分两种形态。第一种是机载实时检测无人机飞控端直接运行轻量模型检测结果实时回传地面站。第二种是离线处理无人机只负责采集数据落地后再放到工作站批量分析。很多实际项目离线处理已经够用而且能省下大量机载端的预算。我自己的系统把两条路都留了接口。机载端优先尝试在Jetson系列或RK3588这类带NPU的板子上跑TensorRT功耗和体积都满足挂载要求。如果你刚开始做我建议先在桌面端把离线批量检测跑通再考虑往机载端迁移一步到位容易崩。篮球场模拟器的话我自己没有深入折腾过凤凰无人机模拟器这类工具但如果你想在室内练好飞行手法再出门飞模拟器确实是零成本试错的最好方式。毕竟检测算法再准飞机飞不稳都是白搭。飞行任务设计方面我会固定检测区域设置重叠率30%左右的航线覆盖保证每块地面至少被两张不同角度的图像捕捉到。航线重叠在视觉检测里非常重要能大幅减少漏检代价只是飞行时间增加一些。图像回传我用的是两个方案实时图传通过RTMP推到地面工作站做流式推理保险起见SD卡同时存储原片用于后处理复核。5. 常见问题与排查技巧实录我把做这个项目过程中踩过的坑和朋友圈子里高频遇到的问题汇总成下面这张速查表里面每一行我都亲自验证过。症状可能原因解决方案训练一开始loss就爆高或NaN学习率过大、数据标注存在非法坐标调低学习率到0.001检查txt中是否有超出0到1范围的坐标验证集mAP极低但训练集mAP很高过拟合或者数据划分泄露检查训练/验证集是否同场景串了给模型提供一点DropOut余地大垃圾很准小目标几乎全部漏检输入分辨率太低或没有切图imgsz提升到1280或用SAHI切图推理无人机飞行画面检测框乱跳抖动导致单帧误检加时间序列过滤连续多帧出现才输出报警框同一片垃圾换个光照角度就检测不到数据多样性不足补充不同时段、逆光、阴影数据做HSV增强TensorRT推理结果和PyTorch结果差异大FP16精度损失尝试保留FP32或对敏感层用FP16中间层混合精度机载端发热降频严重长时间满负荷推理降低帧率、错峰推理板子主动散热加装检测出大量石头/树影的误报背景干扰太强、负样本不足专门采集无垃圾的纯背景图加入训练或者加背景分类头做二次过滤这里我多说两个细节。关于负样本很多人只盯着“有垃圾的图片”猛标结果模型在“没有垃圾但有树影、水渍”的画面上疯狂误报。我在数据集中专门加了20%左右的无垃圾背景图类别标签为空训练时模型对这类“硬负样本”有了抑制能力误报率明显下降。关于检测框抖动这在无人机实时画面上特别影响观感。我加了一个简单的时间滤波只在连续三帧中出现同区域目标才框出来正常单帧烟尘、反光造成的误检会被瞬时过滤。这个逻辑非常简单但对用户体验的提升比再调一轮模型参数还大。还有一个很多新手容易忽略的点标注一致性。多人协作标注时有的喜欢把垃圾框得严丝合缝有的喜欢多留一个像素边距这两者混在一起会导致模型学到的框回归目标不一致定位精度上不去。我后来在标注规范里明确规定贴合目标轮廓外扩不超过2个像素。就这么一个细节让定位精度提升了一截。6. 后续还能怎么玩这套系统跑通之后扩展方向其实非常多。我自己的下一步打算是把检测结果叠加到二维地图上生成一张垃圾密度热力图这样巡检人员只看地图就能安排清理优先级比看一堆检测框直观得多。实现方案是用无人机POS数据做图像映射把检测框中心点投影到地图坐标这一步需要用到相机内参和云台姿态角的矫正稍微有点技术门槛但非常值得做。另一个值得尝试的方向是结合多光谱或者红外相机在夜间或者复杂背景下检测效果会比单一可见光好很多。不过相应要解决的算法适配、飞控挂载、供电问题又多了一圈建议大家先把基础版做扎实再往上叠加。最后说一个我踩过多次的坑不管模型离线测得多好第一次上飞机跑真机推理一定要先做小范围悬停测试再放出去飞固定航线。机载端的光照、振动、散热、内存占用情况和你的台式机完全是两码事。先把姿态稳住、图传通好、推理跑起来再逐步加大飞行半径这种循序渐进的方式能帮你少炸几台机器也少熬几个夜。祝各位的无人机地面垃圾检测系统早日跑通落地让代码真正飞上天。