尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

无人机识别数据集与目标检测:从标注到YOLOv8训练实战

无人机识别数据集与目标检测:从标注到YOLOv8训练实战 简介针对无人机目标检测任务的数据集资源适用于使用YOLO系列、Faster RCNN、SSD等深度学习框架的开发者与研究人员。资源内含9229张无人机图片及对应标注图片与txt标签已划分训练集、验证集和测试集并附带指定类别信息的yaml文件可直接用于YOLOv5至YOLOv10等主流YOLO算法的训练省去数据整理与格式转换环节。压缩包共2000个文件以txt标签文件为主体另有1个yaml配置文件整体大小约814.16MB。当前已有339人学习。对需要快速构建无人机检测模型、开展算法对比或实验的读者来说这份数据集能够显著降低数据准备门槛帮助聚焦模型训练与调优。1. 无人机识别数据集目标检测里最像“找针”的任务“无人机识别数据集”这个词在目标检测项目里经常被误解成“用无人机拍的交通数据集”实际上它指的是把无人机当成待检测目标的数据集。反无人机安防、低空管理、机场净空巡检都要靠目标检测识别图像里的微型无人机难点是非常具体的四个词目标小、速度快、背景杂、像鸟。数据集中无人机目标常只占图像面积千分之几而检测模型的基础指标严重依赖标注质量。后续章节用yolov8、mmrotate、切片推理等方法把这一类数据集从采集标注到训练评估走一遍。适合要做目标检测模型落地的工程师也适合刚拿到反无人机项目需要快速建立数据流程的团队。2. 无人机识别数据集来源公开集、自采与仿真合成怎么选要训练一个能在真实边界场景下工作的无人机识别模型第一步不是急着选模型而是把数据源盘清。无人机识别数据集通常来自三个方向公开下载的已有数据、团队自采的真实视频、三维渲染生成的合成图片。三者各有不可替代的价值也各有明显短板组合使用比只依赖一个来源更现实。2.1 公开无人机识别数据集下载前先确认目标定义公开数据集中anti-UAV、Drone-vs-Bird这类是专门把无人机当目标的另有一些遥感目标检测数据也把无人机列为小目标类别。下载后第一件事不是直接解压训练而是确认它的目标定义红外帧还是可见光帧单目标还是多目标最小目标像素是多少是否带轨迹粒度的标签。这些标注语义相差很大有的数据一帧里只有1个无人机有的数据一帧有几十个直接混用会打乱正负样本配比。我一般会先对所有候选数据集跑一个分布统计脚本把每张图的尺寸、目标数量、目标框面积占全图面积的比例算出来。import cv2, glob, numpy as np from pathlib import Path for img_path in glob.glob(datasets/*.jpg): img cv2.imread(img_path) h, w img.shape[:2] label_path Path(img_path).with_suffix(.txt) if not label_path.exists(): print(f{img_path}: no label) continue boxes np.loadtxt(label_path, ndmin2) area_ratios [] for box in boxes: # 每行类别 归一化中心x 归一化中心y 归一化宽 归一化高 xc, yc, bw, bh box[1], box[2], box[3], box[4] area_ratios.append((bw * w) * (bh * h) / (w * h)) if area_ratios: print(f{img_path}: size{w}x{h}, target_num{len(area_ratios)}, fmin_ratio{min(area_ratios):.5f})逻辑说明脚本按YOLO格式的txt统计ndmin2保证空文件也能进入循环把归一化宽高乘回真实像素再计算目标占图像面积的比例。统计结果如果一半以上目标占比低于0.001这个数据集就跑不进常规COCO预训练模型的舒服区。如果要合并多个公开集切分时按视频或拍摄场景划分不要直接按帧随机划分。相邻帧几乎一样混进验证集会得到虚高mAP部署后遇到新背景立刻打回原形。2.2 自采数据用云台相机连续帧截取真实目标公开集覆盖不到自己项目里的背景、机型和光照就必须自采。常见做法是用带自动跟踪的云台相机录制视频让无人机从远到近、从逆光到顺光飞几个来回把背景中的树、楼、云、鸟都拍进去。不要只挑清晰帧模型要在低清、模糊、过曝的情况下工作所以运动模糊、对焦失败的帧也要留一部分。视频抽帧时不要均匀抽帧否则运动慢的时候全是重复帧快速移动时间隔又太远。我用ffmpeg的mpdecimate滤掉近似重复帧# 剔重后才抽帧避免数据冗余 ffmpeg -i drone_raw.mp4 -vf mpdecimatehi64*32:lo64*32:frac0.1,setptsN/FRAME_RATE/TB -r 5 sampled_frames/%04d.jpg参数说明mpdecimate根据像素差异剔除与上一帧高度相似的帧hi和lo控制阈值frac0.1表示允许最多10%的像素变化就保留setpts重算时间戳防止删帧后跳变-r 5限定每秒最多抽5帧。抽出来的图再交给标注软件按目标检测框标注。自采数据要额外记录相机焦距和拍摄距离方便反推真实尺度。目标在传感器上占据的像素数可以用“目标尺寸乘以焦距除以距离再除以像元尺寸”估算。如果最大监视距离下目标只有50像素训练阶段就应当重点保证该像素区间有充足样本。2.3 仿真合成样本用渲染器制作并做domain randomization真实数据很难覆盖所有气象和遮挡情况仿真合成是性价比很高的补数据方式。在Unity或Unreal里摆放无人机模型设置多角度灯光、云雾、景深模糊渲染出带透明通道的PNG再合成到真实背景照片上。由于渲染时可以拿到精确位姿标注框是自动生成的几乎不存在人工标注误差。但合成数据最大的问题是“一眼假”模型容易学到清晰的锐利边缘。我会在合成阶段做随机的gamma变换、加高斯噪声、增加运动模糊并把无人机模型粗糙度调到与实际漆面接近避免出现类似CG光斑。训练时可以先把合成数据单独预训练再用真实数据微调比较符合“先用大数量学结构再用少量真实数据调风格”的流程。来源成本标注精度背景覆盖主要风险公开集低参差不齐固定场景目标定义不一致自采高高贴近项目现场样本分布偏单一机型仿真中极高无限组合风格迁移难边缘过锐这张表格能直观对比三条路公开集适合做底料自采负责守住真实场景仿真负责把罕见情况的数量顶上去。实际项目里没有绝对最优配比我一般从公开集和自采1:1起步逐步把仿真数据插进去观察验证集mAP变化。3. 无人机识别数据集的标注格式换算COCO、YOLO、DOTA坐标关系拿到一批数据源后第一个绕不开的问题是格式不统一。很多标注工具导出COCO JSON另一些输出VOC XML无人机场景里常见的DOTA格式是四个点的多边形。如果没有统一的中间格式训练脚本会反复踩坑。格式单位目标表示是否支持旋转框COCO像素[x, y, w, h]否YOLO归一化[cls, xc, yc, w, h]否DOTA像素四个顶点坐标是3.1 COCO与YOLO格式的归一化换算最常用的目标检测格式是YOLO txt每行一个目标内容是“类别id 中心x 中心y 宽 高”全部归一化到0-1。COCO JSON里的bbox则存成[x, y, w, h]单位是像素且x、y是左上角坐标。转换时唯一容易出错的是除以图像宽高而不是减去某个预设尺寸。import json, cv2, numpy as np from pathlib import Path with open(annotations/instances_train.json) as f: coco json.load(f) img_info {img[id]: img for img in coco[images]} cat_map {cat[id]: i for i, cat in enumerate(coco[categories])} out_dir Path(yolo_labels) out_dir.mkdir(exist_okTrue) for ann in coco[annotations]: img img_info[ann[image_id]] h, w img[height], img[width] x, y, box_w, box_h ann[bbox] # 像素坐标转归一化的中心点坐标 x_center (x box_w / 2) / w y_center (y box_h / 2) / h n_w box_w / w n_h box_h / h label_line f{cat_map[ann[category_id]]} {x_center:.6f} {y_center:.6f} {n_w:.6f} {n_h:.6f}\n label_path out_dir / (Path(img[file_name]).stem .txt) with open(label_path, a) as out_f: out_f.write(label_line)逻辑说明先把COCO里的类别ID映射成从0开始的连续IDlabel_path用图片文件名的stem命名保证和图片在同一目录下用追加模式写入因为同一张图会有多个标注。转换后要抽几张图叠加显示验证避免宽高写反或类别映射错位。3.2 旋转框标注DOTA四点多边形与HBB无人机在画面里常见倾斜姿态水平框会把机臂和背景一起包进去。DOTA格式用四边形的四个点表示目标但很多目标检测模型只支持水平框。这里是两种选择一是直接取四点外包成水平矩形适合桨叶旋转后外形接近圆形的情况二是转成旋转框交给支持OBB的模型训练。用OpenCV把多边形转成旋转外接矩形import cv2 import numpy as np def poly_to_rotated_rect(poly): pts np.array(poly, dtypenp.float32).reshape(4, 2) (cx, cy), (w, h), angle cv2.minAreaRect(pts) # 统一长边为w保证角度定义只有一套 if w h: w, h h, w angle 90 return cx, cy, w, h, angle参数说明cv2.minAreaRect返回中心、宽高和旋转角度为了统一角度语义约定w永远是不小于h的边后面的角度对应长边与x轴的夹角。实际训练OBB模型时角度周期性问题会让loss震荡同一份标注最好用作者给出的角度协议做校验。如果只是做水平检测用多边形坐标的x、y最小最大值计算外包框即可代价是斜体目标框面积膨胀NMS时容易把两个邻近无人机框合并。3.3 数据划分与类别文件划分数据集时常见做法是按“拍摄片段”或“场景目录”拆分而不是按文件随机分。否则同一段视频的前后半帧会同时进入训练和验证指标好看但没有参考价值。写一个分组划分脚本把每个scene下的图片放到fold列表再按比例切分即可。训练前至少需要一个类别文件yolov8风格如下path: /data/drone train: images/train val: images/val names: 0: drone 1: bird 2: background注意这类数据集的负样本也很关键。如果只有正样本没有背景负样本模型会倾向于把任何相似纹理都判断成无人机误检率会很高。建议在val集中加入纯背景图并允许它们没有标注文件。4. yolov8训练自己的无人机识别数据集完整命令与参数把统一后的无人机识别数据集交给yolov8训练是目前开销最低、目标检测落地最快的方式之一。这里直接写我常用的环境准备、训练命令和参数调整思路不绕弯。4.1 环境准备与数据集目录先创建项目目录按yolov8约定摆放images/train、images/val、labels/train、labels/val。要保证图片和txt标签有相同的文件名缺标签的正样本会被当作背景图跳过缺标签的负样本则会丢掉。安装依赖用pip即可pip install ultralytics安装完成后用yolo detect train启动训练。如果本机有NVIDIA GPUultralytics默认会使用CUDA如果只有CPU建议把模型换成yolov8n并把batch降到2-4否则训练速度会慢到没法迭代。4.2 训练命令及关键参数训练命令可以写成这样# 用小模型快速迭代imgsz640适合显存紧张的环境 yolo detect train datadrone.yaml modelyolov8n.pt \ imgsz640 batch16 epochs100 lr00.01 \ optimizerAdamW cos_lrTrue patience20 \ projectruns/drone namebase参数说明imgsz640是训练输入尺寸。对于无人机小目标可以提升到1280显存不够时先降低batchbatch16在有GPU时设为显存能容的上限通常用batch-1自适应即可lr00.01是初始学习率数据规模大而目标小时可以降到0.005cos_lrTrue用余弦退火能减少后期loss震荡patience20表示验证集指标连续20个epoch不涨就提前停止。yolov8默认开启Mosaic增强这对大目标很有用但无人机识别数据中小目标居多大片背景被裁掉后小目标可能消失。如果训练中期loss降不下去可以关掉或降低Mosaic比例。这里给出常用的一组hyp参数参考参数通用值无人机识别建议原因mosaic1.00.3保留小目标上下文scale0.50.8模拟不同飞行距离fliplr0.50.0避免左右不对称机型产生歧义hsv_h0.0150.02微调颜色防止过拟合背景补充说明fliplr设为0.0是我个人经验少数机型的云台或天线只在单侧水平翻转会让类别语义不准确。scale提高后模型会在更多尺度上看到目标但过大的scale会引入严重形变需要看训练曲线调整。4.3 训练后验证与导出验证时为了看清模型的真实漏检情况不要用默认置信度0.25做报告。低置信度候选对后续难例挖掘非常重要先用0.001跑一遍# conf设低把低置信度候选保留下来 yolo detect val modelruns/drone/base/weights/best.pt \ datadrone.yaml imgsz640 conf0.001 iou0.5参数说明conf0.001让所有高于千分之一的预测都输出会看到很多漏检被转化为低分置信度候选iou0.5是用IoU阈值判定匹配成功用于评估mAP50。验证通过后如果要部署到边缘盒子导出ONNX或TensorRTyolo export modelruns/drone/base/weights/best.pt formatonnx imgsz640导出的best.onnx可以用ONNXRuntime在CPU或GPU上跑也可以进一步量化为INT8模型量化对小目标精度会有一定损失需要结合验证结果决定是否启用。5. 无人机小目标检测切片推理与mmrotate旋转框回炉很多无人机识别数据集训练出来的模型mAP能到0.8但实地测试时远处的无人机一个都检不出来。问题不是模型差而是小目标在特征提取过程中信息消散了。5.1 为什么无人机识别数据集在小目标上漏检目标检测网络通常有5次下采样最终特征图的步长达到32。一个10x10像素的无人机在最后特征图上只占不到1个像素的激活区域。目标框太小还容易在NMS阶段被周围高分背景候选压掉。更麻烦的是训练阶段Anchor和候选框默认针对中等目标大尺寸预训练模型里的先验与小目标不匹配导致召回率很低。针对这个问题的第一道解法是提高输入分辨率但显存占用上升代价很大。第二道解法是切片推理让模型在局部放大区域里找小目标相当于把推理时的“等效焦距”拉长。5.2 用切片推理把大图切块提升小目标召回切片推理在小目标检测里非常常见做法是先把原图切成若干有重叠的patch逐patch检测再把结果映射回原图坐标。用sahi库实现这条流程可以省去很多坐标换算代码# 推理时用20%重叠避免目标被切断 sahi predict --model_type yolov8 \ --model_path runs/drone/base/weights/best.pt \ --source test.jpg --save_dir sahi_out \ --slice_width 512 --slice_height 512 \ --overlap_height_ratio 0.2 --overlap_width_ratio 0.2 \ --conf_threshold 0.15参数说明slice_width/height是切片尺寸建议与训练imgsz一致overlap_*_ratio控制重叠比例0.2能缓解目标被切断的问题conf_threshold比常规推理低因为切片放大了目标模型置信度会整体升高但这个值仍要给后续NMS留空间。切片推理的代价是N倍耗时。比如一张3840x2160的图切成512x512加20%重叠大约有60多个patch在CPU上可能是几十秒。工程落地时需要对远景和近景做策略分流近景目标足够大时直接整图检测远景才走切片流程。5.3 旋转框场景用mmrotate训练DOTA数据集做回炉如果无人机在数据集中呈现明显的倾斜姿态水平框NMS会把斜着飞的两架机器误判成重叠这时需要旋转框模型。mmrotate是目标检测生态里对旋转框支持最成熟的选择之一DOTA数据集是它在遥感上的标准基准无人机识别可以沿用这套训练管线。先准备mmrotate环境核心依赖是mmcv和PyTorchconda create -n mmrotate python3.8 -y conda activate mmrotate pip install torch torchvision pip install openmim mim install mmcv pip install mmrotate环境装完后把自己的旋转标注按DOTA格式整理再修改配置文件把angle_version设为le90训练命令通常是# 实际训练前需修改数据集的class_num和路径 python tools/train.py configs/oriented_rcnn/oriented_rcnn_r50_fpn_1x_dota.py --work-dir work_dirs/drone这里要说明三点一是该配置文件默认用于遥感目标需要修改数据集的class_num、数据集路径和图像scale二是旋转框模型的loss对角度敏感训练前最好先做可视化确保角度定义一致三是mmrotate对PyTorch版本要求较严版本冲突时优先按它的官方环境组合固定版本。6. 无人机识别数据集清洗与难例挖掘用验证结果反向修订最后需要回到数据集本身。模型已经训练完但验证集里仍有一些mAP分析看不到的信息比如哪些小目标被漏检、哪些背景被误报。反向修订数据集比继续加epoch更有效。6.1 统计漏检框的尺寸分布把验证集里没有与真值匹配上的低置信度候选导出统计它们的面积分布能直接看出模型在哪一段距离失效。用ultralytics的predict模式把所有预测结果保存在predictions.json再与标签做匹配提取未匹配真值。import json, glob, numpy as np preds json.load(open(runs/drone/val/predictions.json)) gt_files glob.glob(datasets/val/labels/*.txt) miss_areas [] for pred in preds: img_name pred[image_id] .jpg gt_path datasets/val/labels/ img_name.replace(.jpg, .txt) gts np.loadtxt(gt_path, ndmin2) match False for gt in gts: gt_area gt[3] * gt[4] pred_box pred[bbox] pred_area pred_box[2] * pred_box[3] iou compute_iou(pred_box, gt_box) if iou 0.5: match True break if not match: miss_areas.append(gt_area) print(missed gt target areas:, np.percentile(miss_areas, [25, 50, 75]))这里省略了compute_iou的实现匹配含义是IoU过0.5算命中把所有未命中的真值框面积沿升序排列。如果中位数很小说明切片推理必须设为常驻流程如果中位数不小说明数据分布里缺少和目标相近的背景干扰要补负样本。6.2 难例增强裁剪硬例回灌训练集从漏检真值框里裁剪出原图区域按固定宽高放大后做随机旋转、亮度扰动再作为小目标正样本回灌到训练集。注意不要重复得太厉害一个硬例最多复制3次否则模型会对这张图过拟合。同时误报最高的背景区域也应该裁下来作为负样本目标检测里的负样本需要形成文件而不是放在背景图片里让模型自己忽略。负样本文件可以只写类别编号不写框信息yolov8会把它当作背景图处理。6.3 数据质量验证可视化检查脚本改动数据集后首先要做的是可视化检查。写一个小脚本把每张图的标签和预测框同时画出来拼成4x4网格人工过一眼往往能发现坐标偏移、类别错标、目标框太小等问题。import glob import cv2 import numpy as np def draw_label(img_path, label_path): img cv2.imread(img_path) h, w img.shape[:2] if not label_path.exists(): return img for line in open(label_path): cls, xc, yc, bw, bh map(float, line.split()) # 归一化坐标还原为像素坐标 x1 int((xc - bw/2) * w) y1 int((yc - bh/2) * h) x2 int((xc bw/2) * w) y2 int((yc bh/2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) return img imgs glob.glob(datasets/val/images/*.jpg)[:16] grid np.hstack([ cv2.resize(draw_label(im, Path(im.replace(images, labels)).with_suffix(.txt)), (320, 320)) for im in imgs ]) cv2.imwrite(vis_check.jpg, grid)脚本把前16张验证图的标签画出来并横向拼接最终得到一张vis_check.jpg。脚本只处理了水平框如果是旋转标注需要改成画多边形。跑完脚本后重点看三类问题标注是否紧贴目标物体、小目标是否在缩略图上肉眼可见、类别错标是否让相近目标的分布重合。无人机识别数据集修订完再用上一章的命令重新训练一轮模型提升往往比调参更明显。本文还有配套的精品资源点击获取
返回列表