ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

YOLO航空卫星图像数据集实战:1366张带标签的9类地表覆盖检测

YOLO航空卫星图像数据集实战:1366张带标签的9类地表覆盖检测 简介本资源为面向YOLO系列算法使用者的航空卫星图像目标检测数据集适用于遥感场景下的地物识别模型训练与验证覆盖森林、公路、作物、河流、住宅、工业、果园、牧场及贫瘠土地等九类典型目标适合具备一定深度学习基础、需要快速开展遥感检测实验的开发者与研究人员。压缩包共2000个文件包含1230个xml标注文件与770个txt标注文件分别对应VOC与YOLO两种标签格式并附有data.yaml配置文件可直接适配yolov5、yolov8、yolov9、yolov7、yolov10及yolo11等主流版本整体约60.51MB。目前已有42人学习下载。数据集已完成训练集与验证集划分标签坐标采用归一化中心点与宽高表示省去格式转换与清洗环节读者可据此直接复现遥感目标检测流程并在此基础上调整类别或扩充样本用于课程设计、科研实验或算法对比。1. 1366 张航空卫星图带标签这套 YOLO 数据集到底能落地什么拿到一个压缩包名字里写着「yolo算法-航空卫星图像数据集-1366张图像带标签-森林-公路-作物-河流-住宅-工业-果园-牧场-贫瘠的土地」第一反应不该是「图片挺多」而是「这 9 个类别到底能不能训出一个能用的模型」。航空卫星图像数据集和普通 COCO 那类地面拍摄数据完全是两回事目标尺度小、类间差异靠纹理和颜色、同一类在不同光照和季节下长得不像一家人。1366 张图像带标签说多不多说少也够跑通一次完整的 YOLO 训练闭环前提是你知道每一类大概多少张、标签是什么格式、类别是否均衡。这套数据覆盖森林、公路、作物、河流、住宅、工业、果园、牧场、贫瘠土地九类本质是一个土地利用/地表覆盖的检测任务。它适合三类人想入门遥感目标检测但找不到带标签数据的学生、要做区域规划或农业估产原型验证的工程师、以及手里有 RK3588 或 Atlas 这类边缘板子想试试遥感模型部署的开发者。不适合指望直接拿去生产的人——1366 张的体量训出来的模型泛化能力有限跨区域、跨季节大概率翻车。下面从数据拆包、格式转换、训练配置到避坑把这条路走一遍。2. 拆包先看标签9 类地表覆盖的标注格式与分布核查2.1 先搞清楚标签是 XML、TXT 还是 JSON遥感数据集最常见的坑就是标签格式和你想的不一样。压缩包解压后先别急着写训练脚本用几条命令把目录结构和标签文件类型摸清楚。常见做法是先看有没有annotations、labels、JPEGImages这类目录名再抽样打开一个标签文件。# 解压后先看顶层结构别直接扔进训练脚本 unzip yolo_satellite_1366.zip -d sat_data cd sat_data find . -maxdepth 2 -type d | head -30 # 统计标签文件后缀判断是 VOC XML 还是 YOLO TXT find . -name *.xml | wc -l find . -name *.txt | wc -l find . -name *.json | wc -l # 抽样看一个标签内容 find . -name *.txt | head -1 | xargs cat如果*.txt数量和图像数量接近且每行是class_id x_center y_center width height五个归一化数值那恭喜已经是 YOLO 格式省掉转换。如果是*.xml里面是 VOC 的bndbox绝对坐标就得转。逻辑说明find按后缀统计是最快的格式判断方式比一个个打开看靠谱。参数上-maxdepth 2防止目录太深刷屏head -30控制输出量。失败时看什么如果 txt 数量远少于图像数说明部分图片没标或标签在子目录里用find . -name *.txt | sed s|/[^/]*$|| | sort -u看标签集中在哪些目录。2.2 用脚本统计 9 类的实例数和图像数类别不均衡是遥感数据集的通病。森林、作物、贫瘠土地这种大面积地物标注框可能又大又少公路、河流这种线状地物框可能细长且数量多。先统计再决定要不要做重采样。import os from collections import Counter label_dir sat_data/labels class_names [forest, road, crop, river, residential, industrial, orchard, pasture, barren] cls_counter Counter() img_with_cls Counter() total_boxes 0 for fname in os.listdir(label_dir): if not fname.endswith(.txt): continue seen set() with open(os.path.join(label_dir, fname)) as f: for line in f: parts line.strip().split() if len(parts) 5: continue cid int(parts[0]) cls_counter[cid] 1 total_boxes 1 seen.add(cid) for c in seen: img_with_cls[c] 1 for i, name in enumerate(class_names): print(f{name:12s} boxes{cls_counter[i]:5d} images{img_with_cls[i]:5d}) print(total boxes:, total_boxes)逻辑说明cls_counter统计每个类别的框数img_with_cls统计包含该类别的图像数两个指标一起看才能判断是「框少」还是「图少」。参数上class_names的顺序必须和标签里的class_id严格对应错一位整个训练就废了。如果发现某一类框数为 0要么是类别名对不上要么这类在数据里根本没用这个 id。正常情况 1366 张图总框数在几千到一万多之间如果只有几百说明标注很稀疏训练时要把mosaic增强开大一点。3. 从 VOC 到 YOLO标签转换脚本与四个边界坑3.1 转换脚本要处理归一化和类别映射如果标签是 VOC XML转换的核心是把绝对坐标xmin,ymin,xmax,ymax变成归一化的中心点加宽高。这一步看着简单但边界处理不当会埋雷。import os import xml.etree.ElementTree as ET from PIL import Image xml_dir sat_data/annotations img_dir sat_data/images out_dir sat_data/labels_yolo os.makedirs(out_dir, exist_okTrue) class_map {forest: 0, road: 1, crop: 2, river: 3, residential: 4, industrial: 5, orchard: 6, pasture: 7, barren: 8} 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() img_name root.find(filename).text img_path os.path.join(img_dir, img_name) w, h Image.open(img_path).size lines [] for obj in root.findall(object): name obj.find(name).text.strip().lower() 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) # 边界裁剪防止越界导致归一化后超出 [0,1] xmin max(0, min(xmin, w)) xmax max(0, min(xmax, w)) ymin max(0, min(ymin, h)) ymax max(0, min(ymax, h)) if xmax - xmin 1 or ymax - ymin 1: 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_name os.path.splitext(xml_file)[0] .txt with open(os.path.join(out_dir, out_name), w) as f: f.write(\n.join(lines))逻辑说明先读图像真实尺寸再归一化不能假设所有图都是 640×640。class_map用lower()兜底防止 XML 里大小写不一致。边界裁剪那几行是血泪经验遥感标注经常有框超出图像边缘的情况不裁的话归一化后坐标大于 1训练时会被过滤或产生异常梯度。参数上:.6f保留六位小数足够YOLO 内部会再处理。如果转换后某些 txt 是空的说明该图所有目标类别都不在class_map里需要回头核对类别名。3.2 划分训练集验证集时别按图像随机切遥感图像有个特点同一区域的多张图高度相似。如果纯随机划分验证集里可能有和训练集几乎一样的图导致验证指标虚高实际部署时傻眼。常见做法是按地理位置或按大图切块分组划分。import os import random import shutil random.seed(42) img_dir sat_data/images lbl_dir sat_data/labels_yolo out_base sat_data/dataset # 假设文件名前缀代表不同区域按前缀分组 files [f for f in os.listdir(img_dir) if f.endswith((.jpg, .png, .tif))] groups {} for f in files: prefix f.split(_)[0] groups.setdefault(prefix, []).append(f) group_keys list(groups.keys()) random.shuffle(group_keys) split int(len(group_keys) * 0.8) train_groups group_keys[:split] val_groups group_keys[split:] for split_name, gkeys in [(train, train_groups), (val, val_groups)]: for sub in [images, labels]: os.makedirs(os.path.join(out_base, split_name, sub), exist_okTrue) for g in gkeys: for f in groups[g]: shutil.copy(os.path.join(img_dir, f), os.path.join(out_base, split_name, images, f)) lbl os.path.splitext(f)[0] .txt src_lbl os.path.join(lbl_dir, lbl) if os.path.exists(src_lbl): shutil.copy(src_lbl, os.path.join(out_base, split_name, labels, lbl))逻辑说明按文件名前缀分组保证同一区域的图要么全在训练集要么全在验证集。参数上random.seed(42)保证可复现0.8是常见比例数据量小时可以调到 0.85。如果文件名没有区域前缀退而求其次可以按图像尺寸或拍摄时间聚类分组。这一步做不好后面调参全是玄学。4. YOLOv8 训练配置从 data.yaml 到置信度门限4.1 data.yaml 的路径和类别顺序必须一次写对YOLOv8 用data.yaml描述数据集路径写错是最常见的翻车点。相对路径是相对于你执行训练的目录不是相对于 yaml 文件。# sat_data/dataset/data.yaml path: /absolute/path/to/sat_data/dataset train: train/images val: val/images names: 0: forest 1: road 2: crop 3: river 4: residential 5: industrial 6: orchard 7: pasture 8: barren逻辑说明path用绝对路径最稳train和val相对于path。names的 id 必须和标签里的 class_id 完全一致顺序错了模型学到的就是错的映射。参数上如果显存够可以把val也指向训练集做 sanity check确认能过拟合再换回真实验证集。失败时看什么训练启动报No labels found九成是路径问题用ls逐级确认。4.2 训练命令与关键参数怎么设遥感小目标多输入尺寸和增强策略要针对性调。下面是一条我常用的起步命令。yolo detect train \ datasat_data/dataset/data.yaml \ modelyolov8s.pt \ epochs150 \ imgsz1024 \ batch8 \ lr00.01 \ lrf0.01 \ mosaic1.0 \ scale0.5 \ degrees0.0 \ fliplr0.5 \ flipud0.5 \ patience30 \ projectruns/sat \ nameexp1逻辑说明imgsz1024是因为遥感目标小640 下很多地物只剩几个像素。batch8配合 1024 输入8G 显存差不多是上限显存小就降到 4 或改用yolov8n。mosaic1.0增强小目标效果明显但遥感图像拼接后可能出现不自然的边界可以试 0.5。flipud0.5是遥感特有的上下翻转对地物语义不变能有效扩增数据。degrees0.0是因为旋转会引入黑边遥感图像边缘信息也重要一般不转。patience30早停防止过拟合。参数怎么改如果验证集 mAP 一直上不去先把imgsz加到 1280 试如果训练 loss 震荡把lr0降到 0.005。4.3 推理时置信度门限和 NMS 的调整训练完导出模型后推理阶段的conf和iou直接决定误检率。遥感场景下河流和公路容易混住宅和工业容易混。yolo detect predict \ modelruns/sat/exp1/weights/best.pt \ sourcesat_data/test_images \ imgsz1024 \ conf0.35 \ iou0.5 \ saveTrue \ save_txtTrue逻辑说明conf0.35比默认 0.25 高是为了压掉遥感里大量低置信度的纹理误检。iou0.5控制 NMS 合并阈值线状地物密集时可以降到 0.4 防止漏检。参数上如果发现漏检多先把conf降到 0.2 看召回再逐步往上找平衡点。save_txtTrue导出结果方便后续做 GIS 后处理。失败时看什么如果某类几乎检不出回训练日志看那一类的instances数量太少就得补数据或调类别权重。5. 避坑与排查遥感 YOLO 训练里最容易翻车的 5 件事5.1 现象训练 mAP 很高换一片区域推理全乱原因验证集和训练集来自同一区域模型记住了背景纹理而不是目标特征。解决按区域分组划分数据集验证集必须来自不同地理区域。如果数据本身只覆盖一个区域那就要接受泛化有限的现实部署前用目标区域的无标签图做一轮人工抽检。5.2 现象河流和公路互相误检置信度都在 0.4 左右原因两者都是线状地物在低分辨率下纹理接近颜色也容易受光照影响。解决提高输入分辨率到 1280让宽度特征更明显或者在标签层面检查是否有标注不一致比如同一条路一半标 road 一半标 river。后处理上对这两类单独设更高的conf门限。5.3 现象训练到 50 epoch 后 loss 突然变 NaN原因学习率过高加上某些 batch 里框的宽高归一化后接近 0产生数值不稳定。解决把lr0从 0.01 降到 0.005并在转换脚本里过滤掉宽或高小于 2 像素的框。另外检查是否有标签坐标恰好等于 1.0 的边界情况归一化时除以图像尺寸可能产生浮点误差。5.4 现象小目标果园、工业设施召回率极低原因1024 输入下一个 20×20 像素的果园在特征图上只剩 2×2YOLO 的 P3 层也难捕捉。解决改用带 P2 检测头的模型结构或者把输入加到 1536。数据层面用 mosaic 和 copy-paste 增强小目标实例。如果还不行考虑把果园和工业合并成「人工地物」大类减少类间竞争。5.5 现象推理速度在边缘设备上只有个位数 FPS原因1024 输入加 yolov8s在 RK3588 这类板子上算力吃紧。解决导出 ONNX 后用 RKNN 或 TensorRT 量化到 INT8输入降到 640模型换 yolov8n。精度会掉几个点但速度能到 20 FPS 以上。量化时要用一批遥感图做校准集不能用 COCO 的图否则量化误差会集中在遥感特有的纹理上。6. 把 1366 张用到极致小数据集的增强与验证技巧1366 张图训九类平均每类不到 200 张这个体量下模型很容易过拟合。我一般会做两件事一是用无标签的遥感图做自监督预训练或者伪标签半监督二是把验证做扎实不只看 mAP。先说增强。除了 YOLO 自带的 mosaic、翻转、缩放遥感场景可以加颜色抖动因为不同季节植被颜色差异大。在data.yaml同级加一个augment.yaml或者在训练命令里加hsv_h0.015 hsv_s0.7 hsv_v0.4让模型对颜色不那么敏感。另外可以试 cutmix把两张图的区域拼接对土地利用分类这种任务拼接后的语义仍然合理。# 伪标签半监督的简化流程用训好的模型对无标签遥感图推理筛选高置信度结果加入训练 import subprocess # 第一步对无标签图推理导出 txt subprocess.run([ yolo, detect, predict, modelruns/sat/exp1/weights/best.pt, sourceunlabeled_imgs, imgsz1024, conf0.6, save_txtTrue, save_confTrue ]) # 第二步人工抽检或按置信度过滤后把 txt 和图像加入训练集 # 注意伪标签的类别 id 要和原数据集一致conf 门限建议 0.6 以上逻辑说明伪标签的关键是门限要高conf0.6以上才用否则错误标签会污染训练。参数上save_confTrue保留置信度方便后续按类过滤。这一步做完等效数据量能翻一到两倍但前提是初始模型已经有一定精度否则伪标签全是噪声。再说验证。遥感任务不能只看 mAP50要看 mAP50-95 和每一类的 AP。如果某一类 AP 特别低先看混淆矩阵确认是被哪一类吃掉了。YOLO 训练完会在runs/sat/exp1下生成confusion_matrix.png直接打开看。另外建议留出 20 到 30 张图做「压力测试集」专门挑光照差、有云、目标密集的图训练过程中定期用这个集推理看实际效果而不是只看验证指标。最后说一个我自己的习惯每次训完模型不管指标多好都会随机抽 10 张验证图把预测框画出来肉眼过一遍。有一次 mAP 0.78 的模型抽检发现把所有深色屋顶的住宅都标成了工业原因是训练集里工业样本太少模型靠颜色偷懒。这种问题指标看不出来只有看图才能发现。遥感数据集的坑大多在数据本身不在模型结构多花时间在标签核查和抽检上比盲目换模型有用。希望帮到你。本文还有配套的精品资源点击获取
返回列表