☰
189张军事目标YOLO数据集:从标注格式到yolov8训练全流程
2026/10/10 18:29:39 网站建设 项目流程

简介:这份资源面向从事军事目标探测与识别研究的算法工程师、高校学生及竞赛选手,提供一套可直接用于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 \ data=data.yaml \ model=yolov8n.pt \ epochs=100 \ imgsz=640 \ batch=16 \ device=0 \ project=runs/military \ name=exp1

逻辑说明:model=yolov8n.pt会先下载预训练权重再微调,小数据集上比从零训收敛快得多。imgsz=640是输入分辨率,189 张图用 640 足够,再大容易过拟合。batch=16在单张 8G 显存卡上比较稳,显存不够就降到 8。device=0指定第一块 GPU,CPU 训练把这里改成cpu但速度会慢一个量级。跑起来后重点盯三个指标:box_loss 是否持续下降、mAP50 是否在 50 轮后开始抬头、val 的 loss 有没有反弹。如果 box_loss 从第一轮就卡在 1.0 以上不动,八成是标签格式或路径配错了,回去查 data.yaml 和 txt 内容。

3.3 验证与推理:确认模型真的学到了东西

训练结束后,用 val 集跑一次验证,再用一张没见过的图做推理,两步都过了才算跑通:

# 在验证集上评估 yolo detect val model=runs/military/exp1/weights/best.pt data=data.yaml # 单张图像推理并保存结果 yolo detect predict \ model=runs/military/exp1/weights/best.pt \ source=images/test \ save=True \ conf=0.25

参数说明:conf=0.25是置信度阈值,低于这个值的框不输出。军事目标里无人机往往很小,阈值设太高会漏检,可以先设 0.25 看召回,再根据误报情况往上调。save=True会把画框后的图存到 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 一直为 0,loss 却不报错

这种最迷惑人。常见原因是类别索引越界——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 扰动,小数据集上把mosaic=1.0保持开启,能明显缓解过拟合。

4.4 现象:推理时框位置整体偏移

如果训练指标正常但推理框偏了,先确认推理时的imgsz和训练时一致。训练用 640 推理用 320,归一化尺度对不上,框就会缩水或偏移。另一个原因是图像在标注后被裁剪过,但标签没同步更新,这种只能重新标注或把该图剔除。用第 2 章那段画框脚本在训练前目检一遍,能提前拦住大部分坐标问题。

4.5 现象:显存溢出中断训练

batch 设太大或 imgsz 太高都会撑爆显存。8G 卡上 yolov8n 配 640 分辨率,batch 16 一般安全,换 yolov8m 就得降到 8 甚至 4。如果不想降 batch,可以开梯度累积模拟大 batch,或者用amp=True开启混合精度,显存占用能降三成左右。中断后想续训,加resume=True从 last.pt 接着跑,别从头再来。

5. 小数据集的进阶玩法:迁移学习、剪枝与格式互转

189 张图直接训一个三分类模型,mAP 能到 0.6 左右就算不错,想再往上走,得在迁移学习和数据扩充上做文章。我一般会先用 COCO 预训练的 yolov8s 做 backbone 冻结训练,前 20 轮只训检测头,让模型先适应军事目标的特征分布,再解冻全部层微调。冻结训练的命令是在 train 里加freeze=10,表示冻结前 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,还要在真实推理速度上测一遍,有时候参数少了但算子不友好,延迟反而没降。

从那以后我每次拿到新数据集,都强制先跑一遍配对检查和画框目检,再动训练脚本。这两步花不到十分钟,能省下后面几小时的排查。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询