基于YOLOv8的无人机行人检测系统:从训练到TensorRT部署实战

发布时间:2026/10/18 3:14:26
基于YOLOv8的无人机行人检测系统:从训练到TensorRT部署实战
飞过一片开阔地的时候高空视角下行人就是一个个缓慢移动的彩色小点有时候一个路口几十个人混在树影、车顶和广告牌之间看不清楚轮廓。这个画面的难度和常规安防摄像头平视拍人的场景完全不在一个量级。我这次要分享的是一个完整可复现的基于YOLOv8的无人机行人检测系统从数据准备和模型训练开始一直做到TensorRT推理加速、边缘设备部署和实时监控联动。它适合正在做无人机巡检、应急救援、智慧城市这类方向的人也适合那些模型训练跑得通、一到部署就各种踩坑的边缘AI开发者。文章里不会只讲原理更多是我在实际落地过程中反复试出来的经验哪些参数真的有用哪些环节最容易拖垮整个系统的实时性。1. 项目概述与整体方案设计1.1 无人机行人检测的真正难点先说清楚一个问题为什么无人机行人检测不能直接照搬普通监控方案。地面摄像头的画面里行人通常占画面高度的20%甚至更多模型很容易提取到清晰的纹理特征。而无人机在30到100米高度巡航时行人只占画面很小的一块区域有时候一个目标才十几乘二十个像素连人脸和四肢轮廓都看不出来。其次视角差异非常大。普通数据集大多是平视或者略带俯角无人机是天顶视角和倾斜视角混合行人呈现出头顶、肩膀、背包这类特征和常规样本的分布差异明显。加上无人机飞行时的持续运动卷帘快门会带来运动模糊树冠遮挡、地面反光和复杂阴影也会把浅层特征搅得很乱。还有一个容易被忽视的问题是尺度分布极不均匀。同一帧画面里正下方行人大一些远处人行道上的行人可能只有三五个像素。模型在训练时如果没有针对性处理很容易只学到中等尺度目标小目标几乎全部漏检。这类场景下模型的mAP可能看起来还行但真正到了现场测试你会发现大量关键目标根本没被框出来。1.2 技术选型背后的取舍目标检测框架我对比过YOLOv5、YOLOv8和RT-DETR。YOLOv5在边缘端部署上已经很成熟但它的anchor机制在尺度变化极大的无人机场景里需要反复调anchor尺寸实际操作中非常费时间。RT-DETR精度上限高但Transformer结构在Jetson这类边缘设备上算子融合效率一般实时性反而不占优势。最终选YOLOv8核心原因是anchor-free加解耦头的设计在小目标场景下更省心不需要手动调整anchor模型也能自适应不同尺度的目标分布。更关键的是YOLOv8的导出生态非常顺滑PyTorch到ONNX再到TensorRT的链路几乎没有阻碍这对工程化部署来说是实打实的优势。对比维度YOLOv5YOLOv8RT-DETR小目标适应能力中等依赖anchor配置好anchor-free无调参好TensorRT部署难度简单简单中等算子较复杂边缘端推理速度快快一般后处理复杂度NMSanchor解码解耦头NMS无NMS但后处理模式不同工程生态成熟度高高中实际项目里我用的是YOLOv8s作为主力模型在算力更紧张的低功耗设备上才切换到YOLOv8n。如果你对漏检率要求极高可以尝试YOLOv8m但对应推理延迟会上涨明显需要在自己的硬件上实测权衡。1.3 端到端系统架构设计这个系统的整体链路我按照“机载轻量检测加地面深度解析”的双段架构来做。无人机端负责视频采集、基础图像处理和一部分轻量检测地面端负责接收传输回来的视频流做完整的推理、跟踪和业务规则判断。整条链路分为五个阶段视频采集与编码、传输、解码、推理与后处理、业务联动。无人机端通过机载摄像头采集画面编码成H.265视频流后通过图传链路发送到地面站。地面站拉流解码后送入TensorRT加速的YOLOv8推理模块拿到检测框后送入多目标跟踪模块再由业务规则引擎判断越界、停留、人数超标等情况触发告警并存储关键帧。为什么不把全部推理放到机载端因为边缘设备的算力和功耗有限长时间悬停作业时电池续航压力很大。无人机端只做轻量预处理地面站做重推理整体延迟还是可以控制在几百毫秒以内同时机载负载明显下降。如果你用的是大载重的工业级无人机机载端直接跑YOLOv8s也没有问题这就看实际算力余量来取舍。2. 数据准备与模型训练实战2.1 训练数据从哪里来、要多少无人机场景的数据和普通行人数据集差异太大所以数据准备是整个项目里最关键的一步。我参考了公开的VisDrone和UAVDT这类无人机航拍数据集选择其中行人相关类别作为基础训练集然后针对自己任务的飞行高度和要求做了定向补充采集。自采数据时我在城市道路交叉口、建筑工地、停车场和广场这类典型场景各采集了几段巡航视频。采集时特意覆盖不同时段中午强光、傍晚逆光、阴天阴影也故意让无人机做了原地悬停、缓慢推进和快速转向几个动作目的是让模型见识到不同运动模糊程度下的行人形态。数据量方面我给一个比较实用的参考基础训练集加自采数据合计5000到8000张图像标注目标数在1到2万之间比较稳妥。如果目标数量太少模型会把大量注意力放在误检背景上效果很差。数据量到这个程度配合合理的增强策略模型基本能收敛到可用的状态。2.2 标注质量和清洗的关键细节标注质量决定了模型上限我在这上面踩过的坑最多。第一不要放弃小目标。面积小于16乘16像素的行人只要人能辨认出来就必须标注。模型训练时配合针对性增强小目标学习能力会明显提升如果这些目标不标相当于主动教模型忽略小目标。第二严重遮挡和模糊目标按照“能看到多少标多少”的原则处理标出可见部分即可不要硬标一个完整的大框把遮挡物也圈进去。第三截断目标也要标比如画面边缘只有半个身子的人标注完整身体范围但允许超出图像边界。标注完成后一定要做数据清洗。我遇到过标注框坐标超出图像范围、类别标签打反、重复标注等问题这些脏数据不清理训练时会带来明显的振荡。用标注工具自带的校验功能检查一轮再抽样人工复核标注质量基本就有保障了。2.3 训练配置与超参数调优思路训练我基于YOLOv8官方实现来做。基础预训练权重用的yolov8s.pt图像尺寸从640x640起步训练150轮。等模型基本收敛后再用1280x1280的高分辨率微调30轮左右。这个策略对无人机场景尤其有效640输入让模型先学会全局特征1280微调则给了小目标充分的学习空间。个人训练参数参考如下yolo train modelyolov8s.pt datauav_person.yaml imgsz640 epochs150 batch16 lr00.01数据增强保持Mosaic、Mixup和随机仿射变换开启但要注意把close_mosaic设置到最后10轮关闭否则最后几轮模型会一直在看拼接图导致真实分布上的表现不稳定。训练过程中主要盯box_loss、cls_loss和dfl_loss三条曲线如果后段出现严重震荡先检查学习率和batch大小是否匹配再看数据增强参数是不是太激进。对小目标场景我用了一个比较激进的重采样方式按目标面积对样本做加权让包含大量小目标的图像在每轮训练中出现得更频繁。这个操作比单纯堆数据集效果更直接小目标的召回率能提升几个点。2.4 评估指标怎么定才贴近真实场景常规mAP50和mAP50-95肯定要看但对无人机场景我还单独按目标面积统计了sAP面积小于32乘32像素的行人检测精度。你可以把它理解为小目标专项分数这个指标比整体mAP更能反映实际飞行高度下的可用性。评估时有个容易做错的地方划分测试集不能随机抽样。无人机拍摄的视频帧之间高度相关随机抽样会让同一段视频的画面同时出现在训练集和测试集里评估结果虚高。正确做法是按时间段或场景划分比如把一段完整航线前80%的视频帧做训练、后20%做测试测试集里全是模型没有见过的连续画面。3. 模型压缩与推理加速3.1 为什么必须做TensorRT加速PyTorch模型如果直接跑在Jetson设备上推理速度根本撑不起实时监控。PyTorch的动态图机制在边缘端开销很大算子执行也缺乏融合优化。TensorRT会把模型编译成面向特定GPU架构的推理引擎通过层融合、精度校准、内核自动调优等手段大幅减少延迟。对于YOLOv8s模型在Jetson Orin NX这类设备上PyTorch FP32推理大概只有20到30毫秒一帧听起来不算慢但加上解码和后处理多路视频流场景就撑不住了。转成TensorRT FP16后单帧推理能压到10毫秒附近INT8则更快。这个提升对实时系统来说是决定性的所以工程化部署第一步就是建立完整高效的TensorRT转换流程。3.2 从PyTorch到TensorRT的转换全流程先导出ONNX再用trtexec构建引擎这是最直接也最稳的方式。导出时注意几个关键参数固定输入尺寸、显式指定batch大小、打开端到端模式或保留原始输出由自己实现后处理。yolo export modelyolov8s.pt formatonnx opset12 imgsz640导出后用trtexec构建FP16引擎trtexec --onnxyolov8s.onnx --saveEngineyolov8s_fp16.engine --fp16 --workspace2048一个常见坑是ONNX导出时如果没有固定batch构建的引擎可能只支持动态batch部署代码要手动处理增加复杂度。我一般直接在导出时固定batch为1推理代码里用batch1的方式逐帧处理稳定且没有额外开销。如果确实需要多batch就用动态shape并配合TensorRT的优化profile但部署代码复杂度会高不少没需要就别折腾。3.3 FP16与INT8量化实测对比在Jetson Orin NX上我用同一份验证集测了三种精度模式的指标和延迟精度模式推理延迟毫秒mAP50mAP50-95FP3219.60.9120.638FP169.80.9110.635INT86.80.8850.592FP16在精度几乎无损失的情况下速度翻倍实际部署的默认选择就是它。INT8需要准备200到500张具有代表性的校准图像这些图像要覆盖不同光照和场景否则量化会在大面积暗光或逆光画面上精度崩塌。如果项目对漏检要求很高我建议优先用FP16INT8留给算力严重不足或者并发路数很多的情况。4. 嵌入式平台部署与实时监控链路4.1 Jetson平台环境搭建的版本匹配问题部署硬件我以Jetson Orin NX为主选它是看中它在体积、功耗和算力之间的平衡。拿到设备后第一件事是装JetPack注意CUDA、cuDNN和TensorRT的版本必须和JetPack的版本严格对应。我在一台设备上遇到过JetPack 5.1带了TensorRT 8.5结果代码里调用了8.6才有的API编不过也跑不起来折腾了很久才发现是版本不匹配。装完系统后我建议直接用JetPack自带的基础镜像不要自己重装CUDA。自己装CUDA很容易覆盖掉系统预置的库导致TensorRT找不到依赖。基础镜像里这些组件已经相互测试过了省去大量环境配置时间。Conda或者Docker环境在Jetson上也能用但性能上多少有点损耗裸机环境往往是最优解。4.2 视频流接入与硬件解码策略无人机图传链路常见的视频流协议是RTSP和RTMP。直接让OpenCV从RTSP地址拉流做大分辨率H.265解码CPU占用会飙得很高而且连续运行一段时间后经常出现内存持续增长的问题严重时画面卡死。实际部署我用GStreamer管道来做硬解码把解码工作交给GPUCPU负载直线下降。一条实际可用的GStreamer拉流解码管道大致是这个模式gst-launch-1.0 rtspsrc locationrtsp://192.168.1.100/live ! rtph265depay ! h265parse ! nvv4l2decoder ! nvvidconv ! video/x-raw,formatBGRx ! videoconvert ! video/x-raw,formatBGR ! appsink在Jetson上nvv4l2decoder就是硬件H.265解码器。用这条管道替代OpenCV的VideoCapture延迟和CPU占用都有明显改善。部分老款无人机图传设备只支持H.264对应把rtph265depay换掉、解码器换成nvv4l2decoder处理H.264的版本即可管道整体思路不变。4.3 多线程模型与队列缓冲设计实时监控系统最怕解码线程拖慢推理线程或者推理慢导致解码端积压丢帧。我采用了解码、推理、后处理三个线程加环形缓冲队列的结构。解码线程不断从GStreamer管道取帧写入队列推理线程按固定节奏取帧做检测后处理线程负责NMS和业务逻辑。如果解码队列已经积压说明推理耗时超过解码帧率此时不能无限堆积缓冲否则延迟越来越大。我的处理方式很直接缓冲队列设定最大长度满了就丢弃最老的帧保证系统始终处理最新画面。这个“丢老帧保最新”的策略对实时监控至关重要即使推理偶尔抖动画面整体观感也保持流畅。4.4 业务监控逻辑跟踪、区域规则与告警联动检测框本身是离散的做实时监控必须配上跟踪模块否则同一个行人每帧都是新目标检测框会剧烈闪烁也没法做停留判断和人流统计。我选择ByteTrack因为它计算量小、对低置信度目标有一定容忍度非常适合边缘设备。跟踪结果出来后业务规则引擎负责具体事件判断。区域入侵使用射线法判断目标中心点是否落在用户绘制的多边形区域内拥挤度统计统计指定区域内的跟踪目标数量滞留检测则判断某个目标ID在区域内连续存在的时长是否超过阈值。告警联动方面我做了两级机制。第一级是实时告警区域出现越界或人数超标时立即保存当前帧并推送到监控大屏第二级是证据留存把告警前10秒的短视频片段保存到本地存储方便事后查证。这套组合在巡检场景里非常实用实际部署时客户最关心的不是模型精度有多高而是事件发生后能不能快速看到清晰的证据画面。5. 常见问题与排查技巧实录5.1 推理速度上不去瓶颈到底在哪很多人把推理速度慢直接归咎于模型太大但实测发现系统链路里最先出问题的往往是视频解码。我先让模型用空数据跑只测推理延迟单独测解码帧率再测完整链路三步定位出瓶颈位置。只要解码端CPU跑满了后续推理再快也没有用此时就要立刻切换到硬件解码方案。另一个容易忽略的问题是线程绑定和内存分配。TensorRT引擎推理时会申请GPU工作空间如果你频繁重建context或者在推理线程里反复分配CPU内存延迟会忽高忽低。处理方式是让推理线程长生命周期运行不要每帧都创建设备内存分配尽量复用。5.2 小目标漏检严重怎么解决模型收敛后如果小目标漏检集中我按顺序排查三件事。第一是训练分辨率是否足够如果之前用640立刻回退到1280微调看效果。第二是测试时是否做了切图把大图切成有重叠的图块分别检测再合并结果小目标效果明显。第三是数据层面小目标占比是否过低如果是就用重采样或者复制粘贴增强来平衡。在1280输入加小图切块的组合下实际测试中小目标召回率提升明显漏检率能下降约30%。但要注意切图会增加整体计算量需要根据设备算力权衡不能为了精度牺牲实时性。5.3 TensorRT引擎构建的坑Trtexec构建引擎报错最常见的是ONNX模型里存在不支持的算子和动态维度问题。YOLOv8导出ONNX后有些版本的后处理算子TensorRT不支持解决方式比较直接导出时不带端到端后处理保留原始输出在TensorRT引擎之外自己写NMS。虽然多了一段代码但可控性最强。构建引擎时workspace大小也要给够尤其是INT8校准模式下内存占用比较大。如果构建时显存不足进程会直接崩溃。我把workspace设为2GB以上并在构建完成后再释放后续推理阶段只用引擎文件不再需要额外大内存。5.4 长时间运行的稳定性问题巡检任务经常要连续跑几个小时系统稳定性比单帧性能更重要。实际运行中我碰到最多的就是内存泄漏后来排查发现是GStreamer管道里的buffer引用没有释放以及Python层的循环里不断创建临时对象。解决方式是在主循环里周期性监控内存占用一旦发现异常就重启对应处理进程。无人机飞行造成的画面抖动会让检测框闪烁简单方案是在后处理里对检测框做EMA平滑加上跟踪ID后闪烁感大幅下降。另外飞行中光照剧烈变化引起的误检也很常见我在图像预处理阶段加了自适应曝光校正再在后处理阶段对低置信度目标做了抠图确认两者结合之后误检率降下来不少。5.5 常见问题速查表现象常见原因解决办法推理帧率上不去解码端CPU瓶颈换GStreamer硬件解码小目标漏检严重输入分辨率低1280微调加切图检测检测框闪烁缺少跟踪平滑加ByteTrack和EMA引擎构建失败算子不支持关掉端到端后处理自己写NMS长时间运行卡死内存泄漏监控内存周期性重启进程夜间误检增多缺乏夜间样本补采夜晚数据做微调多路视频延迟大缓冲队列堆积队列满时丢弃旧帧做完这套基于YOLOv8的无人机行人检测系统我最大的体会是模型训练阶段涨点固然重要但决定系统能不能真正用起来的还是工程链路里那些不起眼的细节——解码用什么方案、缓存队列满了怎么处理、推理线程怎么复用内存。每次排查性能问题的过程本质上都是把系统里最脆弱的环节找出来加固一遍。这个方向后续想继续扩展的话可以把单机检测升级成多机组网协同让多台无人机共享检测结果做全局态势分析也可以加入目标重识别模块让同一个行人在不同视角下能被连续追踪。不管往哪个方向走先把手上的部署链路打磨扎实后面再加功能都会顺手很多。