资讯动态

无人机航拍小目标检测数据集构建:从场景设计到智慧交通与应急救援落地

发布时间:2026/10/21 3:07:05 来源:尧图企业网站定制
我做无人机视觉落地也有几年了今年被问得最多的问题不是“模型怎么调”而是“模型怎么到了现场就不灵”。很多朋友拿着公开的航拍检测模型在桌面演示上mAP能到七八十个点可一部署到国内的十字路口、老小区、城乡结合部漏检和误检排着队来。问题不在模型架构在数据本身。国内的车流形态、道路结构、建筑密度、拍摄习惯和公开数据集里的国外街景完全是两套逻辑。我参与构建了一套面向国内场景的无人机车辆行人检测数据集从采集、标注、训练到在智慧交通和应急救援两个方向的实际落地整套流程都走了一遍。这篇文章就把这套数据集本身、背后的设计取舍、以及跑项目时踩过的坑完整拆开来讲。1. 公开数据集的“水土不服”为什么必须自建国内场景数据集1.1 公开航拍数据集与国内实际场景的三大落差先说一个很多人没意识到的点公开能拿到的无人机航拍检测数据集主流来源基本是高校实验室和科研机构发布的场景库拍摄地点多是国外城市、校园周边、高速路网目标尺度偏大、场景开阔、光照规整。用它们做算法预研、打竞赛、验证模型结构完全没问题但放到国内真实业务现场立刻会撞上三堵墙。第一堵墙是目标尺度的分布差异。公开数据集里的车辆在画面里往往能占到几十乘几十像素而国内无人机安防巡逻常用的飞行高度是80到120米搭配普通可见光云台一辆轿车在1080P画面里通常只有15到25像素宽。行人更夸张基本在8到12像素之间。模型在公开数据集上长大的“目标感”偏大一到国内实际航线小目标召回天然吃亏。第二堵墙是交通形态完全不同。国外数据集里最多是轿车、皮卡、巴士道路规整、车道清晰。但国内场景大量存在三轮车、电动自行车、老年代步车、混行的非机动车道而且违停、逆行、占用对向车道这些现象是常态。模型不认识三轮车就会把大量该检出的目标漏掉或者把三轮车认成“奇怪形状的小卡车”对交通违法识别这种业务来说这就是事故。第三堵墙是场景纹理和背景复杂度。国内的老旧小区、城中村、建材市场屋顶有太阳能板、彩钢棚、晾晒物地面有地摊帐篷、施工围挡、堆料这些杂乱背景在航拍俯视视角下会产生大量“伪目标纹理”。国外干净的道路和高尔夫草坪式背景训练出来的模型遇到这些纹理很容易把空调外机、蓝色彩钢棚当车把树荫里晃动的光影当行人。这三堵墙不是靠数据增强能绕过去的——增强只能让模型更鲁棒但无法教会模型“认识”它从未见过的目标形态和场景分布。所以要真正服务国内场景就必须有国内场景的数据打底。1.2 更深的错位标注体系与业务指标对不上比图像差异更棘手的是标注体系跟业务需求之间的错位。公开数据集里的类别体系是学术导向的比如“car”“truck”“pedestrian”粒度到目标类型就停了。但实际业务里智慧交通要的是“这辆车是不是违停”“这辆电动车是不是走了机动车道”“这个路口是不是发生了拥堵聚集”。应急救援更典型。搜救场景里模型要回答的不只是“这里有人”而是“这里有人倒下/被困/聚集待援”。这些是任务级的语义如果数据里只有“person”这个类别下游业务就得写一堆后处理规则去猜猜来猜去极易误报漏报。所以我们这套数据集在设计之初就没按学术分类法走而是按任务场景反推标注体系把目标分成基础类别和业务属性两个维度。基础类别解决“是什么”业务属性解决“该不该报警”。这样的数据才能真正接得住业务指标而不是模型AP很好看用户却用不起来。2. 数据集的构成与组织从原始航拍到标签文件的完整拆解2.1 采集区域与覆盖策略一套能用的数据集第一件事是回答一个问题我到底要覆盖哪些场景。我们当时没有贪多求全而是聚焦三个最能代表国内无人机常态化巡逻需求的地方我按项目内部编号叫它们A区、B区和C区。A区是城市核心商务区特点是高楼密、玻璃幕墙多、十字路口规整、人车密集。这个区域主要服务违停识别、路口车流量统计。B区是城乡结合部自建房密集、道路窄、三轮车和电动车大量出现、白天有集市、夜晚照明条件差。这个区域用于测试模型在“无序交通”下的表现。C区是河滩、树林和疏浚工地属于应急救援演练常选的野外环境。这里车辆少、行人散落、植被遮挡严重目标经常处于半遮挡状态。采集高度上我们做了四档30米、50米、80米、120米。30米和50米的画面能看清车辆细部适合标注“车型”“颜色”属性80米和120米则是实际巡逻里最常用的巡航高度大量小目标样本要从这两档里来。角度以45度斜视和90度俯视为主斜视贴近云台手操作习惯俯视贴近航线任务模式两者都保留模型才不会在某个姿态下“偏科”。时段上白天和黄昏是大头各约占四成夜间约占两成。夜间样本我们特意留了低照度下的路灯环境因为安防巡逻最关键的恰恰是夜里。2.2 类别体系设计基础类别与业务属性分离这套数据集的类别体系我会建议任何做落地场景数据集的人都参考一下。它把标注内容拆成两层第一层是基础检测类别覆盖车辆和行人两大类。车辆类细分为轿车、SUV、面包车、货车、卡车、巴士、三轮车、摩托车、电动车行人按状态再拆为站立行人、骑行人员、聚集人群、倒地人员。有人会问倒地人员和站立行人模型能区分吗单帧静态确实困难所以我们把“倒地/异常姿态”类主要放在静态特征强烈的样本上如完全躺平、四肢展开其他模糊情况一律标为站立行人由时序模型在推理阶段补充判断。第二层是业务属性标签它不是目标框的内容而是目标框的附加字段包括“是否处于路口”“是否停在非泊位区域”“是否为静止目标”这类交通业务属性以及“是否处于植被遮挡下”“是否位于水域附近”这类救援业务属性。标注时把这些属性记在JSON里训练时基础检测头只吃框坐标和类别业务属性则用来做后续的任务模型微调。这样设计的好处是一套数据可以在两个场景间复用。训练基础检测器时两类目标一起进模型做交通业务时用属性过滤出违停车辆做救援业务时用属性过滤出高危目标。不用每次换场景都重标一遍底库。2.3 目录结构与标注格式落地方案数据规模上整套数据集最终保留标注图像约3万张检测框实例总数超过15万个。3万张听起来不算海量但配合多高度、多时段、多场景的覆盖实际训练出来的泛化能力明显优于直接拿公开数据集跑。因为无人机航拍连续帧之间大量重复我们做了严格的去重筛选保证同一条航线中相邻帧的相似度不超过阈值让每张图都贡献独立信息。标注格式我们同时导出了YOLO的txt格式和COCO的JSON格式。YOLO格式方便训练时直接读入COCO格式方便做评测和可视化。这是项目里一个很实际的取舍不要只留一种格式团队里总有人要用另一种。一条标注文件的示例大致长这样# 图片 final_train/images/A_120m_day_traffic_00412.jpg # 对应样本轿车型车辆目标较小轻微遮挡 11 0.452381 0.327604 0.031846 0.024398 23 0.733254 0.284117 0.018742 0.012594前一个数字是类别编号中间两个是归一化中心坐标后两个是归一化宽高。我们专门做了目标尺寸分层统计把最小目标下限定在6像素宽。小于6像素的实例不标因为6像素以下连人工都难以确认标了反而会引入大量噪声标注训练时模型只能学到错误纹理。目录结构按照深度学习项目的标准做法组织├── final_train │ ├── images │ └── labels ├── final_val │ ├── images │ └── labels ├── final_test │ ├── images │ └── labels ├── annotations │ ├── dataset_coco.json │ └── dataset_attrs.json └── data.yaml这里特别说一下数据划分的策略划分维度是“场景”不是“帧”。同一条航线的前后帧如果分别被划进训练集和验证集验证分数会虚高模型像是“背过答案”的考生。我们按航线ID整体划分保证验证集里的画面和训练集完全来自不同航线。这是很多人容易忽略的细节但影响极大。3. 两个落地场景的差异化打磨智慧交通与应急救援的双线复用3.1 智慧交通场景从“看见车辆”到“读懂违章”智慧交通是这套数据集的第一个主战场景。我们内部跑通了一条完整的业务流无人机按既定航线巡航视频流实时接入机载算力或者地面站检测模型输出目标框后台跟踪算法把同一辆车跨帧关联再利用GPS位置和地图网格判定这辆车所在区域是否属于可停区域。只看车辆检测还不够违停识别最大难点是“静止车辆”与“堵车缓行车辆”的区分。数据集中专门补充了静态车流场景把路口排队、红绿灯等待、停车场、违停路段四类“车停着”的情况都做了充分标注。模型学习的是视觉特征但“是不是违停”依赖的是目标在空间网格上的位置语义这就需要属性标签里的“是否位于非泊位区域”“是否静止”信息来支撑。非机动车道占用检测也很有代表性。国内大量路口存在电动车和自行车骑上机动车道的现象这类目标小、速度快、形态多变公开数据集几乎无法提供样本。我们在B区专门采集了混合交通流数据把骑行人员单独设为一个基础类别模型成功把这类目标的召回率从接手时的不到四成提到了稳定七成以上。这个提升直接决定了客户愿不愿意把你这套系统接到他的大屏上。3.2 应急救援场景从“检出人群”到“判定受困状态”应急救援场景的做法和交通有很大区别。交通场景路况相对可控目标是细分类和属性判定救援场景里目标极度稀疏、光照恶劣、背景极端复杂你需要在“有人的画面”里找人还需要判断人的状态。比如河滩搜救演练人员穿着和河滩砂石、枯草高度相似躺倒的人从80米高度看下去就是浅色背景上一小块灰色。这种目标常规检测模型很容易当成地面纹理。我们针对性地在数据集中增加了“倒地人员”类别采集了大量不同姿势、不同环境下的躺倒人员样本。模型在低可见度条件下对单个人的召回率靠新增样本直接提升了十几个百分点。夜里搜救是另一个硬骨头。单靠可见光低照度下目标几乎看不清我们对这类场景的策略是保留样本但降低预期可见光模型负责检出“疑似目标区域”再用热成像或高倍变焦二次确认。数据集中保留的夜间样本保证了模型至少不会在夜里盲目漏掉所有目标能给飞手提示“这里要看一眼”。3.3 一个数据集两套标准的共存与取舍一套数据同时服务两个场景必然遇到类别定义上的冲突。行人这个类别交通场景里就是过马路的普通人救援场景里却可能是需要救助的被困者。我们不能建两套物理数据但可以一套数据两套逻辑。具体做法是训练检测模型时使用统一的基础类别也就是前面说的“轿车/SUV/行人/倒地人员”这套层次业务侧在推理时通过属性标签继续灰度判断。比如倒地人员类别既服务救援场景的“受困人员预检”也能在交通场景中提示“有人跌倒需要处置”。实测下来基础检测模型只需要一套权重文件业务系统按需挂载属性分类模型或者规则引擎两个场景都跑得通。4. 用这套数据集训练检测模型的完整实践4.1 模型选型为什么以YOLO系为基线目标检测模型现在可选范围很广但我们最终以YOLO系作为主要基线。理由很朴素无人机机载算力受限边缘设备上要跑实时视频流YOLO系列的推理速度和部署成熟度最稳。项目内部也对比过基于注意力机制的检测模型精度确实更好但推理速度在机载设备上撑不住30帧业务上只能放弃。具体版本上用了YOLOv8和YOLOv9两种做对比。YOLOv8训练稳定、生态好、文档全适合起步和做基线YOLOv9在部分小目标样本上的精度略高但训练更吃显存和调参。我们的结论是如果算力紧张、快速出结果选YOLOv8m如果后面要做切片推理提升小目标精度可以尝试YOLOv9c。4.2 训练配置小目标场景下的关键参数调优针对无人机航拍的小目标特点训练配置有几个地方值得重点讲。第一个是输入分辨率。常规目标检测默认608或者640无人机航拍完全不够。我们把训练尺寸直接拉到了1280推理时保持1280。分辨率提升带来的计算量上涨明显但小目标召回率的收益更明显。实测从640升到1280小目标AP大概能提8到10个点。如果你的机器实在带不动1280至少也建议拉到960再低就不太建议了。第二个是多尺度训练。航拍场景目标尺度分布极宽同一张图里既有占半个画面的巴士也有只占百分之二像素的行人。我们开了多尺度训练从960到1600之间动态随机缩放让模型同时适应不同飞行高度下的尺度变化。第三个是Mosaic增强策略。Mosaic一直是YOLO训练的好帮手但在无人机场景里要注意它对小目标其实是双刃剑四张图拼一起小目标会进一步被缩小甚至缩到消失相当于给样本引入了强噪声。我们的做法是前150个epoch用Mosaic后面50个epoch关掉Mosaic让模型回到真实分布的稳定精调阶段。第四个是负样本策略。数据集中专门划出约800张无目标空场景图不放任何标注框作为负样本参与训练。这些图里有屋顶、停车场、河滩、树林全部是为了压住误报。负样本对减少树影、彩钢棚误检的作用非常直接强烈建议做落地场景数据时预留这一部分。一个简化的训练配置参考如下# data.yaml 片段 train: final_train/images val: final_val/images test: final_test/images nc: 14 names: [car, suv, van, truck, bus, tricycle, motorcycle, ebike, standing_person, cyclist, crowd, lying_person, water_vessel, barrier]# 训练命令示意 from ultralytics import YOLO model YOLO(yolov8m-seg.pt) model.train( datadata.yaml, imgsz1280, epochs200, batch16, device0, workers8, mosaic1.0, close_mosaic50, hsv_h0.015, hsv_s0.5, hsv_v0.3, scale0.5, )4.3 评测方式不只看全局mAP还要拆开看子场景评测是这次项目里我认为最能帮到同行的一个环节。一套统一指标走天下是不够的我们建了一套分层评测体系按目标尺寸分小于16像素、16到32像素、大于32像素三档分别看AP。小目标档位直接决定航线高度能否放开。按时段分白天、黄昏、夜间三个子集。夜间的AP下降多少直接决定客户敢不敢让你夜里飞。按场景分A区、B区、C区单独出指标。很多模型在A区能达到较理想水平到B区却掉得很厉害如果不分层看根本发现不了问题。提示评测时尽量使用COCO的API做标准化评测不要只在训练日志里看曲线。训练曲线loss降得快不代表小目标AP真的高甚至可能只是背景学得好。分层评测里我们发现过很典型的问题某个版本在全局mAP上比旧版高2个点但按高度一拆80米和120米档位的召回率反而掉了3个点。原因是我们增加了大量大目标样本把模型的容量吸走了一部分。如果不拆开看这个模型就带着“整体更好”的错误结论上线了。5. 数据生产中的真实教训标注误差、类别不均衡与误检治理5.1 标注误差对小目标检测的放大效应数据生产走过一轮之后最想说的一条教训就是小目标场景下标注误差对模型的影响会被放大很多倍。一张800像素宽的画面里一个12像素的小目标框中心偏移1个像素、宽高偏差1个像素相对误差就接近10%。而这个框进入训练后模型会在它的邻域反复学习“正确”和“错误”两种特征等于让同一个目标提供了矛盾样本。我们第一版模型的小目标AP始终上不去排查后发现问题就出在质检环节标注员在小目标上普遍存在2像素左右的偏移。最后我们将质检规则改成“小目标像素差超过1.5像素必须返工”并单独做了一轮小目标专项复标。仅仅这一项小目标AP提升了近3个点。所以如果你自己建数据集请对小目标框做单独质检不要和大目标用同一套容差标准。5.2 类别不均衡的治理让三轮车和骑行人员被充分看见类别不均衡是第二个坑。初始数据里轿车、SUV样本占比高三轮车和骑行人员样本少训练结果就是前者AP普遍较高后者常被漏检。而业务上对这些“少数派”恰恰很敏感。治理思路有三个可以组合用数据加权按类别样本反比设置loss权重让少量类别获得更大的梯度贡献。重复采样三轮车和骑行人员样本做拼图增强同一目标多角度、多时段的复制版合并训练。定向补充回采集区域专门补录三轮车、电动车密集的路段把这两个类别的样本量补到与主要类别差距不超过3倍。这是一个持续迭代的过程。我们的经验是不要企图一步到位先把模型跑起来再去看混淆矩阵里哪些类别的召回明显低定向补数据比盲目堆数量高效得多。5.3 误检雷区实测树影、车顶、彩钢棚误检大概是每一轮测试必遇到的问题而且误检的对象总是出奇一致。树影误检是第一名。阳光强烈时树枝在地面投下密集晃动阴影模型经常把其中某块明暗变化明显的阴影判断为行人。这类误检靠调整置信度阈值压不掉压到0.6确实能去掉不少但也会误伤大量真实小目标。我们的做法是让负样本集中加入大量树影场景模型学到的目标是“行人轮廓与地面的相对关系”而不是简单的“局部暗块”。车顶误检也很有意思。深色车的车顶、天窗区域在高分辨率图里经常被模型认成另一个目标最常见的是把SUV天窗当骑行人员。我们分析是样本里行人多为深色衣服、集中在亮背景特征上与“亮色天窗深色车顶”过于接近。解决方式是补了一轮“车辆车顶区域标为忽略区”的精细化标注让模型在训练时明确知道那是车辆的一部分不用单独预测。彩钢棚和蓝顶棚在城乡结合部极常见色调和天空接近边缘在俯视视角下又规整容易误认为车顶。我们的对策是加大这类背景的负样本比例并且调整检测头的锚框尺度匹配让模型对“过大块面的矩形目标”更克制。注意这些误检治理没有一次性方案每一轮测试都可能出现新雷区。项目上最好把误检样本持续回收每周固定回灌一次负样本模型才会越来越“懂事”。5.4 验证集设计别让航线的“惯性”骗了你最后一个易踩的坑在验证集上一个坑前面简单提过这里展开说一下。无人机执行航线任务时帧与帧之间有很强的空间相关性如果验证集是从所有素材里随机抽帧得到的那训练集必然会包含同一航线其他帧的画面。这类画面目标位置、角度、光照几乎一致模型对它们“过拟合”得非常自然验证AP会虚高。我们当时的验证集设计改成两部分一部分从已覆盖的航线中按场景抽帧另一部分是完全新飞一条独立的、训练阶段从未见过的航线。训练过程中实时看已覆盖航线验证集的指标每轮迭代后再独立航线上快速验证一遍。两者差距如果超过5个点就说明模型已经过拟合既有航线需要重新评估数据增强或者采样策略。这种做法在项目交付中极其重要。客户最终看的不是你的验证集AP而是你飞到他们的地盘上漏不漏检。别让数据划分帮你“作弊”。数据之外的几句经验整套流程走下来我最想分享的心得其实就一句数据集的价值不只是“让人工智能跑得更准”而是让项目团队逼着自己先把业务定义清楚。我们前期花了大量时间讨论类别体系和属性标签当时觉得费劲后面训练、部署、验收反而越来越顺因为业务指标在数据里早就有对应物了。如果你想做类似的事情我给三条最实在的建议第一数据采集前务必把业务场景按“风险等级”排优先级先采集最影响客户感知的那部分第二小目标质检标准单独定不要省这一步第三预留至少一成以上的负样本预算误报清零永远比召回提升更难。下一步我们计划把红外模态加入数据采集序列让全天候巡逻不再依赖运气到时候再回来更新这套数据集构建方案的实际效果。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