简介:压缩包提供了一套面向目标检测的高分卫星图像数据集及其已标注文件,主要服务于计算机视觉方向的学生、研究者和工程师,用来省去遥感数据采集与手工框选目标的重复劳动。数据集源于专业遥感影像,标注了飞机、轮船、储罐、棒球场、网球场、篮球场、地面跑道、港口、桥梁和车辆共10类目标,每张原图都配有标准标注文件,格式与YOLO等主流检测模型兼容,可直接用于训练和验证。整个压缩包共两千六百一十二个文件,以六百五十张原始图像、六百五十个标注文件、一千三百零七个文本说明文件为主体,另附少量缓存文件和说明文档,总体积约六十一兆字节,目录组织清晰,方便按需提取。目前已有三百二十一人学习使用,尤其适合计算机、电子信息、数学等专业学生开展课程设计、期末大作业或毕业设计,也能作为遥感目标检测研究的起步数据。通过这套数据,用户可以立即开始模型训练与效果评估,把时间留给算法调试和结果优化,避免从零准备数据集的漫长周期。
1. 卫星图像目标检测,为什么一份“已标注”的数据集价值比模型还大
做卫星图像目标检测的工程师几乎都经历过同一个尴尬阶段:模型结构选好了,YOLOv8的权重也加载了,结果打开遥感影像一看,一张4096×4096的图里飞机只有几十个像素,船和港口混在一起,停车场里的车密密麻麻。这时你会意识到,真正卡住进度的不是算法,而是数据——尤其是带高质量标注的卫星图像数据。标题里这份“800张图像+对应已标注文件”的rar包,解决的就是这个痛点:不需要自己用LabelImg或CVAT从零画框,解压后就能直接进YOLO训练流程。它适合两类人:一类是刚接触遥感目标检测、想快速跑通YOLO全流程的开发者;另一类是已经有检测经验、但缺少特定场景数据来做迁移学习或算法验证的从业者。后面我会按实际使用顺序,从标注格式、目录组织、训练参数到小目标优化,把这套数据从解压到出模型的全链路讲清楚。
2. 解压后先别急着训练:搞清标注格式和数据组织
2.1 数据集目录结构怎么看
拿到rar包,常见做法是先解压并保持原始目录层级,不要自行调整文件名。卫星图像数据集通常有两种组织方式:一种是images/和labels/平级,另一种是每个样本单独一个子目录。建议先执行tree命令看结构。
unzip yolov8_satellite_dataset.rar -d ./satellite cd ./satellite tree -L 2如果输出类似这样:
satellite/ ├── images/ │ ├── 001.jpg │ ├── 002.jpg │ └── ... ├── labels/ │ ├── 001.txt │ ├── 002.txt │ └── ... ├── classes.txt └── data.yaml说明这已经是YOLO友好结构。若没有data.yaml,你需要自己写;若有,也要检查里面的路径是否与你当前环境匹配。
2.2 标注文件里每一行代表什么
YOLO格式的txt标注文件,每行对应一个目标框,格式为class_id x_center y_center width height。注意这四项坐标都是归一化的,即除以图像宽高后的比例值,取值范围0到1。打开一个标注文件确认:
head -n 3 labels/001.txt假设输出:
0 0.5234375 0.482421875 0.0234375 0.01953125 1 0.7109375 0.28125 0.03125 0.028125第一列是类别ID,第二列是框中心点x坐标比例,第三列是中心点y坐标比例,第四列是框宽比例,第五列是框高比例。这里0对应classes.txt里的第一个类别,通常是airplane或ship。要特别注意:如果类别ID大于classes.txt中类别总数减1,训练时会直接报错,后面我会细说。
2.3 用脚本验证标注是否与图像匹配
“已标注”不代表万无一失,常见问题包括:图像被旋转过但标注没有同步变换、txt文件多行空行、坐标超出0到1范围。写一个Python脚本快速校验:
import os from PIL import Image image_dir = 'satellite/images' label_dir = 'satellite/labels' for label_name in os.listdir(label_dir): if not label_name.endswith('.txt'): continue image_name = label_name.replace('.txt', '.jpg') image_path = os.path.join(image_dir, image_name) label_path = os.path.join(label_dir, label_name) if not os.path.exists(image_path): print(f'警告: 图像 {image_path} 不存在') continue with Image.open(image_path) as img: w, h = img.size with open(label_path, 'r') as f: lines = [line.strip() for line in f if line.strip()] for i, line in enumerate(lines): parts = line.split() if len(parts) != 5: print(f'{label_name} 第{i+1}行格式错误: {line}') continue cls, xc, yc, bw, bh = parts xc, yc, bw, bh = float(xc), float(yc), float(bw), float(bh) if not (0 <= xc <= 1 and 0 <= yc <= 1): print(f'{label_name} 第{i+1}行中心点归一化超限: {line}') if bw <= 0 or bh <= 0: print(f'{label_name} 第{i+1}行宽高非正数: {line}')这段代码遍历每个txt,检查同名图像是否存在,并验证坐标是否在合理区间。宽高非正数在YOLO中会导致损失计算得到NaN,训练loss曲线会异常,所以这一步能省很多排错时间。
2.4 为什么不能直接拿原始遥感图跑YOLO
800张卫星图看起来不少,但每张可能都是几千像素宽的大图。如果直接把原图resize到640×640,小目标会缩小到3×3像素,YOLO的骨干网络下采样32倍后,特征图上一个点对应的感受野根本覆盖不到这么小的目标。这就是为什么很多新人在这个数据集上直接训练,mAP只有0.1甚至更差。正确做法是切图:把大图切成小块(如512×512或896×896),再按YOLO格式生成标注。有些数据集作者已经帮你切好,如果这个rar里的图像尺寸不大(比如已经切成1024以下),那可以跳过这一步;如果还是原始大图,需要自己写切图脚本。
3. 配好YOLO环境,把数据集转成训练需要的配置
3.1 创建data.yaml并正确设置路径
无论你用Ultralytics YOLOv8还是YOLOv5,都需要一个数据集描述文件。假设你解压后没有现成data.yaml,手动创建:
# satellite/data.yaml train: ./satellite/images/train val: ./satellite/images/val test: ./satellite/images/test nc: 2 # 类别数量,按实际修改 names: ['airplane', 'ship'] # 与classes.txt保持一致这里train和val设置的是图像文件夹路径,YOLO会自动在同级目录下找到labels文件夹中的标注。路径建议使用绝对路径或相对当前工作目录的路径,避免训练时找不到数据。nc必须和names列表长度一致,否则会报错。
3.2 如果只有images和labels平级,没有train/val划分怎么办
很多数据集压缩包只给了全部图像和标注,需要你自己划分。用脚本按8:1:1的比例切分:
python - <<'EOF' import os, random, shutil random.seed(42) image_dir = 'satellite/images' label_dir = 'satellite/labels' split_ratio = (0.8, 0.1, 0.1) images = [f for f in os.listdir(image_dir) if f.endswith(('.jpg', '.png'))] random.shuffle(images) n_train = int(len(images) * split_ratio[0]) n_val = int(len(images) * split_ratio[1]) for split, subset in zip(['train', 'val', 'test'], [images[:n_train], images[n_train:n_train+n_val], images[n_train+n_val:]]): os.makedirs(f'satellite/images/{split}', exist_ok=True) os.makedirs(f'satellite/labels/{split}', exist_ok=True) for img_name in subset: base = os.path.splitext(img_name)[0] shutil.copy(os.path.join(image_dir, img_name), f'satellite/images/{split}/{img_name}') label_file = base + '.txt' if os.path.exists(os.path.join(label_dir, label_file)): shutil.copy(os.path.join(label_dir, label_file), f'satellite/labels/{split}/{label_file}') else: print(f'警告: {img_name} 没有对应标注文件,已丢弃') EOF注意这段逻辑里我用了random.seed(42)保证每次运行划分一致,方便复现。切分后原images和labels目录可以留着,但data.yaml里的路径需要改为satellite/images/train这样的新路径。
3.3 从标注文件反推类别分布
训练前查看类别分布很有必要,若800张图里飞机占了90%,另一个类别只有几十个框,模型会严重偏向多数类。统计脚本:
import os from collections import Counter label_dir = 'satellite/labels' counter = Counter() for label_name in os.listdir(label_dir): with open(os.path.join(label_dir, label_name), 'r') as f: for line in f: if line.strip(): cls_id = int(line.split()[0]) counter[cls_id] += 1 print('类别统计:', dict(counter)) total_boxes = sum(counter.values()) print('总目标框数:', total_boxes) print('平均每张图目标数:', round(total_boxes / len(os.listdir(label_dir)), 2))如果发现类别极不均衡,后面训练时要调整class_weights或者采用oversampling。另外,平均每张图目标数很有参考价值——如果是3以下,说明图像内容稀疏;如果是50以上,可能是高密度场景,YOLO默认的NMS后处理可能不够用。
3.4 安装Ultralytics并验证环境
建议使用ultralytics库,它统一了训练、验证和导出接口。创建一个虚拟环境避免污染系统Python:
python -m venv yolo_env source yolo_env/bin/activate pip install ultralytics安装完成后快速验证环境是否能正常读取数据集:
from ultralytics import YOLO model = YOLO('yolov8n.pt') # 下载预训练权重 model.val(data='satellite/data.yaml', split='val', imgsz=640, verbose=False)这一步会输出验证指标。如果提示找不到图片或标签,说明data.yaml里的路径有问题,或labels目录结构不对。注意验证时YOLO会默认将图像resize到imgsz,这里先用640看能不能跑通,后面做推理优化再改。
4. 训练自己的检测模型:从预训练权重到微调
4.1 训练命令与关键参数含义
用预训练权重做迁移学习,能大幅缩短收敛时间。卫星图像虽然与COCO场景差异大,但低层特征(边缘、纹理、形状)仍然通用。训练命令:
yolo train \ model=yolov8s.pt \ data=satellite/data.yaml \ epochs=100 \ imgsz=640 \ batch=16 \ device=0 \ patience=15 \ project=runs/satellite \ name=exp1 \ optimizer=AdamW \ lr0=0.001参数说明:
model=yolov8s.pt:使用small版本的预训练权重。数据量只有800张,不适合直接训练yolov8x,容易过拟合;yolov8s是平衡速度和精度的选择。imgsz=640:训练时把图像resize到640×640。若你的标注框平均像素宽度小于10,建议调大到896,代价是显存占用上升。patience=15:验证集mAP连续15轮不提升则早停。数据量小,训练后期容易震荡,早停能防止过拟合保存最优权重。lr0=0.001:迁移学习时初始学习率建议在0.0005到0.002之间。默认0.01是针对从头训练COCO,放在小数据集上很容易发散。device=0:指定GPU编号。没有GPU时改成device=cpu,但训练速度会慢一个数量级。
4.2 训练日志里真正需要看的三个指标
训练启动后,每轮会输出P(精确率)、R(召回率)、mAP50、mAP50-95。对小目标数据集,重点关注R和mAP50,因为卫星图像中目标小,漏检比误检更常见。mAP50-95是IoU从0.5到0.95取平均,对框位置精度要求极高,小目标框稍微偏一点IoU就掉下去,所以这个指标通常不太好看,不必死磕。
当训练结束时,在runs/satellite/exp1/下会生成weights/best.pt和weights/last.pt。建议用best.pt做推理,因为它是早停时的最优模型。
4.3 数据量只有800张,怎么防止过拟合
800张卫星图像对于检测任务来说偏少,特别是场景多样性有限。常见做法组合使用:
yolo train \ model=runs/satellite/exp1/weights/best.pt \ data=satellite/data.yaml \ epochs=60 \ imgsz=640 \ batch=16 \ device=0 \ patience=10 \ project=runs/satellite \ name=exp2_finetune \ lr0=0.0005 \ mosaic=0.5 \ mixup=0.2 \ fliplr=0.5 \ hsv_h=0.015 \ hsv_s=0.7这里在原有基础上调低了学习率,并增强了数据增强参数。mosaic=0.5代表50%的概率使用四张图拼接,能增加场景混合度;mixup=0.2是两张图按比例融合。但要注意,卫星图像的朝向具有特殊语义(比如道路和建筑的方向),fliplr可以开,rotate不建议随意开,否则模型会把横着的船和竖着的船混淆。
4.4 训练中显存溢出怎么办
batch大小和imgsz是显存的主要影响因素。如果报CUDA out of memory,不要直接降batch到1,梯度更新噪声会非常大。正确做法是降低imgsz到512,或者开启梯度累积。Ultralytics没有直接暴露梯度累积参数,但可以通过增大batch到64同时用device=0加两个卡做分布式训练(device=0,1)。单卡情况下,建议按顺序尝试:
- 将
batch减半,观察显存占用 - 如果还溢出,将
imgsz从640降到512 - 最后再考虑用更小的模型如
yolov8n.pt
同时在训练时加上workers=4(Windows下建议workers=0),否则数据加载会成为瓶颈。
5. 小目标推理与精度验证,把800张数据用到极致
训练完成后,直接拿原图推理往往会发现小目标漏检严重。一个非常有效的技巧是使用切片推理(SAHI:Slicing Aided Hyper Inference)。它的核心是:推理时不把整张大图resize到640,而是先切成512×512的小块,分别推理,再把结果合并回原图坐标。
安装SAHI:
pip install sahi用SAHI配合YOLOv8做切片推理:
from sahi.model import Yolov5DetectionModel from sahi.predict import get_sliced_prediction model = Yolov5DetectionModel( model_path='runs/satellite/exp1/weights/best.pt', confidence_threshold=0.25, device='cuda', category_mapping={0: 'airplane', 1: 'ship'} ) result = get_sliced_prediction( image_path='test_big.tif', detection_model=model, slice_height=512, slice_width=512, overlap_height_ratio=0.2, overlap_width_ratio=0.2, postprocess_match_threshold=0.4, verbose=1 ) result.export_visuals(export_dir='output/')这里的slice_height和slice_width设置切片大小,overlap_height_ratio=0.2表示相邻切片有20%的重叠,防止目标被切在边缘导致漏检。postprocess_match_threshold是合并重叠框时判断是否为同一目标的IoU阈值,建议从0.4开始试,如果出现同一个目标被输出多个框,就调大到0.5。注意SAHI的Yolov5DetectionModel实际上兼容YOLOv8导出的pt文件,只要是通过Ultralytics训练的都能直接用。
对比直接推理和切片推理的效果,你会发现小目标的召回率提升非常明显,代价是推理时间增加数倍。如果对速度有要求,可以先用切片推理找出目标坐标,再用原图局部区域做二次精细分类,这是一个典型的级联思路。
日常调试时可以写个小脚本验证检测结果与标注的匹配程度:
import cv2 import numpy as np image = cv2.imread('test_big.tif') h, w, _ = image.shape with open('test_big.txt', 'r') as f: boxes = [] for line in f: cls, xc, yc, bw, bh = line.split() xc, yc, bw, bh = float(xc)*w, float(yc)*h, float(bw)*w, float(bh)*h x1, y1 = int(xc - bw/2), int(yc - bh/2) x2, y2 = int(xc + bw/2), int(yc + bh/2) cv2.rectangle(image, (x1, y1), (x2, y2), (0, 255, 0), 2) # 再叠加SAHI结果,画红色框 result_boxes = result.object_prediction_list for pred in result_boxes: bbox = pred.bbox.to_xyxy() cv2.rectangle(image, (int(bbox[0]), int(bbox[1])), (int(bbox[2]), int(bbox[3])), (0, 0, 255), 2) cv2.imwrite('comparison.jpg', image)绿色是手动标注,红色是模型预测,两张叠加后能直观看出漏检和误检到底发生在哪些区域——通常是密集排列的车辆、被阴影遮挡的建筑物、以及边界模糊的舰船。之后你可以针对这些失败模式补标注或调参数。
最后还有一个常用的验证技巧:计算你所用训练设备的推理FPS时,不要只测单张640×640的图,因为真实卫星影像尺寸远大于此。你应该模拟切片推理的完整流程,统计包括切片、推理、合并的端到端耗时,才能对实际部署有个合理预期。这份800张的数据集规模不算大,但足够你建立起从数据检查、格式转换、训练调参到小目标推理的完整方法论,之后换上千张图片的数据集,你只需要替换路径和类别数,其余流程完全复用。
本文还有配套的精品资源,点击获取