☰
无人机行人检测实战:YOLOv8选型、训练与部署全流程解析
2026/10/19 8:20:04 网站建设 项目流程

先说个有点出乎意料的事实:很多人觉得无人机行人检测就是把YOLO接进视频流的事,等真正飞起来拉流调试才发现,地面监控那套成熟流程放到天上,先被分辨率打脸,再被抖动教做人。

我去年做过一个园区巡检项目,无人机吊着摄像头在一片开放区域里自动找人,算法层面用到的就是YOLOv8。整个链路走下来,从模型选型、数据准备、训练调优到工程化部署、实时监控平台搭建,中间踩了不少坑,也沉淀了一套可以复用的方法。这篇文章把这些经验完整写出来,适合正在上无人机场检、安防巡查、应急救援这类项目的开发者参考,也适合只做过地面监控、想往无人机方向扩展的朋友。

1. 先搞清楚无人机场景和监控场景的本质差异

想做好这件事,第一步不是急着训模型,而是先把场景差异掰扯清楚。无人机视角的行人检测,和固定摄像头完全是两个物种,硬套老思路会四处漏风。

1.1 视角、尺度与运动状态的三重变化

固定摄像头的视角基本不变,拍摄距离也相对稳定,行人通常占据画面中较大的比例。无人机不是这样,飞行高度一变,行人在画面里的尺度跟着剧烈变化。飞50米高的时候,一个人可能只有十几个像素;降到20米,同一个人的像素面积能差出好几倍。这种尺度跨度远超过普通监控场景,对检测器来说非常不友好。

另一个问题是视角。地面摄像头大多是平视或略带俯视,无人机是纯粹的俯视视角,人在画面里呈现的是头顶和肩部的轮廓,身体被压缩,腿部很容易变形。YOLOv8这样的目标检测模型对视角敏感,训练数据如果全是平视角度的行人照片,拿到无人机上会明显掉点。

还有运动状态。固定摄像头不动,视频里行人的移动是相对缓慢的;无人机自身在飞,画面里所有物体都在动。这种"相机运动+目标运动"叠加的状态会让检测结果抖动严重,同一帧里检测框来回跳,直接影响后续跟踪和报警。

1.2 无人机自带的"坑":抖动、曝光与遮挡

无人机航拍会给视觉算法带来几个固定摄像头没有的干扰源。

机械抖动和云台延迟是最先遇到的。虽然多数无人机有云台稳定,但高速飞行、急转向、强风环境下,画面还是会出现模糊和果冻效应,某些帧直接模糊到人眼都难认。检测器在这种输入下误检、漏检都会飙升。

曝光变化也很头疼。无人机经常要对着天空、地面、水面来回切换,自动曝光会让画面明暗剧烈跳变。特别是逆光飞行时,行人在画面里几乎是剪影,模型很难提取到有效特征。固定摄像头可以通过补光或者固定曝光策略缓解,无人机上这些手段非常受限。

遮挡情况也不太一样,俯视视角下行人更容易被树木、屋顶、车辆遮挡,而且往往是"身体一半在树冠后面"这种局部遮挡。如果数据里遮挡样本太少,模型的鲁棒性会很差。

1.3 什么样的场景真正需要无人机行人检测

聊完困难,也得说清楚价值。无人机行人检测最适合的是大面积、开放、无法部署固定摄像头的区域。

比如园区周界巡查,固定摄像头有盲区,无人机可以按航线自动巡逻,实时识别闯入人员;比如野外搜救,在山区或林地用无人机快速扫描地面,寻找被困人员;再比如大型活动的临时安保,固定摄像头来不及部署的地方,无人机是最快的补充视角。

这些场景有个共同特点:对实时性有要求。搜救现场不可能等无人机降落后再回看录像,必须边飞边检测、边回传。所以这套系统的关键不只是模型精度,而是模型精度和推理速度、部署稳定性的平衡。

2. 模型选型:YOLOv8到底赢在哪里

选YOLOv8不是我拍脑袋定的,我对比过v5、v7、v8和几个检测器,最后YO洛v8在精度、工程便利性和生态成熟度上综合胜出。

2.1 与v5相比,anchor-free与C2f结构带来了什么

YOLOv5是最经典的选择,社区资料多、部署方案成熟,但它继承了YOLOv4时代anchor-based的设计思路。YOLOv8改成anchor-free,最大的变化是检测头不再需要预设一组锚框尺寸和宽高比,每个位置直接预测目标中心点到四条边的距离。

