多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

189张军事目标YOLO数据集:从标注格式到yolov8训练全流程

189张军事目标YOLO数据集:从标注格式到yolov8训练全流程 简介这份资源面向从事军事目标探测与识别研究的算法工程师、高校学生及竞赛选手提供一套可直接用于YOLO系列模型训练与验证的目标检测数据集覆盖飞机、无人机等典型军事目标类别。压缩包共190个文件以189张jpg图像为主另附1个yaml配置文件用于声明类别与路径信息整体约8.55MB体积轻便便于快速加载与迁移实验。数据集已预先划分训练与验证集并同时提供YOLO格式txt标签与VOC格式xml标签两套标注前者以归一化中心点与宽高比例描述目标框后者便于兼容传统检测框架可灵活适配yolov5、yolov8、yolov9、yolov7、yolov10及yolo11等主流算法。目前已有461人学习下载适合作为小样本军事目标检测的入门练手或算法对比基准帮助读者省去数据采集与标注成本快速搭建训练流程并验证模型在特定场景下的检测效果。1. 189 张军事目标图带标签这份 YOLO 数据集到底能跑出什么上周有个做边缘端安防的朋友找我说想验证一个飞机、无人机、直升机混检的模型但公开数据集要么类别太杂要么标注格式对不上自己标 200 张图又嫌慢。我翻出这份 189 张图像带标签的军事目标探测数据集丢给他他当天下午就跑通了 yolov8n 的 baseline。这份资源的核心价值很直接图像和标签已经配对好YOLO 格式的 txt 和 VOC 格式的 xml 分文件夹存放训练集、验证集、测试集也提前划分完毕拿到手不用再做清洗和切分直接指向 data.yaml 就能开训。它适合三类人想快速验证军事目标检测链路的算法工程师、需要小样本数据集做课程设计或毕设的学生、以及拿它当预训练起点再扩自己数据的从业者。189 张不算多但胜在类别聚焦在飞机、无人机、直升机这几个容易混淆的目标上拿来练手和跑通流程足够。2. 数据集结构与标签格式先看清目录再动手2.1 目录布局与文件命名规律拿到压缩包解压后第一件事不是急着写训练脚本而是把目录结构摸清楚。这份数据集的典型布局是 images 和 labels 两个平行目录各自下面再分 train、val、test 三个子目录。图像文件名保留了原始来源的痕迹比如depositphotos_242154762-stock-photo-chinese-wz-10-attack-helicopters_jpg.rf.bc5c7c732a068eb9fec144c20bf61695.jpg这种中间那串.rf.后面的哈希值是标注工具导出时自动加的去重标识不影响读取但用 glob 匹配时要注意别把它当成类别信息。标签目录里对应的是同名 txt 文件VOC 格式的 xml 则单独放在另一个文件夹。常见做法是先用一条命令把文件数量和配对情况点一遍# 统计图像与标签数量确认是否一一对应 find images/train -name *.jpg | wc -l find labels/train -name *.txt | wc -l # 检查是否有图像缺失对应标签 for f in images/train/*.jpg; do base$(basename $f .jpg) [ -f labels/train/$base.txt ] || echo 缺失标签: $f done这段脚本的逻辑很直白先数数量再逐个比对文件名。参数上唯一要注意的是basename去后缀时要和实际图像扩展名一致如果混了.jpeg或.png得把-name *.jpg改成对应模式。跑完如果输出为空说明配对完整可以进入下一步如果有缺失要么补标要么把对应图像移出训练集别留着让 DataLoader 报错。2.2 YOLO 格式与 VOC 格式的字段含义YOLO 格式的 txt 每行代表一个目标五个字段依次是class x_center y_center width height。class 是从 0 开始的类别索引后四个都是归一化到 0 到 1 之间的比例值分别表示框中心点的 x、y 坐标和框的宽、高。这里最容易翻车的地方是有人把像素坐标直接写进去训练时 loss 不降反升排查半天才发现是没做归一化。VOC 格式的 xml 则是绝对像素坐标xmin ymin xmax ymax四个值类别写在name标签里。两种格式各有用途YOLO 格式直接喂给 ultralytics 系列VOC 格式方便用 labelImg 二次修改或转成 COCO。格式坐标类型类别表示适用场景YOLO txt归一化比例值整数索引yolov5/v8/v11 直接训练VOC xml绝对像素值字符串名称labelImg 编辑、格式转换我一般会先抽一张图用脚本把框画出来目检一遍确认标注没有整体偏移。下面这段代码读一张 YOLO 标签并叠加到原图上import cv2 img cv2.imread(images/train/sample.jpg) h, w img.shape[:2] with open(labels/train/sample.txt) 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.imwrite(check.jpg, img)逻辑说明先取图像宽高再把归一化的中心点和宽高换算回像素边界。参数上xc - bw/2是左边界yc - bh/2是上边界乘上 w 和 h 得到实际像素。画完打开 check.jpg 看一眼如果框明显偏了大概率是标注时图像被旋转过或坐标写反了这种样本要单独拎出来处理。3. 从零跑通训练data.yaml 配置与 yolov8 启动命令3.1 写对 data.yaml 的三个关键字段ultralytics 系列靠一个 yaml 文件告诉训练器去哪里找数据、有哪些类别。这份数据集已经分好 train、val、test所以 yaml 里主要填三个字段path 指向数据集根目录train 和 val 填相对路径names 按类别索引顺序列出名称。常见做法是这样写# data.yaml path: /home/user/military_dataset train: images/train val: images/val test: images/test nc: 3 names: 0: airplane 1: drone 2: helicopter参数说明path用绝对路径最稳避免训练时工作目录变化导致找不到文件train和val是相对 path 的子路径ultralytics 会自动把images替换成labels去找标签所以目录名必须保持 images/labels 的对应关系。nc是类别数names的键必须从 0 连续编号中间断了会报索引越界。如果这份数据集的类别名称和上面不同以实际标注为准别照抄。3.2 启动 yolov8 训练与关键超参环境装好后一条命令就能开训。我一般先用 nano 级别跑通流程确认 loss 正常下降再换大模型# 安装 ultralytics pip install ultralytics # 用 yolov8n 跑 100 轮图像尺寸 640 yolo detect train \ datadata.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ device0 \ projectruns/military \ nameexp1逻辑说明modelyolov8n.pt会先下载预训练权重再微调小数据集上比从零训收敛快得多。imgsz640是输入分辨率189 张图用 640 足够再大容易过拟合。batch16在单张 8G 显存卡上比较稳显存不够就降到 8。device0指定第一块 GPUCPU 训练把这里改成cpu但速度会慢一个量级。跑起来后重点盯三个指标box_loss 是否持续下降、mAP50 是否在 50 轮后开始抬头、val 的 loss 有没有反弹。如果 box_loss 从第一轮就卡在 1.0 以上不动八成是标签格式或路径配错了回去查 data.yaml 和 txt 内容。3.3 验证与推理确认模型真的学到了东西训练结束后用 val 集跑一次验证再用一张没见过的图做推理两步都过了才算跑通# 在验证集上评估 yolo detect val modelruns/military/exp1/weights/best.pt datadata.yaml # 单张图像推理并保存结果 yolo detect predict \ modelruns/military/exp1/weights/best.pt \ sourceimages/test \ saveTrue \ conf0.25参数说明conf0.25是置信度阈值低于这个值的框不输出。军事目标里无人机往往很小阈值设太高会漏检可以先设 0.25 看召回再根据误报情况往上调。saveTrue会把画框后的图存到 runs 目录下打开目检一遍重点看飞机和无人机有没有互相误判——这两类在远距离小目标上特征接近是这份数据集最容易混淆的地方。4. 避坑与排查189 张小数据集训练时最容易翻的五个坑4.1 现象训练启动即报 “No labels found”原因通常是 data.yaml 里的路径写错或者 labels 目录名和 images 不匹配。ultralytics 默认把路径里的images替换成labels去找标签如果实际目录叫labels_yolo就找不到。解决办法是把目录名统一成 images 和 labels或者在 yaml 里显式指定 labels 路径。另一种情况是 txt 文件编码不对Windows 下用记事本存成了带 BOM 的 UTF-8读第一行会多出不可见字符导致解析失败用file命令查一下编码统一转成无 BOM 的 UTF-8。4.2 现象mAP 一直为 0loss 却不报错这种最迷惑人。常见原因是类别索引越界——txt 里写了 class 3但 data.yaml 里 nc 只有 3索引 0 到 2越界的框被静默丢弃模型学不到任何正样本。排查方法是统计所有 txt 里出现过的 class 值cat labels/train/*.txt | awk {print $1} | sort -u输出的数字如果大于等于 nc就说明有越界标注要么改 nc要么把越界的行修正。另一个可能是坐标全为 0 或超出 0 到 1 范围同样用 awk 扫一遍后四列的最小最大值就能发现。4.3 现象验证集指标远高于测试集怀疑过拟合189 张图本身量小如果 train 和 val 里出现了同一场景的近似帧验证指标会虚高。解决办法是检查划分时有没有把同一段视频的连续帧分到不同集合。我一般会按图像来源分组再切分同一来源的图要么全在 train要么全在 val避免信息泄漏。另外可以开数据增强ultralytics 默认带 mosaic 和 HSV 扰动小数据集上把mosaic1.0保持开启能明显缓解过拟合。4.4 现象推理时框位置整体偏移如果训练指标正常但推理框偏了先确认推理时的imgsz和训练时一致。训练用 640 推理用 320归一化尺度对不上框就会缩水或偏移。另一个原因是图像在标注后被裁剪过但标签没同步更新这种只能重新标注或把该图剔除。用第 2 章那段画框脚本在训练前目检一遍能提前拦住大部分坐标问题。4.5 现象显存溢出中断训练batch 设太大或 imgsz 太高都会撑爆显存。8G 卡上 yolov8n 配 640 分辨率batch 16 一般安全换 yolov8m 就得降到 8 甚至 4。如果不想降 batch可以开梯度累积模拟大 batch或者用ampTrue开启混合精度显存占用能降三成左右。中断后想续训加resumeTrue从 last.pt 接着跑别从头再来。5. 小数据集的进阶玩法迁移学习、剪枝与格式互转189 张图直接训一个三分类模型mAP 能到 0.6 左右就算不错想再往上走得在迁移学习和数据扩充上做文章。我一般会先用 COCO 预训练的 yolov8s 做 backbone 冻结训练前 20 轮只训检测头让模型先适应军事目标的特征分布再解冻全部层微调。冻结训练的命令是在 train 里加freeze10表示冻结前 10 层这样小数据集上不容易把预训练学到的通用特征带偏。数据扩充方面这份数据集类别聚焦但场景有限可以用 albumentations 做离线增强把 189 张扩到 500 张左右。重点加随机裁剪、旋转和小目标复制粘贴因为无人机在原始图里往往只占几十个像素复制粘贴能显著提升小目标召回。增强后的图要重新生成 YOLO 标签别直接复用原标签否则框和图像对不上。格式互转也是常被忽略的一环。VOC 的 xml 转 YOLO txt 时归一化要用图像实际宽高不能想当然用 640。下面这段脚本处理单文件转换import xml.etree.ElementTree as ET from PIL import Image def voc_to_yolo(xml_path, img_path, class_map): tree ET.parse(xml_path) root tree.getroot() w, h Image.open(img_path).size lines [] for obj in root.findall(object): cls class_map[obj.find(name).text] 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) # 转成归一化中心点与宽高 xc (xmin xmax) / 2 / w yc (ymin ymax) / 2 / h bw (xmax - xmin) / w bh (ymax - ymin) / h lines.append(f{cls} {xc:.6f} {yc:.6f} {bw:.6f} {bh:.6f}) return \n.join(lines)逻辑说明先读 xml 拿到绝对坐标再用 PIL 读图像真实宽高做归一化。class_map是类别名到索引的映射字典必须和 data.yaml 里的 names 顺序一致。保留六位小数是为了避免小目标坐标精度丢失尤其是无人机这种小框少一位小数可能就差出几个像素。剪枝这块189 张图训出来的模型本身不大剪枝收益有限但如果要部署到边缘设备可以用 torch.prune 对卷积层做结构化剪枝再微调 10 轮恢复精度。我试过把 yolov8n 剪掉 20% 通道模型体积降了约 15%mAP 掉不到 2 个点对算力紧张的场景值得一试。验证剪枝效果时别只看 mAP还要在真实推理速度上测一遍有时候参数少了但算子不友好延迟反而没降。从那以后我每次拿到新数据集都强制先跑一遍配对检查和画框目检再动训练脚本。这两步花不到十分钟能省下后面几小时的排查。希望帮到你。本文还有配套的精品资源点击获取
返回列表