ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

飞机型号识别数据集选型与YOLO训练:从军机检测到细粒度分类实战

2026/10/5 17:26:31 拓冰建站 浏览量
飞机型号识别数据集选型与YOLO训练:从军机检测到细粒度分类实战 简介这份飞机型号识别数据集04面向从事目标检测与细粒度图像分类的算法研究者、学生及军工爱好者采集自俄罗斯机场覆盖苏霍伊、米格、安东诺夫、伊尔、雅克、图波列夫等47种军民机型可用于飞机检测、型号识别等模型的训练与验证。资源包共2001个文件含1000张1024×768可见光RGB图像、1000份labelimg标注的xml标签及1份说明txt压缩包约250.43MB图像与标注一一对应开箱即可投入训练。目前已有219人学习下载。该批次与02、03、05等批次采集地点和机型均不相同读者可据此构建多场景数据组合用于模型泛化能力对比、类别不平衡分析与标注格式转换等实验适合作为目标检测课程设计或科研预研的实用素材。1. 飞机型号识别数据集从军机识别到目标检测的落地选型拿到「飞机型号识别数据集」这个标题很多人第一反应是去找一个开箱即用的压缩包解压、训练、出结果。但真正做过军机识别和飞机目标检测的人都知道数据集从来不是「一个包」的事而是一整套从标注体系、类别粒度到场景覆盖的工程决策。飞机分类数据集解决的是「这张图里是什么机型」飞机目标检测数据集解决的是「图里哪里有几架飞机、分别是什么」两者在标注格式、评估指标和落地链路上完全不同。如果你正在做遥感目标检测、机场场面监控或者军机识别相关的课题这篇笔记会从数据集选型、格式转换、YOLO 训练参数到踩坑排查把一条能复现的路径讲清楚。适合刚接触目标检测的新手照着走也适合做过通用检测、想切到细粒度飞机型号识别的熟手看边界。2. 飞机型号识别数据集到底分几类分类、检测与细粒度识别的边界2.1 飞机分类数据集和目标检测数据集的本质区别飞机分类数据集的组织形式通常是「一个文件夹一个类别」目录名就是机型标签比如J-20/、F-16/、Su-35/、C-130/。这种结构直接喂给 ImageNet 风格的分类网络就能跑评估指标是 Top-1 / Top-5 准确率。它的问题是一张图里如果有多架飞机或者飞机只占画面一小块分类标签就变得含糊——整张图被强行打上一个机型标签背景和无关区域全被当成特征学进去。飞机目标检测数据集则是每张图配一个标注文件记录每个飞机实例的边界框坐标和类别。常见格式有 PASCAL VOC 的 XML、COCO 的 JSON、YOLO 的 txt。评估指标是 mAP0.5、mAP0.5:0.95、Precision、Recall。军机识别场景下检测比分类更贴近真实需求因为你要知道「哪里有飞机」以及「那架是什么型号」而不是给整张卫星图打一个标签。细粒度识别是夹在中间的一层。同样是战斗机J-20 和 F-22 的轮廓差异在低分辨率遥感图里可能只有几个像素的边条翼和尾喷口区别。这时候分类数据集如果类别粒度太细、每类样本又少模型很容易退化成「记住背景」而不是「记住机型」。我一般会建议先做检测把飞机框出来再在框内做细粒度分类两阶段比端到端硬训更稳。2.2 军机识别场景下类别体系怎么定军机识别的类别体系不是越多越好。常见做法是按「代际 用途」粗分比如战斗机、轰炸机、运输机、预警机、直升机、无人机六大类再在战斗机下面细分型号。如果一上来就做 50 类机型每类只有几十张图mAP 会非常难看。一个可操作的类别体系设计原则层级类别示例建议最小样本数标注粒度粗类战斗机、运输机、直升机每类 500边界框中类三代机、四代机、大型运输机每类 200边界框 机型细类J-20、F-35、Su-57每类 100边界框 型号如果手头数据只够做粗类就不要硬标细类。标注不一致比类别少更致命——同一架飞机在不同标注员手里标成不同型号模型学到的就是噪声。2.3 遥感目标检测和常规目标检测的数据差异遥感飞机检测和常规自然图像检测有几个硬差异。第一目标尺度极端一架飞机在 10000×10000 的卫星图里可能只有 30×30 像素直接缩放到 640×640 输入网络后只剩几个像素。第二方向任意飞机朝向不固定水平框会引入大量背景旋转框更合适但标注成本高。第三背景单一但干扰多机场跑道、停机坪、机库阴影都容易和飞机混淆。常见做法是切图。把大图切成 1024×1024 或 512×512 的瓦片带重叠区域再送进检测网络。重叠率一般设 20%30%避免飞机被切一半导致漏标。切图脚本里要记录每块瓦片在原图的偏移量推理时再把框映射回原图做 NMS 合并。3. 把飞机检测数据集转成 YOLO 格式脚本、参数与四个边界坑3.1 VOC 转 YOLO 的转换脚本大多数公开的飞机目标检测数据集是 VOC 格式而 YOLO 系列训练需要每张图一个 txt每行class_id x_center y_center width height全部归一化到 01。下面是我常用的转换脚本处理 XML 标注import os import xml.etree.ElementTree as ET # 类别映射按你的数据集实际类别修改 CLASS_MAP { fighter: 0, bomber: 1, transport: 2, helicopter: 3, uav: 4, } def convert_voc_to_yolo(xml_dir, img_dir, out_dir): os.makedirs(out_dir, exist_okTrue) for xml_file in os.listdir(xml_dir): if not xml_file.endswith(.xml): continue tree ET.parse(os.path.join(xml_dir, xml_file)) root tree.getroot() size root.find(size) w int(size.find(width).text) h int(size.find(height).text) lines [] for obj in root.iter(object): name obj.find(name).text.strip() if name not in CLASS_MAP: continue # 跳过未定义类别避免训练时报错 bbox obj.find(bndbox) xmin float(bbox.find(xmin).text) ymin float(bbox.find(ymin).text) xmax float(bbox.find(xmax).text) ymax float(bbox.find(ymax).text) # 裁剪到图像边界防止标注越界 xmin max(0, min(xmin, w)) ymin max(0, min(ymin, h)) xmax max(0, min(xmax, w)) ymax max(0, min(ymax, h)) if xmax xmin or ymax ymin: continue # 跳过无效框 xc (xmin xmax) / 2.0 / w yc (ymin ymax) / 2.0 / h bw (xmax - xmin) / w bh (ymax - ymin) / h lines.append(f{CLASS_MAP[name]} {xc:.6f} {yc:.6f} {bw:.6f} {bh:.6f}) out_path os.path.join(out_dir, xml_file.replace(.xml, .txt)) with open(out_path, w) as f: f.write(\n.join(lines)) convert_voc_to_yolo(annotations_xml, images, labels_yolo)逻辑说明脚本遍历 XML 目录读取图像宽高做归一化把 VOC 的左上右下坐标转成 YOLO 的中心点加宽高。CLASS_MAP必须和你的data.yaml里names顺序一致否则类别全乱。裁剪到边界和跳过无效框这两步是后悔药不做的话训练时会出现负宽度或超出 1.0 的坐标YOLO 会直接报错或者静默丢弃。参数说明xc、yc是归一化中心坐标bw、bh是归一化宽高保留 6 位小数足够。如果你的数据集有difficult标记可以在循环里判断obj.find(difficult)并决定是否跳过。3.2 data.yaml 的写法与路径坑YOLO 训练靠data.yaml找数据。一个飞机检测的典型配置path: /data/aircraft_det train: images/train val: images/val test: images/test names: 0: fighter 1: bomber 2: transport 3: helicopter 4: uav注意path是数据集根目录train和val是相对路径。YOLO 会在path/train找图片同时把路径里的images替换成labels去找同名 txt。也就是说images/train/a.jpg对应labels/train/a.txt。这个隐式替换规则是新手翻车最多的地方图片和标签目录结构不一致训练时找不到标签模型会把所有图当负样本loss 降不下去但 mAP 为 0。3.3 切图与重叠遥感飞机小目标的预处理遥感大图直接训练不现实切图是必须的。下面这个脚本按 1024 窗口、30% 重叠切图并同步裁剪标注框import cv2 import os def slice_image(img_path, label_path, out_img_dir, out_lbl_dir, slice_size1024, overlap0.3): img cv2.imread(img_path) h, w img.shape[:2] step int(slice_size * (1 - overlap)) labels [] if os.path.exists(label_path): with open(label_path) as f: labels [list(map(float, l.split())) for l in f if l.strip()] idx 0 for y in range(0, h, step): for x in range(0, w, step): x2 min(x slice_size, w) y2 min(y slice_size, h) patch img[y:y2, x:x2] ph, pw patch.shape[:2] new_lines [] for cls, xc, yc, bw, bh in labels: # 还原到原图绝对坐标 abs_xc xc * w abs_yc yc * h abs_w bw * w abs_h bh * h # 判断中心点是否落在当前瓦片内 if x abs_xc x2 and y abs_yc y2: nx (abs_xc - x) / pw ny (abs_yc - y) / ph nw abs_w / pw nh abs_h / ph new_lines.append(f{int(cls)} {nx:.6f} {ny:.6f} {nw:.6f} {nh:.6f}) if new_lines: name f{os.path.splitext(os.path.basename(img_path))[0]}_{idx} cv2.imwrite(os.path.join(out_img_dir, name .jpg), patch) with open(os.path.join(out_lbl_dir, name .txt), w) as f: f.write(\n.join(new_lines)) idx 1逻辑说明按步长滑动窗口切图只保留中心点落在瓦片内的目标。这样做的代价是边缘目标可能被切掉一部分但避免了同一个目标在多个瓦片里重复出现导致训练标签冲突。如果你的场景要求召回优先可以改成「框与瓦片有交集就保留」但要在推理阶段做跨瓦片 NMS 合并。参数说明slice_size根据你的 GPU 显存和飞机像素尺寸定飞机普遍小于 50 像素时用 512 或 640 更合适。overlap设 0.20.3太小会漏掉跨边界目标太大则冗余样本翻倍。3.4 标注质量检查三个必查项转换完先别急着训。我一般会跑三个检查第一统计每个类别的框数量某类少于 50 个框就要考虑合并或补充第二随机抽 20 张图把 YOLO 格式画回原图看框是否贴合第三检查有没有宽高为 0 或坐标大于 1 的脏数据。画框验证的代码很短import cv2 def draw_yolo(img_path, label_path, names): img cv2.imread(img_path) h, w img.shape[:2] with open(label_path) as f: for line in f: 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) cv2.putText(img, names[int(cls)], (x1, y1 - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2) cv2.imwrite(check.jpg, img)这一步花十分钟能省掉后面几小时的无效训练。4. 用 YOLO 训练飞机检测模型环境、参数与显存调优4.1 环境配置与最小训练命令YOLO 系列目前主流用 Ultralytics 的框架安装就一条命令pip install ultralytics训练飞机检测模型的最小命令yolo detect train \ data/data/aircraft_det/data.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ device0逻辑说明model指定预训练权重飞机检测样本通常几千到几万张从 COCO 预训练权重微调比从头训收敛快得多。imgsz是输入分辨率飞机小目标多时建议提到 1024 或 1280但显存占用会平方增长。batch根据显存调16 是 8GB 显存的保守值。参数说明epochs设 100300看验证集 mAP 是否还在涨。device0指定第一块 GPUCPU 训练用devicecpu但速度不可接受。如果显存不够优先降batch再降imgsz不要一上来就换小模型。4.2 飞机小目标检测的关键参数飞机检测和通用检测最大的参数差异在imgsz和 anchor 相关设置。YOLOv8 是 anchor-free 的不需要手动调 anchor但输入分辨率直接决定小目标能不能被看到。一架 30 像素的飞机在 640 输入下只剩 30 像素在 1280 下变成 60 像素特征图上多一层响应。另一个关键是数据增强。飞机检测不建议用太强的随机裁剪因为裁剪容易把飞机切掉。我一般会关掉mosaic或者把mosaic概率降到 0.5 以下degrees设小一点飞机有朝向大角度旋转会引入不真实样本flipud在遥感图里可以开因为卫星俯视图上下翻转物理上合理。yolo detect train \ data/data/aircraft_det/data.yaml \ modelyolov8s.pt \ epochs200 \ imgsz1024 \ batch8 \ mosaic0.3 \ degrees10 \ flipud0.5 \ fliplr0.5 \ device04.3 训练过程看什么loss、mAP 与过拟合信号训练日志里重点看三个东西。第一box_loss和cls_loss是否稳定下降如果 cls_loss 震荡剧烈多半是类别不平衡或标注噪声。第二验证集 mAP0.5 和 mAP0.5:0.95 的差距差距大说明框回归不准可能是小目标太多或标注框偏大。第三训练集 mAP 远高于验证集 mAP 时就是过拟合加数据或加增强不要一味加 epoch。如果 mAP 卡在某个值不动先查标注再查类别分布最后才调模型。我见过太多人一上来就换大模型结果发现是某个类别的框全标错了。5. 飞机型号识别避坑五条血泪经验5.1 类别不平衡导致小类全军覆没现象训练完 mAP 看着还行但直升机、无人机这些小类几乎检不出来。原因战斗机样本占 80%模型倾向于把所有疑似目标判成战斗机。解决对稀有类做过采样或者在 loss 里加类别权重。Ultralytics 框架下可以复制小类图片到训练集简单粗暴但有效。5.2 图片和标签路径不匹配导致 mAP 为 0现象训练 loss 正常下降但验证 mAP 一直是 0。原因data.yaml里train指向images/train但标签实际在labels/train之外的目录YOLO 找不到标签把所有框当背景。解决确认images和labels目录同级且文件名一一对应用ls labels/train | head和ls images/train | head对比。5.3 遥感大图不切图直接训练导致显存爆炸现象一跑训练就 OOM或者图片被强行缩放到 640 后飞机变成几个像素。原因原始卫星图可能 10000×10000直接读入内存就爆缩放后又丢失小目标。解决先切图再训练切图尺寸和重叠率按 3.3 节的脚本处理。5.4 标注框把飞机阴影和尾迹包进去现象模型学到的框比飞机实际大一圈推理时框重叠严重。原因标注员把飞机阴影、尾迹甚至旁边的小车都框进去了。解决重新定义标注规范框只包机身和机翼阴影不标。已经标完的可以统计框的宽高分布把明显异常的框挑出来复查。5.5 验证集和训练集同源导致指标虚高现象验证集 mAP 0.9换一批新图推理效果很差。原因训练集和验证集是从同一张大图切出来的瓦片相邻瓦片高度相似等于变相泄漏。解决按原图划分训练验证集同一张大图的瓦片只能出现在一个集合里。这个坑在遥感目标检测里极其常见指标好看但落地翻车。6. 飞机型号识别的进阶技巧从检测框到细粒度分类的级联方案检测做完只是第一步军机识别真正难的是型号细分。我一般用级联方案YOLO 负责把飞机框出来裁出框内图像再送进一个分类网络做型号识别。这样做的好处是检测和分类解耦分类网络可以用更大的输入尺寸看细节检测网络不用背细粒度的包袱。分类网络选型上飞机型号识别属于细粒度分类ResNet 和 EfficientNet 都能用但关键在数据增强和损失函数。我习惯用RandomResizedCrop加ColorJitter损失用标签平滑或者 ArcFace。ArcFace 在类别多、类间差异小的场景下比交叉熵更稳因为它强制类内紧凑、类间分离。级联的工程实现要注意两点。第一检测框裁图时往外扩 10%20%避免机身被切掉。第二分类置信度低时不要硬判可以设一个阈值低于阈值的输出「未知机型」比强行猜一个错误型号更实用。验证级联效果的方法在验证集上先跑检测统计检测召回率再在检测正确的框上跑分类统计分类准确率。两个指标乘起来才是端到端的型号识别准确率。很多人只看分类准确率忽略了检测漏检对最终结果的影响。最后说一个我自己的习惯每次训完模型我都会拿几十张完全没参与训练的图人工看推理结果把错例截图存下来。这些错例比 mAP 数字更能告诉我下一步该补什么数据、调什么参数。飞机型号识别这个方向数据质量的决定性远大于模型结构的花哨程度。希望帮到你。本文还有配套的精品资源点击获取