尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

遥感目标检测YOLOv5数据集:从标注格式到训练避坑全指南

发布时间:2026/9/24 18:05:11

资讯中心
01
ARTICLE

遥感目标检测YOLOv5数据集:从标注格式到训练避坑全指南

遥感目标检测YOLOv5数据集:从标注格式到训练避坑全指南
简介面向目标检测、遥感影像分析方向的开发者和学习者这份资源提供飞机、油罐、船只三类遥感目标的YOLOV5格式标注数据。数据目录按照YOLOV5组织划分训练集与验证集并附类别文本文件可配合遥感图像直接用于目标检测模型的训练与验证。包体方面压缩包共2000个文件其中1999个为txt格式标签文件1个为Python可视化脚本show.py整体大小约237.68MB7z压缩便于存储与传输。资源描述给出了训练/验证集规模训练集含2398张图片及对应标签验证集含1393张图片及对应标签便于评估数据覆盖度与划分比例。此外附带的可视化脚本无需修改即可运行能随机读取一张图像、绘制边界框并保存到当前目录极大降低了标注质量核查成本。目前已有215人学习下载适合需要快速获取遥感目标检测标注资源的项目团队与个人研究者。1. 遥感卫星图像目标检测一份能直接跑 YOLOv5 的数据集在卫星图上找飞机、油罐和船只和街景里检测行人完全不是一回事。目标在整张图里往往只占几十个像素背景是地形、云层、港口类别之间还会相互遮挡。我折腾遥感目标检测数据集时最耗时的反而不是模型调参而是数据整理标注格式五花八门标签要么没归一化要么目录层级对不上 YOLOv5。这份遥感卫星图像目标检测数据集就是冲着这个痛点来的——按 YOLOv5 目录格式存好train/val 共 3791 张 800×600 RGB 原图和对应 txt 标签3 个类别飞机、油罐、船只还附了一个 show.py 可视化脚本解压之后可以直接进训练流程。特别适合正在做遥感图像目标检测、或者第一次用 YOLOv5 训练自己的数据集的人。2. 数据集结构与标注格式先看懂 YOLOv5 目录再谈训练2.1 目录布局图片和标签的对应关系解压之后先别急着看训练命令把目录结构完整过一遍。这套数据集最省心的地方在于它已经按 YOLOv5 的目录约定排好了images 下分 train/val 存放原图labels 下分 train/val 存放同名 txt 标注classes.txt 在一级目录里show.py 也放在最外层。下面是一棵示意目录树图片扩展名以实际文件为准这里用 .jpg 展示。remote_satellite_dataset/ ├── classes.txt # 3 个类别名一行一个 ├── show.py # 可视化脚本直接运行 ├── images/ │ ├── train/ # 2398 张原图 │ │ ├── 07714.jpg │ │ ├── 07715.jpg │ │ └── ... │ └── val/ # 1393 张原图 │ ├── 08924.jpg │ └── ... └── labels/ ├── train/ # 2398 个 txt │ ├── 07714.txt │ ├── 07715.txt │ └── ... └── val/ # 1393 个 txt ├── 08924.txt └── ...train 和 val 下同名文件一一对应比如 images/train/07714.jpg 对应 labels/train/07714.txt后缀从图片扩展名换成 txt。YOLOv5 在训练时就是按“图片路径换成 labels 目录、扩展名换成 txt”这个规则去找标注所以目录结构一旦错位训练能启动但验证指标会全是 0这一点在第 5 章展开说。训练集 2398 张验证集 1393 张比例大约 6:4。遥感数据处理上验证集留大一点是合理的因为遥感图的背景复杂度太高val 占比太小会让 mAP 波动很大。图片分辨率统一是 800×600RGB 三通道压缩包解完 240MB 出头放在本机跑完全没压力。2.2 txt 标签格式归一化坐标怎么算回像素打开任意一个 txt每行 5 个数字用空格分隔。第一个是类别编号从 0 开始后面四个数字是归一化后的中心点 x、中心点 y、框宽 w、框高 h。三个类别分别是飞机、油罐、船只所以编号只会在 0、1、2 之间。下面是一行示例实际内容以数据集为准。0 0.532810 0.410122 0.025416 0.019203这一行的含义是类别 0飞机目标中心点在图像横向 53.28%、纵向 41.01% 的位置宽度占整图宽度 2.54%高度占整图高度 1.92%。把它换算回 800×600 像素中心点坐标大约是 (426, 246)框宽约 20 像素高约 11 像素——典型的遥感小目标。想验证自己的换算逻辑可以跑下面这段 Python。w_img, h_img 800, 600 with open(labels/train/07714.txt, r, encodingutf-8) as fp: for line in fp: parts line.strip().split() if len(parts) ! 5: print(格式异常:, line.strip()) continue cls, xc, yc, bw, bh int(parts[0]), float(parts[1]), float(parts[2]), float(parts[3]), float(parts[4]) x_pixel xc * w_img y_pixel yc * h_img box_w bw * w_img box_h bh * h_img print(f类别{cls}: 中心({x_pixel:.1f}, {y_pixel:.1f}) 宽{box_w:.1f} 高{box_h:.1f})这段代码把归一化坐标乘回图片宽高方便人工判断标注是否合理。我一般会再用它做一轮统计看每张图里目标的宽高分布如果绝大多数框宽高都在 10 到 60 像素之间说明这是一套典型的小目标数据训练参数就得往小目标方向调整如果扫出某个 w 超过 400 像素那大概率是标签混入了别的格式需要单独拎出来看。2.3 show.py 可视化脚本和运行方式光看 txt 数字不够直观把框画到图上才是最快的人工校验方式。这套数据集附带的 show.py 就是干这个的脚本不用改任何参数。把一张待检查的图片放到脚本同级目录然后直接运行。python show.py跑完之后当前目录会多出一张绘制好边界框的图片。脚本的作用是帮你确认标签和图像是否对得上框有没有贴在目标上、三类目标的颜色区分是否明显、有没有叠在一起的两个框。如果脚本支持指定图片路径常见做法是加--image参数比如python show.py --image images/val/08924.jpg具体参数名以源码为准先跑默认模式总没错。这里有个环境问题show.py 依赖 opencv-python如果直接运行报ModuleNotFoundError: No module named cv2先装依赖再跑。pip install opencv-python可视化和训练共用同一套 Python 环境时装 cv2 不会影响训练但注意别在 conda 的 YOLOv5 环境里覆盖 numpy 版本装完建议pip install -r requirements.txt把 YOLOv5 的依赖重新对齐一遍。如果画出来的框和目标位置有错位先怀疑对应 txt 文件本身而不是怪脚本这个顺序能帮你快速定位问题。3. 把数据集接进 YOLOv5 训练流程数据集 YAML 与三项校验3.1 写 dataset.yaml类别顺序决定训练结果YOLOv5 训练之前要有一个数据集配置文件通常叫 dataset.yaml。这个数据集已经是标准目录格式所以配置文件只需要写三个东西train 和 val 的图片路径、nc 类别数、names 类别名列表。下面是一个能直接用的例子。# remote_satellite.yaml train: ./datasets/images/train val: ./datasets/images/val nc: 3 names: 0: airplane 1: oil_tank 2: shiptrain 和 val 指向的是图片目录不是 labels 目录。YOLOv5 会自己把 images 替换成 labels 去找同名 txt所以路径写到图片这一层就够了。nc 必须等于 3names 里的顺序必须和 classes.txt 的行序一致。如果 classes.txt 里写的是中文名比如“飞机”“油罐”“船只”在 yaml 里最好用英文或拼音避免训练日志和画图时终端乱码。配置项示例值说明train./datasets/images/train训练图片目录自动关联同名标签val./datasets/images/val验证图片目录nc3类别总数必须和标签编号最大值一致namesairplane/oil_tank/ship顺序决定 0/1/2 的显示名类别顺序是这里最容易翻车的点。假设你的标签里 0 是飞机但 yaml 里 0 写成油罐训练不会报错loss 也能降最后画出来的框类别名全是错的。所以写 yaml 之前先打开 classes.txt 看一眼别凭记忆写。3.2 训练前校验一个脚本查数量、坐标和类别拿到数据集第一次用之前建议先跑一遍校验脚本把三个基础问题一次性查清楚图片和标签数量是否一致、标签坐标是否在合法范围、类别编号有没有越界。下面这个脚本直接放在数据集根目录跑即可。import os from collections import Counter split train # 改成 val 可以检查验证集 img_dir fdatasets/images/{split} lab_dir fdatasets/labels/{split} img_names {os.path.splitext(f)[0] for f in os.listdir(img_dir)} lab_names {os.path.splitext(f)[0] for f in os.listdir(lab_dir)} print(f图片数量: {len(img_names)}, 标签数量: {len(lab_names)}) print(缺标签的图片:, sorted(img_names - lab_names)[:10]) print(缺图片的标签:, sorted(lab_names - img_names)[:10]) cls_counter Counter() bad_lines [] for f in os.listdir(lab_dir): path os.path.join(lab_dir, f) with open(path, r, encodingutf-8) as fp: for line in fp: parts line.strip().split() if len(parts) ! 5: bad_lines.append((f, line.strip(), 列数不为5)) continue cls, xc, yc, bw, bh int(parts[0]), float(parts[1]), float(parts[2]), float(parts[3]), float(parts[4]) cls_counter[cls] 1 if not (0 xc 1 and 0 yc 1 and 0 bw 1 and 0 bh 1): bad_lines.append((f, line.strip(), 归一化坐标越界)) if xc - bw / 2 0 or xc bw / 2 1 or yc - bh / 2 0 or yc bh / 2 1: bad_lines.append((f, line.strip(), 框超出图像边界)) print(类别分布:, dict(sorted(cls_counter.items()))) if bad_lines: print(异常标签数量:, len(bad_lines)) for item in bad_lines[:10]: print(item) else: print(校验通过)这段脚本做三件事第一用文件名集合求差集找出缺标签或缺图片的文件隐藏文件比如 .DS_Store、.ipynb_checkpoints也会被揪出来第二统计类别编号分布如果出现 3、4 或者负值说明标签混入了别的数据源第三检查归一化坐标是否越界中心点必须在 0 到 1 之间宽高必须大于 0并且框不能超出图像边界。坐标越界的标签在训练时不会报错但会导致 loss 异常变大模型学出一堆无效框。建议把这个脚本存成 check_dataset.py 放在数据集根目录以后每次换机器、换环境、重新解压之后都跑一遍。整个过程不到一分钟但能省掉一整轮废训练。3.3 为什么这份数据集不用转格式YOLOv5/YOLOv8 通用很多遥感数据集公开出来是 VOC 的 XML 或者 COCO 的 JSON拿回来第一步就是要用标注工具或者写脚本转成 YOLOv5 目录格式这一步最容易在类别映射上出错。而这个数据集已经是 YOLOv5 目录格式可以跳过转换阶段省掉至少半天工作量。目标检测常用标注工具比如 LabelImg、Label Studio 导出的格式五花八门但最终落到 YOLO 系模型时格式收敛点基本都是这套目录规范。如果你已经在用 YOLOv8 而不是 YOLOv5这份数据集也能直接用。YOLOv8 训练自己的数据集时用的 data.yaml 结构和 YOLOv5 几乎一模一样同样是 images/train、images/val 加 labels 的结构把 YOLOv5 的 dataset.yaml 字段名微调一下就能跑。转换格式时最常见的坑是类别 id 错位VOC 的类别名到 YOLO 的编号往往要人工对一遍而这套数据已经帮你把这一步做完了。4. 训练与评估参数怎么定从 800×600 原图到小目标检测的取舍4.1 基线训练命令参数和显存预算把 yaml 放好、校验脚本跑完下一步就是训练。YOLOv5 训练入口是 train.py一套能直接起步的基线命令如下。python train.py \ --data remote_satellite.yaml \ --weights yolov5s.pt \ --img 640 \ --batch 16 \ --epochs 100 \ --patience 30 \ --name remote_satellite参数的含义--data指向上一步写的 yaml--weights用官方预训练权重做迁移学习--img是训练输入尺寸--batch和--epochs控制单轮样本量和迭代轮数--patience表示验证指标连续多少轮不提升就早停。图片本身是 800×600但 YOLOv5 的输入默认是正方形训练时会把原图做 letterbox 缩放并填充灰边所以--img 640意味着原图先被等比缩到 640 宽再补成 640×640。参数建议值说明--weightsyolov5s.pt显存 8G 也能跑追求精度换 yolov5m--img640 或 800800×600 会被 letterbox 成正方形输入--batch16 或 88G 显存建议 816G 以上可以 16--epochs100遥感小目标收敛偏慢100 轮比较稳--patience3030 轮没提升自动停省时间--nameremote_satellite输出目录名runs/remote_satellite 下4.2 小目标检测的三种调整路线img、切图、超参基线命令能跑通之后针对遥感小目标场景一般有三条调整路线按代价从低到高排。第一条是把训练尺寸从 640 提到 800 或 960因为原图是 800×600用 640 训练等于主动把目标缩小飞机本来就只有 20 像素再缩到 16 像素特征就快没了。命令只需要把--img 800batch 相应降到 8显存 8G 勉强能跑mAP50-95 通常会有明显提升。第二条是切图。如果目标在 800×600 里仍然太小常见做法是把大图切成若干 patch比如上下左右切成 4 张 400×300再对每张做目标检测相当于把每个目标放大两倍。切图有个硬性要求训练和推理必须用同一套切图策略否则推理时目标正好落在切图拼缝上会被切碎。对这份数据集来说我一般先试--img 800效果不够再上切图。提示切图必须训练和推理保持一致否则目标落在拼缝处会被切成两半。第三条是调 YOLOv5 超参。YOLOv5 自带几组超参文件比如 hyp.scratch-low.yaml 是官方默认的较低增强配置训练时用--hyp指定。遥感小目标场景下我一般会把 mosaic 和 copy_paste 的概率调高一些因为小目标需要更多上下文同时把 lr0 从 0.01 降到 0.005 左右防止 start 阶段梯度震荡。注意改超参要复制一份再改别动官方原文件。4.3 验证指标怎么读P、R、mAP50 和 mAP50-95训练结束后 YOLOv5 会打印一组指标对这组数据最需要注意的是不要只看 mAP50。P 是精确率R 是召回率mAP50 是 IoU 阈值 0.5 时的平均精度mAP50-95 是在 0.5 到 0.95 多个 IoU 阈值上的平均。对遥感小目标mAP50 很容易刷得好看但 mAP50-95 会低不少这是正常的。指标含义这套数据的参考区间Precision预测框里真目标的比例0.85 以上Recall真目标被召回的比例0.85 以上mAP50IoU 0.5 下的平均 AP0.88 以上mAP50-95多 IoU 阈值平均 AP0.55~0.75mAP50 高而 mAP50-95 低的本质是框的定位精度不够目标被找到了但边界框偏移了几个像素。对于 20 像素的小目标偏移 3 个像素在 IoU 0.5 时也许还能过到 IoU 0.75 时就被判为负样本。想提高 mAP50-95优先把--img提上去小幅目标放大的收益通常大过换更大模型的收益。另外要习惯用 val 集做调参决策如果把 val 当测试集反复跑几十次指标就会虚高最后换到真正没见过的数据上会打回原形。5. 避坑手册遥感图像目标检测训练中的 5 个常见翻车点5.1 类别编号越界现象训练到第二个 epoch 突然崩溃控制台报IndexError: index 3 is out of bounds for axis 0 with size 3。看到 size 3 基本可以判定 nc 是 3但某个标签里出现了编号 3 或更大的数字。原因数据集在采集或转换时混入了多余类别的标签通常来自别的数据源或者 classes.txt 的顺序被人动过导致编号整体错位。YOLOv5 在读取标签时不会主动校验编号范围等 loss 计算阶段按编号取类别名才会暴露问题而且报错位置和问题源头往往隔着好几个进程。解决不要停在报错信息本身直接用第 3 章的校验脚本统计类别分布。我一般会把 cls_counter 的打印结果和 classes.txt 逐行对照编号集合必须是 {0, 1, 2}而且每一类的数量都应该是几十上百这个量级。如果某个编号只有一两条大概率是误标直接删掉对应行或重新标注。改完标签后重新跑校验脚本要能通过再回去训练。5.2 训练正常但验证 AP 全是 0现象训练 loss 曲线正常下降每个 epoch 过完验证集输出 P、R、mAP 全部是 0日志里验证图片数量显示为 0。原因YOLOv5 找标签是按“图片目录同级的 labels 目录”这个隐式规则推导的。如果 images 和 labels 不在同一个上级目录或者 labels 目录是空的训练不会报错只是验证时没有任何 ground truth 可以匹配于是所有指标归零。解决确认目录结构必须满足 images/train 和 labels/train 同级。跑验证之前先手动数一遍 labels/val 下的文件数量再对照 3.2 的校验脚本输出。还有个隐蔽情况标签文件如果是从 Windows 复制到 Linux文件名大小写可能不一致比如图片叫 07714.jpg 而标签叫 07714.TXTYOLOv5 按 txt 后缀精确匹配这种情况下匹配数量也会归零。5.3 图片与标签数量对不上现象训练启动时 YOLOv5 打印train: 2398 images但标签目录数出来只有 2380 个或者在验证阶段卡住不动。原因通常是解压不完整或者系统在目录里生成了隐藏文件。macOS 的 .DS_Store、压缩包里的 __MACOSX 文件夹、还有 Jupyter 的 .ipynb_checkpoints都会被os.listdir数进去导致集合差集不为空。如果是在 Windows 上解压后再拷到 Linux还可能遇到大小写或短文件名的问题。解决用 3.2 脚本把差集文件名打出来人工看是图片多了还是标签多了。如果是隐藏文件混入删除后重跑如果真的是某个文件缺失直接重新解压对应子目录。不要在数量对不上的情况下强行训练YOLOv5 对缺失标签是直接跳过那张图等于训练数据悄悄变少而且你从日志里很难察觉。5.4 可视化画出的框位置不对现象show.py 输出的图片上有些框落在背景上框的宽高夸张地占满整张图或者明显超出图像边界被画到图外面。原因标签坐标没有按归一化格式写。如果某个 txt 里出现 x 或 w 大于 1说明这一行的坐标可能是像素值而非归一化值。像素坐标和归一化坐标混在一套数据里在实际数据集中不算罕见尤其是多人分头标注后合并的数据。解决先区分是单个文件异常还是整批异常。单个文件直接删掉或重新标注整批异常就得用脚本把所有坐标除以图片宽高重新写回 txt。判断依据很简单一行五个数里只要出现一个大于 1 的数就当成像素坐标处理。show.py 本身只是画框它不判断坐标是否合法所以这种问题只能靠校验脚本提前拦下来。5.5 小目标漏检严重现象验证结果里飞机、油罐这些小类别 mAP 很低船只稍好尤其 mAP50-95小目标的数值惨不忍睹。原因800×600 的原图缩放到 640×640 后飞机可能只剩十几个像素经过骨干网络下采样 32 倍后在特征图里不到一个像素检测头根本拿不到有效特征。这不是模型 bug是分辨率不够加目标太小的物理限制换大的预训练权重收益有限。解决第一优先级是把--img提到 800 或 960让输入分辨率尽量贴近原图第二优先级是在推理阶段用 tiling/SAHI 一类切图工具把小目标放大后再检测第三才是换更大的模型。注意切图方案必须和训练策略对齐我见过有人在训练时用整图、推理时用切图结果目标被切成两半漏检一半这个坑最隐蔽。6. 进阶技巧批量可视化抽检反向修正标注质量6.1 批量生成带框预览图show.py 适合单张抽查但人工一张张跑效率太低。更实用的做法是自己写一个批量可视化脚本把验证集前十几张图全部画上框输出到一个目录里几秒钟就能扫完。下面这个脚本不依赖 show.py直接读 images 和 labels 生成预览图。import os import cv2 names [airplane, oil_tank, ship] colors [(0, 255, 0), (0, 0, 255), (255, 0, 0)] img_dir, lab_dir datasets/images/val, datasets/labels/val out_dir, exts check_vis, (.jpg, .jpeg, .png) os.makedirs(out_dir, exist_okTrue) imgs [f for f in os.listdir(img_dir) if f.lower().endswith(exts)][:16] for img_name in imgs: stem, ext os.path.splitext(img_name) img cv2.imread(os.path.join(img_dir, img_name)) h, w img.shape[:2] lab_path os.path.join(lab_dir, stem .txt) if not os.path.exists(lab_path): print(跳过无标签图片:, img_name) continue with open(lab_path, r, encodingutf-8) as fp: for line in fp: parts line.strip().split() if len(parts) ! 5: continue cls, xc, yc, bw, bh int(parts[0]), float(parts[1]), float(parts[2]), float(parts[3]), float(parts[4]) if cls len(names): print(跳过越界类别:, img_name, cls) continue x1, y1 int((xc - bw / 2) * w), int((yc - bh / 2) * h) x2, y2 int((xc bw / 2) * w), int((yc bh / 2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), colors[cls], 2) cv2.putText(img, names[cls], (x1, max(0, y1 - 6)), cv2.FONT_HERSHEY_SIMPLEX, 0.5, colors[cls], 1) cv2.imwrite(os.path.join(out_dir, stem .jpg), img) print(已生成, stem .jpg)这段脚本把验证集前 16 张图各画上三类颜色的框输出到 check_vis 目录。跑完扫一眼框是否牢牢包住目标、有没有明显漏标、类别颜色是否和名称匹配。注意这里[:16]只取了前 16 个文件想全量检查就把列表切片去掉。6.2 抽检结果怎么辅助迭代数据抽检不是看完就完了发现的问题要落到数据修正上。如果某张图的标注框明显大了一圈把对应 txt 打开人工核对如果连续看到飞机被漏标说明这轮标注的容忍标准偏松回到标注阶段补标要比硬调模型参数有效得多。数据噪声在遥感场景里对训练的影响比大多数 CV 任务更大因为背景太复杂模型很容易学到背景特征去凑 loss。我自己在这类数据上栽过跟头拿到一套目录结构看起来没问题的数据集跳过了可视化抽检直接开训跑了两天发现验证集的标签路径是空的所有指标归零相当于两天白白浪费。从那以后我每次拿到 YOLOv5 目录格式的数据集都会强制先跑一遍数量和坐标校验再批量可视化抽检 20 张图确认框和类别都对得上才开训练。这套检查流程也就十几分钟但省掉的往往是一整轮废训练的时间。希望帮到你。本文还有配套的精品资源点击获取
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。