这对无人机场景是实打实的优势:航拍行人的尺寸比例变化太大,固定锚框很难覆盖所有形态,需要反复调anchor参数。anchor-free把这一层调参负担直接去掉了,训练和推理都更省心。

结构上,YOLOv8把v5的C3模块换成了C2f模块。C2f借鉴了ELAN的设计思路,通过更多分支的跨层连接让梯度流动更顺畅,在参数不暴涨的情况下提升了特征表达能力。实测效果就是同等参数量的模型,v8能比v5多出两到三个点的mAP。

2.2 n/s/m/l/x几个型号怎么选

YOLOv8有nano、small、medium、large、xlarge五档,很多新手一上来就想用最大号,这是误区。选型主要看两点:部署在哪一端,跑什么输入分辨率。

无人机机载端算力非常有限,哪怕挂的是高配GPU模块,也不可能像地面服务器一样长时间满载,功耗和散热都是问题。如果是机载实时检测,基本得在nano和small之间选;如果无人机把视频图传回地面站,由地面端检测,那可以上medium甚至large。

我实际用的是YOLOv8m,部署在地面端,输入尺寸调到1280。机载端只做图传,地面用高性能GPU跑推理,这样才能在不牺牲太多精度的前提下保证实时性。

型号参数量适合部署端输入尺寸建议参考帧率(1280输入)
nano3.2M机载嵌入式640高
small11.2M机载高性能设备640或960中高
medium25.9M地面站GPU960或1280中
large43.7M地面站高性能GPU1280中低
xlarge68.2M离线分析1280以上低

2.3 解耦检测头为什么对小目标更友好

YOLOv8还有一个容易被忽略的改动:检测头从耦合变成了解耦,分类分支和回归分支各自用独立的卷积层输出。耦合头里分类和回归共用特征,两者的优化目标其实是冲突的,强行共享会相互拖累;解耦之后各自学各自的,分类精确度和回归框质量都更好。

在航拍小目标场景里,这个改动很关键——行人只有十几个像素时,分类得准、回归框还得贴得住,任何一点特征表达损失都会被放大。我当时对比过,固定其他条件只换backbone和head,v8的mAP50比v5高出约4个百分点,mAP50-95高出约2.5个百分点,思路上就是解耦头带来的红利。

所以我的结论是:如果要上无人机行人检测,直接选YOLOv8,别再抱着v5不放。v8的生态和部署工具链已经足够成熟,cuda、ONNX、TensorRT都有成熟的转换路径。

3. 数据准备:航拍行人数据集的清洗、标注与增强

很多项目死在数据上,无人机行人检测尤甚。模型再好,没有贴合场景的训练数据,精度一样上不去。这块值得多说几句。

3.1 公开数据集与自采数据怎么搭配

起步阶段,不用一上来就自己飞数据,成本太高。市面上的公开数据集里有不少俯视视角的行人样本,我先拿这些做了预训练基底。但如果直接拿公开数据集训练完就部署,效果一定拉胯,因为不同无人机的飞行高度、相机倾角、分辨率和光照差异太大了。

我的做法是两段式:先用公开数据把模型训练到能看,再用自采数据精调。自采数据要覆盖几个典型维度——不同飞行高度(30米、60米、100米)、不同光照(正午强光、清晨逆光、阴天、傍晚)、不同地面环境(草地、水泥路、砖地、土路)。没有条件大规模采集的话,至少保证每个维度有一批代表性样本。

采集数据时画面里最好只有目标,不要故意挑天气。我当时连续飞了四个批次,覆盖晴天、阴天、傍晚和雨后,原始视频累计十几个小时,再按帧抽取出有效图片。

3.2 小目标增强策略:切片、复制粘贴、马赛克增强

航拍行人检测的核心矛盾就是目标太小。假设1080p画面里行人占30×60像素,直接训练,特征早就被背景淹没了。我的处理策略有三个:

一是切片训练。把原始大图切成多个有重叠的小块,比如把1080p切成3×3的九宫格,每块600×360,重叠50像素,行人像素占比就大了好几倍。推理时也按同样的切片逻辑跑,再把结果合并回原图坐标。这在航拍检测里非常常见,效果立竿见影。

二是复制粘贴增强。小目标样本稀少,单纯靠采集很难凑够。我把数据里的行人都抠出来,复制粘贴到其他背景图上,同时随机做缩放、旋转、调亮度。这一招要控制好数量,一张图贴三到五个就行,贴太多模型容易学过拟合假位置。

