拓冰建站拓冰建站
首页 / 资讯中心 / 正文

无人机多目标识别实战:基于ResNet的深度学习检测与部署

项目概述给无人机装上“会认人”的眼睛这几年一直在折腾无人机视觉感知方向的项目从单纯的航拍图像拼接、正射影像生成到后来转向实时目标识别踩过不少坑也积累了一些比较落地的经验。这次要聊的这个项目核心任务很明确让无人机在飞行过程中对地面或空中的多个目标进行实时识别和定位而算法骨架选的是深度残差网络ResNet系列。之所以专门写一篇博客来复盘这个项目是因为无人机视角下的多目标识别和普通安防摄像头场景完全不是一回事——它要应对高度变化、视角剧烈抖动、目标尺度跨度大、算力受限等一系列问题。如果你是做无人机应用开发、计算机视觉算法落地或者正在纠结怎么给自己的无人机平台加上识别能力这篇文章应该能帮你省下不少走弯路的时间。项目最初的需求来自一个“低慢小”无人机防御演示系统需要无人机在巡检过程中识别出视野里出现的其他无人机并触发告警。后来扩展到了地面车辆和行人的多目标识别。整个系统的核心链路是——机载相机采集视频流经过深度残差网络构成的目标检测模型实时推理输出目标的类别和位置信息再叠加到图传画面上或者触发声光告警。整个项目里模型选型、数据准备、训练调优、边缘端部署每一环都有很多细节值得展开讲。1. 整体设计与技术选型为什么是深度残差网络1.1 无人机视角下的目标识别难在哪先说一个最直观的感受无人机飞在100米高空往下看一辆汽车只有几十个像素大飞到300米人基本就是个点。这和手机拍照、监控摄像头完全是两种场景。无人机视角下的目标识别主要难在四个地方。第一是目标尺度跨度极大。同一帧画面里可能近处有一架无人机占了1/4画面而远处500米外另一架无人机只有20像素。固定分辨率的检测头很难同时兼顾这两种极端尺度。第二是运动模糊和抖动。无人机本身在飞电机振动、气流扰动都会让画面出现模糊特别是在低空悬停或者快速转向的时候运动模糊会直接毁掉小目标的纹理信息。第三是视角变化剧烈。无人机在空中俯拍目标呈现的是顶视角但有时候需要侧视跟踪同一个目标在不同角度下外观差异非常大。第四是计算资源限制。机载设备通常是Jetson Nano、Jetson Orin NX这样的嵌入式平台功耗和算力都是有限的不是随便塞一个大模型就能跑起来的。1.2 深度残差网络的核心优势在目标检测领域骨干网络Backbone决定了特征提取能力的上限。从VGG、GoogLeNet到ResNet再到后来的EfficientNet、Swin Transformer选择很多。但综合无人机场景的约束条件ResNet系列是最稳妥的选择。ResNet的核心创新是引入了残差连接也就是在卷积层堆叠的同时增加一条从输入直接到输出的“捷径”。这样一来网络在反向传播时梯度可以通过捷径直接流回浅层解决了深层网络退化问题。通俗点说普通网络在层数加深到一定程度后训练误差反而会上升这不是过拟合而是优化困难残差结构把优化目标从“学习一个完整的映射”变成了“学习一个残差修正”后者要容易得多。在无人机场景里选ResNet还有几个非常现实的原因。第一ResNet有成熟的预训练权重在ImageNet上训好的模型可以直接迁移到无人机数据集上做微调这对标注数据稀缺的团队来说至关重要。第二ResNet结构规整无论是TensorRT加速还是ONNX导出兼容性都很好部署的时候省心。第三ResNet-50、ResNet-101的模型大小和推理速度匹配机载GPU平台的算力窗口精度和速度能达到一个比较理想的平衡点。1.3 检测框架选择两阶段还是单阶段选定了骨干网络之后接下来要决定的是检测头。目前主流的目标检测框架可以分成两派以Faster R-CNN为代表的两阶段检测器和以YOLO、SSD为代表的单阶段检测器。两阶段检测器先通过区域建议网络RPN生成候选框再进行二次分类和回归精度高但对算力要求也高在机载设备上很难做到实时。单阶段检测器直接回归目标类别和位置速度快但小目标检测能力普遍偏弱。这次项目里我在模型选型上做了一个折中主力模型用Faster R-CNN ResNet-50 FPN同时保留了一套YOLOv8的备用方案。为什么这么选因为“低慢小”无人机目标确实太小了单阶段检测器在远距离小目标上的召回率不够理想而两阶段检测器配合特征金字塔网络FPN能明显提升小目标的检出能力。代价是推理慢一些但通过TensorRT的FP16优化在Orin NX上还是能跑到20帧左右满足了演示系统的需求。2. 数据准备与标注策略一切精度问题的根源2.1 开源数据集怎么选、怎么补训练数据是整个项目里最耗时也最决定成败的环节。无人机视觉感知这个领域开源数据集并不算多而且分布比较分散。我调研和实测用过的主要有这几个VisDrone是天津大学开源的无人机视角数据集包含车辆、行人、自行车等多个类别标注很规范场景覆盖城市、乡村、高速公路等是训练地面目标识别的主力数据源。UAVDT是无人机检测跟踪数据集主要关注车辆晴天和多云天气的照片都有适合做车辆识别的补充。UCAS-AOD包含车辆和飞机两类目标参与标注的飞机包括客机和无人机尺度变化比较大。Anti-UAV数据集是新出的专门针对无人机目标用红外和可见光两种成像方式对“低慢小”目标检测非常有用不过公开部分的标注精度需要自己清洗一遍。但纯用开源数据是不够的。原因很简单无人机目标在不同背景下外观差异极大而且真实作战中的“低慢小”无人机比如多旋翼小型机在开源数据集里数量很少。所以这个项目里我花了不少时间自采数据用另一架无人机悬停在多个高度20米、50米、100米、150米以不同角度拍摄目标无人机覆盖逆光、顺光、阴天、黄昏等光照条件一共采集了约8小时视频抽帧后得到1.2万张有效图片。2.2 标注工具与质量控制的细节标注工具用的LabelImg和X-AnyLabeling前者轻量后者支持半自动辅助标注效率高一些。但工具只是基础真正影响模型效果的是标注规范的一致性。我踩过的一个典型坑是标注框到底是紧贴目标还是四周留余量。如果多人协作标注标准不统一模型回归出来的框就会飘。后来我定了两条硬性规定一是标注框必须紧贴目标可见边缘留残不超过2个像素二是目标小于16像素的一律不标注小于这个尺寸人眼都很难确认硬标进去只会给模型制造噪音。另外遮挡超过70%的目标不标这也是为了减少训练数据里的不确定性。还有一个容易被忽视的问题样本均衡。无人机目标在整个数据集里占比可能只有5%如果不做处理模型会严重偏向地面车辆和行人。我的做法是对包含无人机目标的图片做离线增强复制粘贴增强和MixUp让无人机类别在每批训练数据里的占比提升到20%左右。这样既不动原始数据分布又能有效缓解类别不均衡。3. 模型训练全过程与关键参数解读3.1 环境配置与训练框架训练用的机器是一台双卡RTX 3090的工作站深度学习框架用PyTorch检测库用MMDetection。选MMDetection而不是纯手写训练脚本是因为它把Faster R-CNN、FPN这些经典结构的实现都封装好了配置改起来方便而且自带了很多训练技巧的官方实现不需要自己造轮子。训练环境的版本组合建议直接参考MMDetection官方文档这里给一个亲测稳定的组合# CUDA 11.3 # PyTorch 1.11.0 # mmcv-full 1.5.3 # mmdetection 2.25.0 pip install torch1.11.0cu113 torchvision0.12.0cu113 pip install mmcv-full1.5.3 -f https://download.openmmlab.com/mmcv/dist/cu113/torch1.11/index.html pip install mmdetection2.25.03.2 骨干网络初始化迁移学习的重要性一个新手容易犯的错误是直接从随机初始化开始训练整个网络。在只有几千张图片的数据集上这么做几乎必然导致训练发散或者严重过拟合。正确的做法是加载ResNet-50在ImageNet上的预训练权重然后做“冻结训练解冻微调”两步走。具体操作分为两个阶段。第一阶段冻结骨干网络的所有层只训练检测头和FPN部分学习率设为0.005跑30个epoch。这个阶段的目的是让检测头在骨干网络已经能提取出有效特征的基础上快速学会目标分类和框回归。第二阶段解冻骨干网络的最后两个Stage即layer3和layer4把学习率降到0.0005再跑20个epoch。之所以解冻最后几个Stage而不是全部是因为浅层网络学到的是边缘、纹理这些通用特征冻结它们可以防止灾难性遗忘而深层特征与具体任务相关微调它们能让模型适应无人机视角下的特殊分布。这样一套组合拳做下来收敛速度比全部解冻快了约两倍最终mAP也更高。3.3 训练超参配置与Loss曲线解读我用MMDetection训练的核心配置如下关键参数节选model dict( typeFasterRCNN, backbonedict( typeResNet, depth50, frozen_stages2, init_cfgdict(typePretrained, checkpointtorchvision://resnet50)), neckdict( typeFPN, in_channels[256, 512, 1024, 2048], out_channels256, num_outs5), rpn_headdict( typeRPNHead, anchor_generatordict( typeAnchorGenerator, scales[2, 4, 8, 16, 32], ratios[0.5, 1.0, 2.0], strides[4, 8, 16, 32, 64]), ... ) ) data dict( samples_per_gpu8, workers_per_gpu4, traindict( typeRepeatDataset, times3, datasetdict( typeCocoDataset, pipeline[ dict(typeLoadImageFromFile), dict(typeLoadAnnotations, with_bboxTrue), dict(typeResize, img_scale(1333, 800), keep_ratioTrue), dict(typeRandomFlip, flip_ratio0.5), dict(typeNormalize, mean[123.675, 116.28, 103.53], std[58.395, 57.12, 57.375]), ... ]))) optimizer dict(typeSGD, lr0.005, momentum0.9, weight_decay0.0001) lr_config dict( policystep, warmuplinear, warmup_iters500, warmup_ratio0.001, step[20, 30]) total_epochs 50有几个参数值得展开说说。Anchor尺度的选择是经过实测调整的。默认Faster R-CNN的Anchor是[0.5, 1, 2.0, 4, 8, 16, 32]这组但无人机视角下很多目标特别小而且目标的宽高比比较集中地面车辆的俯视宽高比大概在1.5:1到2.5:1之间所以我把Scale从8起步往小方向多加了2、4两档长宽比去掉了0.5保留[0.5, 1.0, 2.0]。这个改动对小目标的召回率提升非常明显。Batch Size设的是8单卡4张、双卡并行输入尺度是长边不超过1333、短边不低于800。这里需要强调一下不要为了迁就小目标而把分辨率调得过高否则显存会爆炸。如果你用的是Jetson平台训练不推荐建议把输入尺度降到800x600。训练过程中的Loss曲线我记录了几条经验前500个迭代是warmup阶段Loss下降会很快这是正常的不要因为前几个epoch的Loss波动就慌。RPN_Loss和Cls_Loss如果持续震荡不下降基本是学习率过高或者Anchor配置不匹配。如果训练后期验证集mAP不再上升但训练Loss还在降那就是过拟合了需要提前停止或者加大数据增强。3.4 评估指标怎么看模型效果好不好目标检测的评估指标主要看mAPmean Average Precision细分的话要看不同IoU阈值下的AP。在这个项目里我重点关注两个指标APIoU0.5和APIoU0.75。前者看的是“检不检得到”后者看的是“框得准不准”。实测下来用上述配置训练的Faster R-CNN ResNet-50 FPN模型在自建测试集上的结果是目标类别APIoU0.5APIoU0.75备注无人机87.3%68.2%目标尺度小框精度还有提升空间车辆92.1%81.5%数据充足效果最稳行人76.4%55.7%小目标遮挡双重挑战整体mAP0.5大约在85.2%左右。这个水平对于演示系统来说已经够用了但距离“高可靠低误报”的实战要求还有距离。后期针对无人机类别的漏检案例做了专项数据补充AP又提升了大概3个百分点。4. 多目标识别与机载部署的工程化4.1 多目标识别中的NMS参数调优模型输出的原始预测框数量非常多同一目标周围可能围绕十几个置信度不等的框需要用非极大值抑制NMS来过滤。NMS的核心逻辑是按置信度从高到低排序保留得分最高的框然后删除与它IoU超过阈值的其他框重复这个过程直到处理完所有候选框。NMS的IoU阈值是一个需要小心调的参数。阈值设得太低比如0.3两个紧密相邻的不同目标可能被误删一个阈值设得太高比如0.8同一目标周围的重复框清理不干净。在无人机多目标场景里由于目标之间经常有遮挡和接近我把NMS的IoU阈值设为0.5置信度阈值设为0.35效果比较均衡。另外要特别提一个多类别NMS的细节如果你的检测器支持多类别输出默认的NMS是逐类别做的。但当两个不同类别的目标重叠严重时比如一辆车上面站了一个人逐类别NMS会同时输出两个框这在某些场景下会造成误判。我在部署代码里改成了跨类别NMS让重叠度很高的不同类别框也参与抑制这样能减少一部分重复告警。4.2 针对小目标的推理优化技巧即使有了FPN小目标仍然是无人机视觉感知里最难啃的骨头。在推理阶段我做了两个比较有效的优化。第一个是Tiling切图推理。把大图切分成有重叠的若干小图块每块单独推理再把结果合并。这个方法对小目标非常友好相当于提高了目标在输入分辨率中的占比。在Jetson Orin NX上我把1080P视频切分成2x2的图块每块约720x540重叠率10%小目标的召回率提升了近15个百分点代价是推理耗时增加了约1.5倍。对于实时性要求不高的巡检场景这个代价可以接受。第二个是多尺度测试Multi-Scale Testing。推理时同时用原始尺度、0.5倍尺度和1.5倍尺度各推理一遍把结果合并。0.5倍尺度有助于检出大目标1.5倍尺度有助于检出小目标。这个操作只推荐离线处理视频时用实时推理时的计算量直接翻三倍不划算。4.3 TensorRT加速与嵌入式平台部署模型训练完成后部署是另一个大坑。我最终的目标平台是NVIDIA Jetson Orin NX算力大约100TOPS听起来还不错但跑原生的PyTorch模型远达不到实时。部署流程是PyTorch模型导出为ONNX → 用TensorRT构建推理引擎 → 在Jetson上运行。具体命令大致如下# 导出ONNX python tools/deployment/pytorch2onnx.py \ configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py \ work_dirs/faster_rcnn_r50_fpn/epoch_50.pth \ --output-file faster_rcnn_r50.onnx \ --input-img demo/demo.jpg \ --shape 800 1333 # 构建TensorRT引擎在Jetson上执行 trtexec --onnxfaster_rcnn_r50.onnx \ --saveEnginefaster_rcnn_r50.trt \ --fp16 \ --maxShapesinput:1x3x800x1333这里需要注意一个细节TensorRT默认用静态输入尺寸但视频流的宽高往往是固定的所以问题不大。如果你需要处理动态分辨率就要设置动态Shape复杂度会高很多。我的做法是直接固定推理尺寸为960x544这是一个在检测精度和速度之间比较折中的分辨率省掉动态Shape的麻烦。FP16量化后Faster R-CNN ResNet-50 FPN在Orin NX上的推理速度从原来的6帧提升到了22帧左右精度损失大约只有0.5个百分点完全在可接受范围内。4.4 机载端到端系统的协同工作模型部署完成只是第一步真正让整套系统跑起来还涉及相机接入、图像预处理、识别结果叠加、告警触发、图传推流这些周边工作。这里分享一下我搭建演示系统时的整体架构思路。机载端跑一个主程序用GStreamer管道从摄像头拉取RTSP流解码成BGR图像后缩放到推理尺寸送入TensorRT引擎推理得到目标框和类别后映射回原图坐标再叠加到原始画面上。同时当某个类别的目标比如无人机连续3帧以上都被检测到且置信度超过0.5就触发告警向地面站发送告警消息并弹出弹窗提示。这里有个细节容易踩坑GStreamer解码出来的图像是NV12格式需要先转换成BGR再送入TensorRT而这个转换在Jetson上可以用GPU加速。如果直接用CPU做颜色空间转换1080P视频大概要占掉2-3毫秒看似不多但在抠帧率的时候就很难受了。我用的是Jetson自带的v4l2视频采集插件配合CUDA进行转换帧率稳定在24帧以上。5. 常见问题与排查技巧实录5.1 小目标大面积漏检怎么办漏检是最常见的问题现象是模型对大目标识别很好但离得远的小目标基本不输出框。排查思路依次是检查Anchor配置Anchor最小尺度是否覆盖了小目标的像素尺寸。可以用脚本统计训练集里所有目标框的面积分布然后把Anchor的最低档设置到略小于最小目标的中位数。检查输入分辨率分辨率太低会导致小目标在特征图上只有不到一个像素。适当提升输入尺度但要注意显存占用和速度损耗。检查特征图输出用特征图可视化工具看看FPN的浅层特征里是否还有小目标的响应。如果浅层特征响应很弱说明骨干网络在下采样过程中丢掉了小目标的信息这时候可以在FPN增加浅层融合权重或者使用Dilated/ASPP结构增强感受野。5.2 误检率高、频繁告警烦死人误检在演示场景里比漏检更尴尬——时不时对着空荡荡的天空叫一声。我遇到过两类典型情况。一类是背景误检。无人机目标在天空背景下容易把远处的鸟、风筝、甚至云朵边缘误检成无人机。解决思路是给检测器加上“负样本”数据专门收集大量不含无人机的天空、地面建筑图片标注为空标签参与训练让模型见过更多“什么都不是”的背景样本。另一类是高置信度误检。模型对某些纹理密集区域比如树冠、屋顶输出了很高的置信度但人眼一看就知道是背景。这种情况通常是类别特征不够鲜明可以通过在Loss里加入中心度惩罚Center-ness或者引入基于时序的确认机制来缓解——同一目标必须连续多帧被检测到才告警。5.3 推理速度不达标帧率只有个位数速度问题是部署阶段绕不开的坎。帧率上不去先看瓶颈在哪里模型尺寸太大ResNet-101相比ResNet-50mAP提升不到2个点但推理耗时增加约50%。如果不是对精度有极端要求机载端建议优先选择ResNet-50。输入分辨率过高模型推理耗时近似正比于输入像素数从1333x800降到960x544推理速度能快约1.8倍而精度损失可控。后处理耗时过大NMS如果是在CPU上跑的当检测目标数量多时会成为瓶颈。TensorRT的NMS插件是在GPU上执行的强烈建议优先启用。5.4 训练时Loss不收敛的几个排查点训练过程不收敛常见原因其实就几类学习率过高表现为Loss剧烈震荡、Anchor设置与数据分布严重不匹配RPN Loss降不下去、标注数据存在大量错误分类Loss在某个数值附近卡死、Batch Size太小导致BN统计量不稳定。其中最简单有效的自查方法是先选一个样本子集几百张图用小学习率做十来个迭代看看Loss能不能降下来。如果子集上能正常收敛再逐步恢复到大数据集和正常学习率。6. 经验心得与后续扩展方向这个项目做下来我的核心体会是模型选型虽然重要但真正决定项目上限的往往是数据质量和工程细节。ResNet-50 FPN这个组合谈不上炫酷但配合精心整理的数据、合理的训练策略和TensorRT优化在实际效果上并不输给那些结构更花哨的模型。对于嵌入式端的目标识别稳定可靠远比“刷榜”重要。最后再分享一个小技巧在调试阶段强烈建议把所有检测结果包括置信度低于告警阈值的都可视化保存下来。很多误检漏检问题看单帧图是看不出来的但一旦你把检测热力图、特征响应图和实际场景叠加在一起回放问题就能一目了然。我就是靠这个方法快速定位到了FPN浅层特征对小目标响应不足的症结。这个项目后续还能往多目标跟踪方向扩展比如加入DeepSORT或ByteTrack让系统不仅能识别目标还能持续跟踪目标的运动轨迹这对于无人机巡检和安防场景会更有价值。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门