无人机视角下的车辆与行人检测,近几年问的人特别多。原因也简单:消费级无人机越来越便宜,但“飞起来容易,看清地面难”。我自己在某个城市安防巡检项目里正好做过一整套方案:以Mask R-CNN为检测框架,backbone用HRNetV2p-W18,预训练权重来自COCO,训练调度采用2x策略。整个项目从数据采集、标注、训练到部署,踩了不少坑也攒了不少经验。这篇内容就是把这套模型的选型逻辑、训练细节和部署要点完整拆开讲一遍,给正在折腾无人机目标检测的朋友一个能直接参考的路径。
先说结论:在城市环境下做车辆和行人检测,俯视视角带来的问题远比地面道路视角麻烦。目标朝向不定、尺度跨度大、遮挡严重、运动模糊频繁,加上无人机自身抖动和高度变化,模型既要扛得住大目标的稳定识别,又要在小目标(比如视距外的行人)上不轻易丢检。Mask R-CNN配合HRNetV2p-W18这个组合,在很多实验里表现出对小目标的友好性,同时实例分割带来的轮廓信息对拥挤场景中的目标分离非常有帮助。
1. 项目到底要解决什么,以及为什么这个任务不简单
很多人第一次拿到“无人机城市环境车辆行人检测”这个需求,第一反应是:直接用地面目标检测的模型和套路不就行了?事实远没有那么轻松。我在项目早期就犯过这个错误,拿一个在常规驾驶数据集上表现优秀的检测权重直接去跑无人机画面,结果密集的小目标漏检几乎没法看,模型对俯视场景的适应性非常差。
1.1 需求拆解:安防巡检场景下的真实痛点
这个项目挂在一个城市日常巡检任务下面:无人机按设定航线巡航,需要实时识别视野内的车辆和行人,输出目标类别、位置和轮廓,为后台调度提供结构化信息。需求可以拆成三块:
首先是识别可靠性。城市环境复杂,车辆种类多、颜色丰富,行人姿态多样,再加上俯视角度下目标形状变化大,模型必须在不同高度、不同光照条件下稳定输出结果。
其次是实例级输出。只给一个矩形框在一些场景下不够用。比如多辆车紧挨着停放的时候,矩形框之间大面积重叠,下游统计数量时很容易把一个目标算成两个或者反过来。用Mask R-CNN输出实例分割掩码,每个目标的轮廓区域独立,统计起来干净得多。
第三是推理延迟。无人机悬停或者巡航过程中,地面目标不断进入视野,后台处理链路要求单帧推理控制在合理范围内,至少不能出现几秒钟才出一帧结果的情况。这就对模型结构的复杂度和部署优化都提了硬要求。
1.2 无人机视角的特殊性:它到底难在哪
无人机高度一般在30米到120米之间变化,同一辆车在不同高度下成像尺寸可以相差数倍。我做了一个粗略统计:飞行高度60米左右,一辆普通轿车的像素宽度大约是60到100像素;升高到120米,就只有30到50像素。行人更夸张,高度稍高一点就只剩下十几个像素的尺寸。这个尺度跨度对检测器的多尺度能力是很大的考验。
另一个麻烦是俯视角度带来的形状变化。地面道路场景里,车辆绝大多数是侧视或斜视,模型可以依赖车灯、车牌、车窗这些显著特征。但俯视画面里车顶成为主体视觉特征,不同车型的车顶纹理差异很大,加上车辆朝向任意,模型需要从更抽象的形状信息里识别目标。
还有遮挡和密集场景。无人机看地面,树冠、建筑阴影、桥梁结构都会遮挡目标;十字路口车辆排队时目标一个贴一个,普通检测框很难把彼此分开。这些场景恰好是实例分割的用武之地。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 模型选型与结构原理:为什么是Mask R-CNN加HRNetV2p-W18
选型这件事不能光看指标,还得看具体场景的匹配度。这个项目最终确定Mask R-CNN加HRNetV2p-W18-2x这套组合,不是拍脑袋,是几次试验对比之后的结果。
2.1 Mask R-CNN:检测之外还要分割轮廓
Mask R-CNN是在Faster R-CNN基础上扩展出来的实例分割框架。它的主体结构和Faster R-CNN保持一致:先通过backbone提取特征,再经过RPN(区域建议网络)生成候选区域,然后ROI Align层把不同大小的候选区域统一到固定尺寸的特征图上,最后并联输出三条分支——分类结果、边界框回归结果、以及二值掩码分割结果。
这个结构的好处在于:检测和分割共享特征提取与候选区域生成,训练是端到端的,模型在学“在哪里”的同时也在学“长什么样”。在无人机俯视场景里,掩码监督信号相当于一个强正则项,让模型对目标边缘和轮廓信息的感知更敏锐。实际项目里我们主要用边界框做下游统计,但训练阶段开了mask分支之后,边界框的定位精度明显比纯检测模型更稳。
Mask R-CNN有一个需要接受的现实:推理耗时高于纯检测模型。如果对mask没有需求,可以考虑在推理阶段只保留检测分支,或者用训练的模型蒸馏一个轻量的纯检测模型。这个后面部署部分会具体说。
2.2 HRNetV2p-W18:让小目标信息不容易丢
Backbone选型直接决定模型的上限。无人机画面里小目标多,所以backbone必须具备保持高分辨率特征的能力。
经典的ResNet系列采用串行下采样结构,从高分辨率逐步降到低分辨率,语义信息逐步增强,但空间分辨率也在逐步牺牲。对于尺寸很小的目标,经过多次下采样之后特征可能只剩下几个像素,检测器很难在这种特征上给出置信度足够高的结果。这也是很多模型在小目标上表现疲软的核心原因。
HRNet的思路完全不同。它从头到尾保持一条高分辨率特征主路,同时并行构建低分辨率支路来获取语义信息,各分辨率之间通过反复的信息交换融合特征。这种结构保证了空间细节和语义信息能够同时存在。HRNetV2p-W18中的W18指宽度(即每层通道数的基数),18是一个相对轻量的配置,在计算量和精度之间比较平衡。
我用HRNetV2p-W18替换掉经典ResNet50再跑同一批数据,小目标类别的AP有明显提升。在地面常规数据集上两者差距可能不到一个点,但到了无人机俯视场景,分辨率保持带来的优势就被放大了。
2.3 COCO预训练与2x调度:迁移学习的关键细节
COCO数据集包含80类常见物体,车辆和行人都在其中。用COCO预训练权重做初始化,模型已经具备通用的特征提取能力和对这些类别的初步感知,迁移到无人机场景后收敛快、精度高。
训练调度采用2x策略也很讲究。2x通常指在常规配置下训练约24个epoch,相比1x(12 epoch)训练量翻倍。采用2x而不是更长的8x,主要考虑两点:一是项目周期有限,2x已经在多数任务里能逼近收敛;二是无人机场景数据规模和复杂度决定了训练到后期容易过拟合,过犹不及。
实际训练的时候我再补充一句:即便有COCO预训练,也不能完全不冻结backbone直接全量训练,尤其是数据量并不大的时候。我的做法是先跑一小段只训练检测头的阶段让模型适应新数据的输出分布,再放开全部参数做完整训练,整个流程更稳。
3. 数据采集与标注细节:模型的真正上限在这里
很多人拿到一个模型就急着训练,结果反复调参也提不了精度,最后发现是数据的问题。无人机目标检测项目里,数据和标注质量几乎决定了80%的结果,模型结构反而是次要因素。
3.1 无人机数据采集的几个核心原则
数据的核心要求是“贴合真实部署场景”。如果模型要部署在60到100米高度,训练数据就必须覆盖这个高度范围,否则高度差带来的尺度分布差异会让模型无所适从。
采集时有几个注意事项:
采集时间要分散。上午、中午、下午、傍晚的光照条件完全不同,阴影方向和长度也不一样。只采某个固定时段会导致模型对特定光照过拟合,换到其他时段精度直线下滑。
天气不能太单调。晴天、多云、薄雾天气都要有。城市里玻璃幕墙和浅色车顶在强光下容易过曝,多云天气的均匀光照反而让目标特征更清晰。模型见过多样天气,鲁棒性才上得来。
航线尽量模拟真实轨迹。采集时不要只做悬停拍摄,要模拟实际巡检的航线动作,包括直线巡航、转弯、高度变化。这样采集到的图像天然包含运动模糊和视角连续变化的样本,比飞一个点拍几百张扎实得多。
不同场景要覆盖足。老城区窄路、新城区宽马路、露天停车场、高架桥附近,这些场景的目标密度、背景纹理都不一样。我做过统计,光停车场一个场景就能贡献40%以上的车辆样本,如果只在停车场采集,模型对其他场景的适应能力会很差。
3.2 标注规范与格式转换:省心和省事不可兼得
无人机俯视图里的目标标注比地面图难得多。我标注的时候设定的规则是:车辆目标标注可见车体轮廓,被严重遮挡且可见面积不足20%的目标不标;行人只要可见身体任意部位就尽量标出。
Mask标注是最费时间的部分。车辆轮廓相对规整,标注效率还行;行人姿态各异,加上树枝和阴影遮挡,抠轮廓非常耗时。这个项目里我们设计了一个折中方案:先用检测框拉出目标,再用半自动标注工具生成初始掩码,标注员在此基础上修正边缘。整体效率比从零开始抠轮廓提升很多。
标注格式最终统一为COCO格式。COCO格式以JSON存储,包含images、annotations、categories三个基本字段。标注工具导出后,我们写脚本把原始标注转换成COCO格式,顺便做类别映射。这个项目的类别最终简化为两个:vehicle和person。其实一开始有想过细分为轿车、公交车、卡车,但实际统计里公交车和卡车样本量不足,细分后类别不均衡反而拖累整体精度,所以合并处理。
3.3 数据增强策略:有限样本撑起复杂场景
数据增强是弥补样本不足最有效的手段。无人机场景我用的增强策略包括随机的水平翻转、旋转、缩放、颜色抖动和运动模糊模拟。
旋转增强在这个场景里是必须的,因为无人机画面中的目标朝向完全随机,模型不能对某个方向有先验偏好。我配置的旋转范围是[-30度, 30度],配合翻转基本上覆盖了所有朝向。
缩放增强要特别注意。单纯的随机缩放容易把大目标缩得太小、小目标缩得更小,导致训练样本分布失衡。我采用的做法是让缩放范围控制在[0.7, 1.3],同时对本就较小的目标做专门的过采样复制策略,保证小目标样本在训练中占一定比例。
运动模糊增强是后期加进去的。无人机巡航时的画面经常带有轻微的运动模糊,图像整体对比度下降、边缘变柔。我在训练管线中加入与真实模糊状态接近的卷积模糊模拟,效果是模型在推理时的鲁棒性明显提升。
4. 训练过程与关键参数解析
模型确定之后,训练过程中的很多细节直接关系到最终效果。我把我用的一套配置和背后的考量完整写出来,方便参考和复现。
4.1 硬件环境与框架选择
训练在一台配置了高性能GPU的服务器上进行,显存压力主要来自大分辨率输入和多尺度训练。框架使用主流的深度学习训练框架,配合标准检测工具箱。输入尺寸设置为1333x800,这是一个在精度和显存占用间比较平衡的取值,配合多尺度训练的范围缩放,模型可以学习不同尺度目标上的特征表达。
优化器选择带动量的SGD优化器。动量系数设为0.9,权重衰减设为0.0001。初始学习率设为0.005,这个参数不能盲目照搬,具体值要根据batch size和输入分辨率微调,后面详细说。
4.2 训练阶段划分与学习率策略
训练分为两个阶段:第一阶段冻结backbone参数,只训练检测头和分割头,让模型快速适应无人机数据的输出分布,大约跑2到3个epoch;第二阶段解冻全部参数,完整训练,学习率采用阶梯式下降策略。
2x调度下总共24个epoch,在第16和第22个epoch时将学习率降为原来的十分之一。这种阶梯下降是让模型前期大步探索、后期小步收敛的关键做法。如果你在日志里看到验证集损失卡住不动,检查一下当前epoch位置和当前学习率,多半是学习率太高在损失曲面附近震荡。
每个epoch大约需要处理一定数量的图像,配合batch size为4的设置,一个完整流程大概耗时十几个小时。训练过程中需要定期保存checkpoint,不要等全部训练完才保存一次,后面微调全靠这些中间权重。
4.3 训练日志怎么读:关注哪些指标
训练日志里指标很多,但真正需要盯的其实是那几个。
loss_cls和loss_bbox反映检测头的收敛状态,loss_mask反映分割分支的学习情况。如果loss_mask持续下降缓慢或波动很大,一般是因为掩码标注质量不高,建议回查标注数据而不是盲目调参。
验证集上重点看AP_50、AP_75和mAP。AP_50对定位要求相对宽松,AP_75要求更精确的框。无人机场景里我一般要求AP_50达到0.85以上才有部署价值,AP_75大于0.70算合格。
特别要单独统计小目标指标。多数检测框架会按目标尺寸区分AP_small、AP_medium、AP_large。无人机场景里AP_small是最关键的指标,也是提升空间最大的。如果AP_small和AP_large差距过大,比如差20个点以上,说明小目标仍然是模型短板,需要从数据层面补样本或微调anchor配置。
4.4 配置调优与常见瓶颈
训练初期常见的问题是loss不下降。可能原因有三个:学习率过大、标注数据存在严重噪声、或者backbone没有正确加载预训练权重。挨个排查,不要一上来就大改网络结构。
关于anchor配置:默认RPN锚点在不同尺寸和比例上分布,地面常规数据集的分布和无人机场景差异明显。无人机画面里目标长宽比例更多样,方形锚点效果最好。我根据数据统计把锚点比例调整后,小型目标的召回率提升明显。
另一个容易忽视的问题是批次大小。显存不够用的时候,很多人直接减小batch size,但没有同步调整学习率,导致收敛变慢。batch size和初始学习率是绑定的:减半batch size,学习率也应该相应减半,这个细节很多情况下能救回一整个训练流程。
5. 部署推理与性能优化的实战记录
训练完成的模型不能直接用于实际飞行任务,推理速度和硬件兼容性必须在部署阶段解决。我在这个环节踩了不少坑,也摸索出一套比较顺畅的流程。
5.1 模型转换与硬件适配
训练框架产出的权重格式不便于在推理侧直接高效运行。部署的第一步是把训练好的模型转换成标准化开放格式,再通过推理加速框架进行优化。
整个转换流程有几个容易出问题的地方。首先是输入输出节点名要对齐,其次要保证动态输入支持,因为实际推理时输入图像的尺寸可能变化。我在转换时先固定一个参考输入尺寸批量验证输出结果,确认数值在可接受误差范围内再继续后续加速。
推理加速框架选择的是针对目标硬件优化过的引擎。转换时开启FP16精度模式,进一步减少计算量和显存占用。FP16带来的精度损失在检测场景下几乎可以忽略,但推理速度提升非常明显。
5.2 推理链路设计:让结果稳定可用
在部署阶段,我在推理链路里额外加入了一个检测结果后处理模块,不仅仅是做NMS(非极大值抑制),还包括目标类型的二次过滤和邻近帧结果的时间平滑。
NMS的参数需要根据场景反复调。阈值设高了密集场景容易出重复框,设低了又可能漏检。我最终把NMS阈值定在一个中间值,确保车辆排队场景和行人聚集场景都能稳定输出。
时间平滑是一个实际部署中很重要的细节。单帧检测结果会出现抖动,同一个目标这一帧识别为车辆、下一帧又漏检了。我在后处理环节做了轻量的跟踪关联,利用相邻帧的检测结果互相矫正,最终输出的结构化信息稳定很多。
实时性能上,在优化过的推理引擎配合下,单帧图像分辨率下的处理时间已经可以被压缩到一个比较理想的水平,可以满足巡检任务的实时性需求。如果要进一步提升,可以考虑只运行检测分支去掉mask计算,或者把输入尺寸降为0.8倍,精度损失不显著但速度提升可观。
5.3 飞行任务中的部署经验
实际飞行时,机载端处理和大疆地面站回传处理是两种不同的部署路线。机载端功耗和算力限制严格,适合跑轻量模型或只做检测不做分割。地面站回传方案则可以让模型跑在更强的计算平台上,实时性和精度都有保障。
在具体飞行任务中,我总结出几条实操建议:
飞行高度尽量稳定。频繁变高会让目标的尺度分布剧烈变化,增加检测器的不确定性。如果巡检任务确实需要多高度覆盖,建议把数据按高度分档,训练时按档位做分组增强而不是混在一起。
尽量避免对着太阳方向拍摄。无人机视角下太阳直射会让画面过曝,高光区域的车辆几乎完全失去纹理信息。航线规划时优先考虑顺光方向,能让模型表现稳定得多。
存储和回传的图传帧率不要盲目调高。帧率过高只会加重推理链路的压力,而且相邻帧信息高度冗余,分析价值有限。我通常将关键视频流控制在20到30帧,配合平滑模块足够满足巡检需求。
6. 常见问题与排查实战:把踩过的坑都列出来
这套方案从数据到部署走完整个流程,遇到的问题是成体系的。每类问题我都整理出实际的排查思路和处理方案,直接做成一个速查表风格的内容,方便对应检索。
| 问题表现 | 可能原因 | 排查步骤 | 实际解决 |
|---|---|---|---|
| 小目标漏检多 | 数据里小目标样本少、锚点尺寸不匹配 | 统计训练数据中目标尺寸分布,对比anchor设置 | 调整锚点尺寸参数,增加小目标过采样复制 |
| 多车辆密集排列时mask重叠严重 | 掩码分支对边缘区分能力不足 | 检查标注掩码质量,确认边缘贴合度 | 增加边缘感知损失权重,重新修正低质量标注 |
| 玻璃幕墙反光区域出现误检 | 训练集中类似样本不足 | 收集误检样本回溯分析背景特征 | 在训练数据中增加反光区域负样本,迭代重训 |
| 夜间或低光照条件下检测率低 | 训练数据缺少夜间样本 | 统计各时段数据占比 | 补充夜间和黄昏数据,加入暗光增强策略 |
| 运动模糊导致的边缘模糊和漏检 | 训练数据缺少模糊样本 | 对比正常样本和模糊样本的检测置信度 | 引入模糊模拟增强,降低模型对清晰纹理的依赖 |
| 推理速度达不到实时要求 | 模型计算量过大、硬件算力不足 | 检查单帧耗时分布,确认瓶颈算子 | 开启FP16推理,移除mask分支只保留检测头 |
| 模型在特定高度下精度骤降 | 高度变化导致目标尺度超出训练分布 | 按高度分档统计分析检测精度 | 按高度分档训练多个模型,推理时动态选择 |
表格里的每一项都来自实际踩坑。特别强调一下误检问题:城市环境中的玻璃幕墙反射、屋顶太阳能板、地面上鲜明的交通标线,都容易触发假阳性。单纯调阈值不能根治,最有效的手段是在训练数据中补充这些复杂背景的负样本,让模型真正学会区分。
还有一个容易忽略的问题:模型对遮挡目标的响应。无人机视角下,树冠遮挡会让车辆露出一小半,行人也经常被路灯杆、路牌截断。这类目标的标注本来就困难,模型学习也吃力。我的做法是在标注时对遮挡目标进行特殊标记,训练时降低这些样本的损失权重,避免模型为了少数极端情况牺牲整体精度。
尾声:这套方案的后续扩展空间
写这篇内容的时候,我脑子里还在过这个项目后续可以继续推进的地方。当前模型输出的检测结果和掩码,实际上已经可以支撑更上层的数据应用了。比如统计某个区域的车辆密度、分析行人聚集趋势、对指定区域的目标进行持续跟踪——这些能力在巡检场景里都很有价值。
从我个人的经验来看,未来的优化重点有两个方向。一个是轻量化。当前方案的精度和速度已经够用,但在更小型的无人机平台上部署仍有压力,后续可以考虑用蒸馏或神经架构搜索的方式把模型缩得更小。另一个是时序信息的利用。目前的检测是单帧独立的,如果引入连续帧的光流或多帧融合,可以在运动模糊和遮挡更严重的场景下提升检测稳定性。
这个项目最重要的是验证了“在无人机俯视场景下,通过合理的backbone选择和训练策略设计,能够达到实用级检测精度”这一条路径。数据决定上限、模型逼近上限、部署释放上限,这个逻辑在这个项目里体现得淋漓尽致。如果正在看这篇内容的你刚好也在做类似的无人机巡检项目,希望这些踩坑记录和实操经验能帮你少走几步弯路。