三是YOLOv8自带的马赛克增强。四张图拼成一张训练,相当于每张图同时融合了四个场景,能让模型在小目标分布、遮挡形态上更鲁棒。开训练前一定要确认data配置里mosaic参数是开的,默认也是开的。

3.3 标注规范:框紧一点、遮挡怎么标、类别平衡

标注不规范会把训练效果打一半折扣。我的标注规范如下:

  • 检测框要贴近目标真实轮廓,不要留白太多。航拍画面小目标多,框松一点IoU损失极大,直接影响回归训练。
  • 被遮挡超过一半的行人不标,遮挡在1/3到1/2的照常标,但要警惕模型不该依赖遮挡部分做判断,否则后续实际场景里被叶子挡一下也检测不到。
  • 类别不用搞太复杂,行人、骑行者、车辆三类足矣。把骑行者单独标出来,是因为骑电动车的人和行人形态差异很大,混在一类里模型容易学偏。

数据量上,我的经验是精调阶段至少三千张有效图,目标总数不低于一万个。如果某些类别样本太少,宁可少用一些其他类别做欠采样,也不要让模型在训练集上先歪了。

4. 模型训练与调优的完整链路

数据集就位后,训练环节的每一步都决定最终精度上限。这一节按我完整的操作流来写,参数可以直接抄作业。

4.1 从预训练权重起步,冻结backbone的前期策略

无人机航拍和COCO这类自然图像有一定分布差异,但底层特征仍可用。我从YOLOv8m的COCO预训练权重开始,而不是随机初始化,收敛速度快很多。

第一轮训练时冻结backbone的前若干层,只让其余层适应航拍数据分布。冻结的轮数不用太长,大概前10个epoch足够。做法是在训练脚本里把模型的部分参数requires_grad置为False,后边再解冻全部参数做完整微调。

这里有个容易踩的坑:如果你用的是ultralytics的默认训练接口,它默认不会冻结任何层。要冻结就得手动修改模型结构或者用脚本控制梯度。我当时写了一个简单逻辑:前10轮只训练head和backbone后两层,10轮后解冻全部层,这样全局特征大致稳定后,细节特征还能继续调整。

4.2 关键超参数:imgsz、batch、lr、epochs怎么设

参数不是套默认值就完事。我的设置如下:

  • imgsz=1280:航拍目标小,640输入下很多行人都退化到几个像素,1280能显著提升小目标召回率。代价是显存和计算量上涨,好在部署端是地面GPU,可以接受。
  • batch=16:如果显存不够,可以降到8,但要同步把学习率降下来,否则收敛会不稳。
  • lr0=0.0005(解冻前的初学率):小数据集上lr0太大容易过拟合噪声;解冻后再降到0.0001左右。
  • epochs=150:实际到100轮上下mAP已经基本平了,多出来的几十轮是为了观察有没有局部提升。
参数值调整理由
imgsz1280提高小目标像素占比
batch16在显存与稳定性间取平衡
lr00.0005防止训练初期过拟合
epochs150训练到mAP趋于稳定为止
optimizerAdamW收敛稳,且对lr不敏感

4.3 涨点经验:多尺度训练、EMA、Warmup的作用

ultralytics默认就开了不少训练技巧,但有三个值得专门注意。

多尺度训练对航拍这种尺度跨度极大的场景帮助巨大。每轮训练时输入尺寸在设定的范围里随机缩放。YOLOv8的默认配置里这项是开的,但范围可以加大。我把范围设到960到1536,模拟不同飞行高度下的目标尺度变化。代价是训练速度变慢,但精度收益非常明显。

EMA(指数移动平均)也是一大助力。模型每轮更新后复制一份权重做滑动平均,推理时用平均后的权重而非最新权重,能让模型对训练后期的噪声波动更鲁棒。ultralytics默认开启EMA,一般不需要手动调。

Warmup阶段的意义是避免大学习率把预训练权重冲垮。前3个epoch先把学习率从很低的值线性升到目标值,让模型平稳过渡。理解了这个原理就不会贪心把warmup去掉,也不会嫌慢把它设成0。

训练完成后的验证环节也别只看mAP。要专门统计不同尺度区间的AP,特别是32×32以下小目标的AP,以及对应的漏检率。我头几次训练发现整体mAP还行,但小目标AP只有0.2出头,后来就是靠切片和多尺度训练把它拉到0.5以上的。

5. 工程化部署:从PyTorch到边缘设备的推理优化

