简介:YOLO卫星遥感多类别检测数据集提供1000张真实场景高清遥感图片,覆盖多样地物目标,使用LabelImg逐框标注,质量较高,适合作为目标检测入门与算法验证的数据基础。资源内已转换出VOC(xml)、COCO(json)、YOLO(txt)三种格式标签,分目录存放,可直接接入YOLOv5/YOLOv8等主流训练流程,省去自行格式转换的麻烦。压缩包共包含2000个文件,除标注数据外,还有Python划分脚本、YAML配置以及环境搭建与训练教程HTML文档,帮助使用者一键生成训练集、验证集和测试集,并快速完成Linux/Windows下的环境配置与自定义数据训练。整体包体约114.64MB,文件结构清晰,便于按需取用。目前已有635人学习下载,适合遥感图像处理学习者、算法开发人员以及需要高质量标注数据完成课程设计或项目实践的读者。配套教程与脚本能够有效降低YOLO系列模型的入门门槛,使数据准备、环境搭建、模型训练形成完整闭环。
1. 一套卫星遥感数据,把“能直接训练”这件事说透
搞目标检测的人多少都经历过这种痛苦:模型选好了,环境搭好了,结果卡在数据上。要么标注格式跟框架对不上,要么图片和标签对不齐,要么划分脚本写得像黑匣子。这份YOLO卫星遥感多类别检测数据集,罕见地在一份压缩包里把训练所需的几块拼图一次给齐了:1000张高质量遥感图片,同时带VOC、COCO、YOLO三种格式标签,各自独立成文件夹,外加三种划分脚本和配套训练教程。它不是让你自己去做标注、磨格式,而是把“标注好、分好类、能开训”这件事直接端到面前。适合做目标检测课程设计、毕设或遥感方向算法验证的从业者,也适合刚接触YOLO、想找一份靠谱数据跑通全流程的新手。
2. 三种标签格式的对应关系:从 XML 到 JSON 再到 TXT
2.1 一套标注三种格式:为什么数据集要做到“开箱即用”
遥感检测区别于普通街景目标检测的难点在于:目标尺度小、方向任意、背景复杂,单类别能跑通不代表多类别能稳定。这套数据集在标注阶段就做了三份标签,省去的是每个使用者都要重复做的格式转换。VOC 格式以 XML 文件存放目标框,核心是<bndbox>下的四个绝对像素坐标;COCO 格式以 JSON 组织数据,核心是images、annotations、categories三张表;YOLO 格式则是每个图片配一个同名 TXT,每行记录class_id x_center y_center width height,且四个数值都归一化到 0~1 区间。
三种格式要表达的是同一批框,只是组织方式不同。VOC 和 COCO 的坐标是绝对值,YOLO 是相对值;VOC 和 YOLO 的类别是数字编号,COCO 的类别有id和name双向映射。理解这个对应关系是后面所有操作的地基。
2.2 格式对齐校验:用脚本确认三份标签的一致性
拿到数据集后第一件事,不是急着开训,而是先验证三份标签是否严格对齐。我一般会写一个快速校验脚本,随机抽几十张图,把 YOLO 的 TXT 转成 VOC 的 XML 格式,再跟原 XML 做坐标误差对比。
import os import numpy as np import xml.etree.ElementTree as ET def yolo_txt_to_boxes(txt_path, img_w, img_h): boxes = [] with open(txt_path, 'r') as f: for line in f.readlines(): cls_id, cx, cy, w, h = map(float, line.strip().split()) # 反归一化:把相对坐标还原成绝对像素坐标 x1 = (cx - w / 2) * img_w y1 = (cy - h / 2) * img_h x2 = (cx + w / 2) * img_w y2 = (cy + h / 2) * img_h boxes.append((int(cls_id), x1, y1, x2, y2)) return boxes def voc_xml_to_boxes(xml_path): boxes = [] tree = ET.parse(xml_path) root = tree.getroot() for obj in root.iter('object'): cls_name = obj.find('name').text bnd = obj.find('bndbox') # VOC 的 bndbox 是整数像素坐标,YOLO 转出来是浮点,要做容差对比 x1 = float(bnd.find('xmin').text) y1 = float(bnd.find('ymin').text) x2 = float(bnd.find('xmax').text) y2 = float(bnd.find('ymax').text) boxes.append((cls_name, x1, y1, x2, y2)) return boxes # 示例:读一张 512x512 的遥感图对应的两份标签 img_w, img_h = 512, 512 yolo_file = 'labels/001.txt' voc_file = 'Annotations/001.xml' yolo_boxes = yolo_txt_to_boxes(yolo_file, img_w, img_h) voc_boxes = voc_xml_to_boxes(voc_file) print(f'YOLO 框数: {len(yolo_boxes)}, VOC 框数: {len(voc_boxes)}')这段脚本的逻辑很直接:YOLO 归一化坐标乘以图片宽高还原成像素坐标,VOC 从 XML 里直接读绝对坐标,然后逐框比对。参数上要注意两点:一是img_w、img_h必须和实际图片分辨率一致,遥感图经常出现 1024x1024 或 640x640 的输入,如果图片有 EXIF 旋转信息,读出来尺寸可能和实际不符;二是对比时建议留 2~3 像素误差容限,因为 YOLO 归一化再反算会引入浮点精度损失,lableimg 标注的整数框和换算结果天然有细微差别。跑完这个校验,三份标签的一致性心里就有底了。
2.3 COCO JSON 的依赖关系:先建categories再建annotations
COCO 格式看似复杂,但拆开就三条线:images表记录每张图的id、file_name、width、height;categories表定义每个类别的id和name;annotations表则是每条框记录,通过image_id关联到具体图片。训练时框架会先读categories建立类别索引,再遍历annotations取框的bbox字段,这个字段是[x, y, width, height]的绝对坐标数组,顺序和 VOC 的xmin ymin xmax ymax不一样,是xmin ymin w h。
校验这个文件最容易踩的坑是category_id从 1 开始还是从 0 开始,以及annotations里是否出现image_id在images表中找不到的情况。我借这个数据集做老师分配的任务时,都是先用 json 库把categories打印出来,确认类别顺序,再统计annotations数量跟 VOC 标签里的<object>总数是否相等。三份标签数量完全一致,才有资格说“可以直接用于训练”。
3. 划分脚本与 train_list.txt:从原始数据到可训练目录
3.1 三个划分脚本到底有什么区别
压缩包里附带三个划分脚本:一个做“训练集 + 验证集 + 测试集”三划分,一个做“训练集 + 验证集”两划分,还有一个是split_train_val生成ImageSets下 TXT 文件的脚本。初学者很容易把这三个当成同一种东西,实际上分工完全不同。
两划分脚本服务于“只要训练完看个效果”的快速验证场景;三划分脚本服务于“训完要交测试报告”的课程设计或项目交付场景,因为最终测试分数必须来自模型没见过的图片;ImageSets脚本是为老版本 YOLOv3/YOLOv4 服务的,那代框架要求先把图片名写进train.txt、val.txt,再由训练代码按 TXT 列表去读图。现在的 YOLOv5/v8 系列只需要data.yaml里指向train和val两个文件夹,所以三划分脚本反而更常用。
3.2 用脚本做划分:核心是“移动还是复制”和“随机种子”
import os import random import shutil def split_dataset(image_dir, label_dir, output_dir, train_ratio=0.7, val_ratio=0.2, seed=42): """ 按比例划分图片和对应标签到新目录 - train_ratio: 训练集比例 - val_ratio: 验证集比例,测试集 = 1 - train_ratio - val_ratio - seed: 随机种子固定,保证每次划分结果一致 """ random.seed(seed) all_images = [f for f in os.listdir(image_dir) if f.lower().endswith(('.jpg', '.jpeg', '.png'))] random.shuffle(all_images) train_cnt = int(len(all_images) * train_ratio) val_cnt = int(len(all_images) * val_ratio) train_files = all_images[:train_cnt] val_files = all_images[train_cnt:train_cnt + val_cnt] test_files = all_images[train_cnt + val_cnt:] for split_name, file_list in zip(['train', 'val', 'test'], [train_files, val_files, test_files]): split_img_dir = os.path.join(output_dir, split_name, 'images') split_label_dir = os.path.join(output_dir, split_name, 'labels') os.makedirs(split_img_dir, exist_ok=True) os.makedirs(split_label_dir, exist_ok=True) for img_name in file_list: # 图片和标签只共文件名不同扩展名,复制而非移动,避免误操作毁掉原目录 shutil.copy(os.path.join(image_dir, img_name), split_img_dir) label_name = os.path.splitext(img_name)[0] + '.txt' if os.path.exists(os.path.join(label_dir, label_name)): shutil.copy(os.path.join(label_dir, label_name), split_label_dir) print(f'划分完成: train={len(train_files)}, val={len(val_files)}, test={len(test_files)}') split_dataset('images', 'labels', 'dataset_split', train_ratio=0.7, val_ratio=0.2)这段脚本用random.shuffle打乱图片列表,再按比例切三段。注意几个细节:第一,固定seed,否则每次运行划分结果都不同,训练日志就对不上了;第二,用shutil.copy不用shutil.move,保留原始数据等于留了后悔药,划分错了随时可以重跑;第三,os.path.splitext(img_name)[0] + '.txt'是标准的同名标签匹配方式,遥感数据集偶尔会把标签放在labels目录后,如果图片名带特殊字符,这个匹配逻辑也要跟着调。
3.3 train_list.txt 在训练里的角色
train_list.txt是这套资源里的附加文件,通常逐行列出训练用的图片相对路径。YOLOv5/v8 默认不读这个文件,它更多是给早期 YOLO 版本或自己写的训练脚本用的。如果教程文档里明确要求使用它,常见做法是手动改成一个data.yaml:
# dataset.yaml 示例:在根目录新建这个文件 train: dataset_split/train/images val: dataset_split/val/images nc: 6 names: ['aircraft', 'ship', 'storage_tank', 'vehicle', 'harbor', 'bridge']需要注意nc必须跟标签里最大的class_id + 1一致,names的顺序也必须跟 lableimg 标注时定义的类别顺序一致。否则训练能跑,但 mAP 计算结果会把类别错位——其实训练时损失函数不报错,真正翻车的是最后画混淆矩阵的时候。这个顺序问题在第 5 章单独讲,这里先记住一点:YOLO 不校验类别名,只认编号。
4. 环境搭好、数据路径配对:把训练教程吃到嘴里
4.1 Linux 路线:Ubuntu 环境安装与 CUDA 驱动版本匹配
这套资源付了两个 HTML 教程,一个 Linux 一个 Windows,Windows 里还专门拆了一篇 Ubuntu 环境安装教程。搭 YOLO 环境最容易翻车的就是 Ubuntu 显卡驱动和 CUDA 版本对不上。先跑一遍nvidia-smi看驱动支持的最高 CUDA 版本,再决定装 PyTorch 的 CUDA 版本。
# 1. 查看 GPU 驱动和系统显存 nvidia-smi # 2. 用 conda 建一个干净环境,Python 3.10 兼容性最好 conda create -n yolo python=3.10 -y conda activate yolo # 3. 安装对应 CUDA 版本的 PyTorch,这里以 cu121 为例 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu121 # 4. 克隆 YOLOv5 仓库并安装依赖 git clone https://github.com/ultralytics/yolov5 cd yolov5 pip install -r requirements.txt参数说明:cu121指 CUDA 12.1,需要驱动版本在 525 以上;如果nvidia-smi显示驱动支持最高 12.0,就得换cu118版本。装完跑python -c "import torch; print(torch.cuda.is_available())",输出True才算环境通。Linux 版本教程里多半是这套流程,核心就是先驱动后 CUDA 再 PyTorch,顺序反了会浪费大量时间排查 import 报错。
4.2 Windows 路线:conda 是最省事的依赖隔离方式
Windows 上最麻烦的是路径分隔符和 OpenCV 的 DLL 冲突。不要直接在全局 Python 里装,强制建 conda env,否则某天装了个新包把 OpenCV 版本顶掉,训练时读图就静默失败。Windows 版教程里给出的流程通常是:
# PowerShell 或 Anaconda Prompt 里执行 conda create -n yolo python=3.9 -y conda activate yolo pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 git clone https://github.com/ultralytics/yolov5 cd yolov5 pip install -r requirements.txt这里把 Python 版本换成 3.9 的原因是 Windows 上部分依赖对 3.10 的支持不够稳。注意git clone时不要选带中文或空格的路径,YOLO 的Path模块在 Windows 上遇到中文路径会出诡异问题,表现是图片找得到但权重保存失败。
4.3 数据集 YAML 修改:路径、类别数、类别名逐项核对
假设已经按第 3 章脚本划分出dataset_split/train和dataset_split/val,接下来把数据集的 YAML 文件指到这两个目录。VOC 和 COCO 标签在这个环节用不上,YOLO 训练直接读 TXT。常见做法是新建remote_sensing.yaml:
# 路径以项目根目录为基准,用相对路径避免迁移后失效 train: dataset_split/train/images val: dataset_split/val/images nc: 6 names: ['aircraft', 'ship', 'storage_tank', 'vehicle', 'harbor', 'bridge']修改后启动训练:
python train.py --data remote_sensing.yaml --weights yolov5s.pt --img 640 --batch 16 --epochs 100 --name remote_v1--img 640是训练分辨率,遥感小目标建议直接上 1024 或 1280,代价是显存占用增大;--weights yolov5s.pt用预训练模型做迁移学习,比从零训收敛快得多,代价是如果新数据集类别和 COCO 差异大,前几轮损失会震荡。
4.4 训练日志里怎么看“真收敛了”
训练不是跑完就算完。重点盯三个指标:box_loss应该持续下降,obj_loss是目标置信度损失,如果降不下去说明有小目标漏检;mAP@0.5在第一个 epoch 之后从 0 开始爬升是正常的,如果 20 个 epoch 后还在 0 附近,基本可以断定标签有误或类别配置错误。Windows 和 Linux 的教程 HTML 里一般都有对应的日志解读段落,配合这份数据的预期类别来看,前几个 epoch 的 mAP 冲到 0.3 以上说明数据质量没问题。
5. 避坑排查:标注、划分与训练阶段的五个翻车现场
5.1 训练时提示 “No labels found in ...”
- 现象:启动训练后几乎立即警告,找不到标签文件的路径。
- 原因:YOLO 期望图片和标签分别在
images和labels目录下,且两者目录结构保持对应。划分脚本如果只把图片复制了,标签文件夹没建全,就会触发这个警告。 - 解决:回到
split_dataset脚本,确认split_label_dir确实创建了并写入了文件。常见做法是打印每个划分目录下的文件计数,确认图片数和标签数相等后再开训。
5.2 某些图片训练时显示 “corrupt JPEG”
- 现象:训练中断,提示 OpenCV 无法解码某张 JPEG。
- 原因:遥感图片可能有特殊色彩空间或压缩参数,lableimg 能打开不代表 OpenCV 能解码;偶发性的截断文件也会这样。
- 解决:不要只删掉这张图,会连带标签一起失配。常见做法是把整批图用
cv2.imdecode重编码一遍,统一转成标准 JPEG 或 PNG 再训练。
5.3 mAP 异常低但损失是正常下降的
- 现象:损失在降,验证集的 mAP 却一直贴着 0。
- 原因:典型的数据集划分翻车——验证集和训练集来自同一场景的不同截图,模型学到的几乎是无意义的场景记忆而非类别特征;另一种情况是标签类别编号和
data.yaml里names顺序不一致,VOC 格式第 0 号类对应vehicle,YOLO 的 TXT 里第 0 号对应ship,模型从第一轮就学错了语义。 - 解决:固定随机种子重新划分,确保验证集和训练集在空间上分离;写一个脚本读取 TXT 标签和
names列表,逐类别统计框数量,人工核对语义。
5.4 显存不足,batch size 调小后精度暴跌
- 现象:
CUDA out of memory,强行把--batch从 16 降到 4 后,损失曲线剧烈震荡。 - 原因:batch 太小导致 BN 层统计量不稳定。遥感大图用 640 分辨率输入时,batch 4 确实容易崩。
- 解决:不要直接降 batch,优先降
--img到 512;如果坚持大图训练,尝试开启梯度累积。常见做法是把 batch 保持 16、img=512训练 100 个 epoch,再用--img 1024微调 20 个 epoch,效果往往比一口吃成大图更好。
5.5 标签框越界:归一化坐标出现大于 1 或小于 0
- 现象:训练时
assert报错,提示cx或w超出 [0,1] 区间。 - 原因:使用 lableimg 标注时,物体边缘贴图边界很容易把框画到图片外,导出的 XML 是绝对坐标没问题的,但转成 YOLO 归一化坐标后会出现负值或超 1 的值。
- 解决:在预处理阶段加一个裁剪脚本,把所有归一化坐标强制裁剪到 [0,1] 内,同时剔除面积小于一定阈值的框。这类清洗是一次性的,做一次后面所有训练都受益。
6. 进阶技巧:把 1000 张图的价值用到极限
6.1 用小模型先跑 baseline,再决定要不要上高分模型
第一次训练建议直接用 YOLOv5s,而不是一上来就调大模型。s 模型训练一轮的时间大概是 l 模型的三分之一,足够把数据问题、标签问题全部暴露出来。等 s 模型在mAP@0.5上到一个稳定值后,再用这个结果做确认:如果 mAP 在 0.5 以下,先怀疑数据问题,而不是模型容量不够。
6.2 难例挖掘:用训练好的模型给未标注图片打粗标签
1000 张图训出的模型大概率在航拍密集场景下会有漏检,把这些漏检挑出来人工补标,是扩大数据集最节约时间的做法。流程是:用训练好的权重遍历原始大图,保存置信度在 0.1 到 0.5 之间的检测框,转为 VOC 格式导入 lableimg 做人工修正。这个过程一般能找回 25% 左右的漏检框,尤其是小目标。
6.3 用统计脚本量化数据集的“难”在哪
import os import numpy as np def analyze_bbox_size(txt_dir): all_areas = [] all_wh = [] for f in os.listdir(txt_dir): with open(os.path.join(txt_dir, f), 'r') as fh: for line in fh.readlines(): _, cx, cy, w, h = map(float, line.strip().split()) # 归一化面积乘以输入分辨率,得到实际像素面积 all_areas.append(w * h) all_wh.append((w, h)) all_areas = np.array(all_areas) print(f'框总数: {len(all_areas)}, 中位面积: {np.median(all_areas):.4f}') print(f'面积小于 0.01 的框占比: {(all_areas < 0.01).mean() * 100:.1f}%') analyze_bbox_size('labels/train')这个统计直接关系到训练策略:小框占比高的时候,把--img调到 1280 的收益远大于调大模型;中位面积如果集中在 0.02 以下,就需要考虑用 SAHI 或切图训练这类专门方案。从那以后,我每次拿到新数据集都强制先跑一遍这个统计脚本再进训练循环,省掉过无数轮“损失很漂亮但漏检一片”的无效训练。这套数据连同划分脚本和教程文档,把这些步骤全部预置好了,剩下的就是你自己的实验设计了。希望帮到你。
本文还有配套的精品资源,点击获取