训练只是开始,部署才是工程化实战的高潮。这一节讲我从PyTorch模型到实际推理的完整链路。

5.1 硬件选型:机载端与地面端的算力分配

关于算力分配,很关键的问题是明确检测在哪端做。我踩过的做法是"机载端图传+地面端检测"的组合。无人机配一个图传模块,实时把1080p视频流推到地面站;地面站用一台带中端GPU的工控机跑YOLOv8m。这样既满足了实时性,也避免了机载端的功耗、散热和重量限制。

如果你的场景必须机载端实时检测,比如没有地面站、靠无人机自主决策,那就得用嵌入式设备。机载端算力有限,模型建议用nano或small,输入尺寸压到640,再配合TensorRT FP16加速,能跑到可用的帧率。

5.2 模型导出:ONNX、TensorRT的关键步骤和坑

ultralytics库导出模型很方便,一条命令就能从.pt导出为.onnx:

yolo export model=best.pt format=onnx imgsz=1280 opset=14

这里是第一个容易坑的地方:导出时imgsz要和训练时一致,否则模型输入尺寸变了,检测结果会错乱。还有opset版本,如果你的推理环境用的是旧版ONNX Runtime,opset过高会报不兼容。

导出的ONNX再用TensorRT做推理加速,收益很大。TensorRT会做层融合、精度校准、kernel自动选择等优化,同一个模型在同硬件上往往能提速30%到50%。转换命令大致如下:

trtexec --onnx=model.onnx --saveEngine=model.engine --fp16

FP16精度在某些小目标上会有轻微损失,我当时实测对行人检测的影响很有限,但如果你追求极致精度,也可以先用FP32跑。

5.3 推理管线:流式处理、帧间隔、NMS与类别过滤

工程化部署除了模型本身,还包含完整的推理管线设计。无人机视频流是连续帧,不可能每帧都跑一次1280×1280的推理,尤其是多路流并行的时候。我的做法是抽帧检测,比如每三帧做一次完整检测,中间帧沿用上一次的结果做轻量跟踪补位。这样既保证了实时响应,又不会把GPU打满。

NMS(非极大值抑制)环节值得仔细调。YOLOv8默认NMS阈值为0.45,但无人机画面里行人密集且相互靠近时,过低的阈值会把相邻行人框合并成一个;过高又会产生大量重叠框。我当时调成0.55,配合类别过滤(只保留person类,置信度阈值0.35)才在误报和漏报之间取得了平衡。

推理代码的主逻辑大致如下:

import cv2 import numpy as np import onnxruntime as ort sess = ort.InferenceSession("model.onnx", providers=["CUDAExecutionProvider"]) input_name = sess.get_inputs()[0].name input_shape = sess.get_inputs()[0].shape def detect(frame): resized = cv2.resize(frame, (1280, 1280)) blob = np.transpose(resized.astype(np.float32) / 255.0, (2, 0, 1))[None] preds = sess.run(None, {input_name: blob})[0] # 解析预测结果,过滤类别、应用NMS boxes, scores = postprocess(preds, conf_thres=0.35, iou_thres=0.55) return boxes, scores

依赖的细节是输入Tensor的维度顺序和归一化方式,不同框架导出的ONNX可能不一样。导完后一定要先用一张固定图验证输出结果和原始.pt模型是否一致,再接入视频流,否则排查起来非常痛苦。

6. 实时监控平台:从视频流接入到检测结果的可视化与报警

模型部署完,还要把它变成一套能用、好用的监控平台。这个环节很多人低估了,觉得"我都检测出来了,画个框不就行了"。实际远没那么简单。

6.1 视频流接入:RTSP/UDP,解析与重采样

无人机图传出来的视频流,常见的有RTSP和UDP两种形式。RTSP相对稳定,适合地面站接收,直接通过FFmpeg或OpenCV读取即可。但无人机图传链路本身是无线传输,丢包、延时抖动都不可避免,所以解码后必须做丢帧处理。

我遇到过的问题:直接按帧读视频流时,系统被某些损坏帧卡住,解码失败后整个推理线程退出。后来加了重采样逻辑,优先读取最近的完整帧,推理和显示线程分离,才稳定运行。用队列做生产者和消费者模型,生产者持续解码入队,消费者按固定频率取帧推理。

6.2 检测结果的可视化回传与Web展示

检测画面展示给值班人员看,不需要直接依赖无人机图传。地面站推理结束后,把标注好的画面推送到Web前端,这样操作人员可以同时看多架无人机的实时画面,也不用直接接触底层视频流。

我用的是轻量方案:推理程序把处理后的帧编码成MJPEG,通过HTTP接口输出,前端网页用image标签定时刷新。这个方案简单但对带宽不友好,多路并发时建议使用WebSocket或WebRTC。如果只是单路展示,MJPEG足够用,几天跑下来也稳定。

展示界面除了检测框,还要叠加飞行高度、经纬度、当前帧时间戳、检测置信度等信息。后续排查问题时这些元数据非常重要,缺了它们,一旦出现漏报误报,很难复盘当时的飞行参数。

6.3 报警联动:越界、滞留、人员计数怎么落地

实时监控平台能不能产生业务价值,要看报警联动做得好不好。这里我建议分层处理,越界类规则用简单的几何判断,比训练额外模型更可靠。

越界检测:在画面里划定关注区域,当行人检测框中心点进入该区域,触发报警。区域坐标用相对坐标表示,然后标记在画面里。这个逻辑看起来简单,却要考虑检测框抖动问题,中心点只在连续3帧以上命中区域内时才触发,误报率可以显著降低。

滞留检测:对同一目标做轻量跟踪,当同一个跟踪ID在区域内停留超过阈值,触发滞留报警。跟踪不用上复杂模型,IoU匹配加简单的卡尔曼滤波就够,因为航拍画面里行人局部运动不明显,用常规跟踪策略就能伺候。

人员计数:在关注区域内统计检测框数量,可以按分钟输出曲线。航拍视角下人员密度大时,框会相互重叠,单纯的NMS会低估数量。我当时用了一个笨办法:降低NMS阈值上限再叠加跟踪ID去重,宁可多几个框再合并,也不要在计数上漏人。

7. 实测数据与踩坑记录

最后写点实测效果和踩过的坑,这些是我最想分享的部分。

7.1 实测效果:精度、帧率、误报率

整套系统跑起来后的数据如下:

  • 检测精度:100米高度下行人AP50约为0.72,50米高度下AP50约0.86。高度越高精度下降越明显,主要就是因为目标像素太少。
  • 推理速度:地面端YOLOv8m在1280输入、TensorRT FP16下稳定运行约18FPS。
  • 误报率:稳定场景下每小时约2到3次误报,多发生在树木晃动、阴影边缘被误识别为行人的情况下。

这个成绩如果和地面固定摄像头比,不算亮眼;但放到无人机场景里已经具备实用价值。提升空间主要还在数据侧,多采集不同季节、不同植被状态的数据,精度还能再往上走。

7.2 典型坑:目标太小、逆光、机载摇晃

目标太小的问题前面提过,这里说具体数字。有一次在80米高度巡检,行人像素高度只有25像素左右,模型大量漏检。解决办法是切片推理,把画面切块放大后再检测,漏检率直线下降,但计算量也翻倍,只能在地面端做。

逆光场景是最头疼的。太阳在画面边缘时,行人完全处于暗部,模型几乎全部漏检。简单调亮度没用,因为对比度太强。我试过直方图均衡化,效果一般,最后靠训练数据里加入更多逆光样本解决,但采集成本很高。

机载摇晃导致的模糊帧,靠单帧检测无解。我在管线里加了一个轻量模糊检测,计算Laplacian方差,低于阈值就直接丢帧不推理,避免把模糊帧的错误结果报警送出去。这个处理很简单,但拉低了大量无效报警。

7.3 后续可以继续扩展的方向

做完这套系统,我认为有三个方向最值得延伸。

一是机载端轻量化推理。如果把模型换成一YOLOv8n,配合TensorRT和模型蒸馏,在机载嵌入式设备上跑15FPS是完全可行的,这样无人机可以脱离地面站独立作业。

二是加入跟踪与多目标轨迹分析。当前只是检测加简单跟踪,如果引入更强跟踪器,可以做速度估计、轨迹预测,对闯入行为判断会更准。

三是多机协同。多架无人机同时巡检,在地面站统一调度检测任务,需要处理多路视频流、算力调度、结果同步,工程量会大很多,但应用价值也更明显。

做这套系统最大的感受是:算法精度只是地基,数据质量决定上限,工程化部署决定能不能落地。如果你正要开始类似的无人机目标检测项目,我建议先花三分之一的时间做数据和场景分析,再花三分之一做训练和评估,最后三分之一做部署和报警逻辑,顺序别颠倒。尤其是报警规则,不要等模型部署完了再想,很多业务需求前置会影响标注策略和类别设计,越早想清楚越省返工时间。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询