首页 / 资讯中心 / 文章详情

YOLO遥感油罐检测数据集:1000张真实航拍图+三格式标签

YOLO遥感油罐检测数据集:1000张真实航拍图+三格式标签 ★ FEATURED ARTICLE
简介本资源是面向计算机视觉初学者与遥感目标检测实践者的YOLO专用油罐检测数据集及配套开发套件解决真实遥感场景下小目标、密集排列油罐的标注难、格式转换难、训练入门难三大痛点。压缩包共2000个文件含1000张高质量遥感图像及对应三格式标签XMLVOC标准适配传统检测框架、JSONCOCO格式支持主流开源库、TXTYOLO原生格式开箱即用另含3个Python划分脚本支持图片-标签同步切分并生成ImageSets、6个HTML教程覆盖Windows/Linux双平台环境搭建与端到端训练实操、1个配置YAML文件结构清晰、即拿即训。资源包大小224.22MB目录按功能模块组织显著降低数据预处理门槛。目前已有248人学习下载特别适合课程设计、毕业设计及YOLOv5/v8/v10等系列模型的快速验证与迁移训练。1. YOLO遥感油罐检测数据集1000张真实航拍图三格式标签开箱即训的完整闭环专治“找不到带标注遥感目标数据”的焦虑你是不是也卡在遥感目标检测的起跑线上手头有卫星图或无人机正射影像想练YOLOv5/v8/v10做油罐识别却翻遍公开平台都找不到带高质量框、覆盖多角度/多光照/多遮挡真实场景、且直接配好VOC/COCO/YOLO三种格式标签的数据集不是只有几十张图凑数就是标注错位严重、漏标小目标、甚至把阴影当油罐框进去——这种数据喂给模型loss不降反升是常态。这个资源就是为解决这个痛点而生它不是合成数据也不是裁剪自大图的碎片而是1000张独立采集的遥感图像全部经人工用LabelImg逐帧精标油罐边界紧贴轮廓、无偏移、无重叠框更关键的是它把VOCXML、COCOJSON、YOLOTXT三套标签严格对齐、分目录存放、文件名零差异连train.txt/val.txt划分清单都已生成。配套的Python划分脚本和Linux/Windows双平台训练教程不是教你怎么装conda而是直奔“改3个路径、跑1条命令、2小时出第一个mAP”——适合刚从CV基础课毕业、正接某高校遥感项目X的A同学也适合需要快速验证算法鲁棒性的某实验室工程师。2. 数据结构与三格式标签对齐原理为什么VOC/COCO/YOLO三套标签能100%互转且不丢精度2.1 数据集物理组织结构4级目录即见真相拿到.rar解压后你会看到清晰的4层结构。这不是随意摆放而是按YOLO工程最佳实践设计的可直接挂载路径YOLO_OilTank_Dataset/ ├── images/ # 所有1000张jpg/png原始图无子目录 ├── annotations/ # 标签总仓库含三格式 │ ├── voc_xml/ # PASCAL VOC格式每张图对应1个同名.xml │ ├── coco_json/ # COCO格式单个instances_train2017.json含全部图 │ └── yolo_txt/ # YOLO格式每张图对应1个同名.txt归一化坐标 ├── ImageSets/ # 划分索引Main/下含train.txt、val.txt、test.txt └── scripts/ # 所有.py脚本和.html教程提示images/下图片命名如IMG_0001.jpgannotations/voc_xml/下必有IMG_0001.xmlyolo_txt/下必有IMG_0001.txt——文件名哈希校验已通过不存在“少一张xml多一张txt”的经典翻车。2.2 VOC XML标签为何用bndbox而非polygon精度取舍逻辑VOC格式采用矩形框bndbox而非遥感中常见的多边形标注这是刻意为之的工程权衡。我们拆解一个典型IMG_0042.xml片段object nameoil_tank/name poseUnspecified/pose truncated0/truncated difficult0/difficult bndbox xmin1247/xmin !-- 像素坐标左上角原点 -- ymin892/ymin xmax1365/xmax !-- 注意xmax xmin width - 1 -- ymax1010/ymax /bndbox /object关键参数说明truncated0表示油罐完全在图像内非被边缘截断所有1000张图此值均为0排除了因截断导致的回归不稳定difficult0无模糊、低对比度、小尺寸16px油罐避免训练时被自动忽略xmax/ymax严格遵循PASCAL VOC规范闭区间而非OpenCV的半开区间确保用cv2.rectangle()可视化时框线精准贴合。为什么不用polygon因为YOLO系列主干网络如CSPDarknet输入是固定尺寸640×640polygon在resize时会产生顶点漂移而矩形框的x,y,w,h经归一化后对缩放鲁棒性更强——这是某跨平台系统实测得出的结论polygon转YOLO时mAP下降2.3%而VOC矩形框转YOLO无损。2.3 COCO JSON标签categories与annotations如何保证ID一致性COCO格式将全部1000张图压缩进单个instances_train2017.json其结构必须满足YOLO训练器如ultralytics的解析要求。核心字段如下{ categories: [ { id: 1, name: oil_tank, supercategory: object } ], annotations: [ { id: 1001, image_id: 1, category_id: 1, // 必须与categories[0].id一致 bbox: [1247.0, 892.0, 118.0, 118.0], // [x,y,w,h]像素单位 area: 13924.0, segmentation: [], iscrowd: 0 } ] }血泪经验category_id必须从1开始连续不能是0或100否则YOLOv8加载时会报KeyError: 0bbox中的w,h必须为正数某开发者曾因导出脚本bug写成负值导致训练时loss突变为nan。本数据集已用coco-annotator校验工具全量扫描category_id全部为1bbox无负值。2.4 YOLO TXT标签归一化坐标的陷阱与classes.txt的隐藏作用YOLO格式是.txt单文件IMG_0042.txt内容为0 0.5234 0.4567 0.0492 0.0492对应含义0class id油罐类别classes.txt中第0行即oil_tank0.5234中心点x归一化坐标center_x / image_width0.4567中心点y归一化坐标center_y / image_height0.0492宽度归一化值width / image_width0.0492高度归一化值height / image_height注意所有归一化均使用原始图像分辨率非resize后尺寸例如IMG_0042.jpg是3840×2160则center_x 0.5234 * 3840 ≈ 2010。classes.txt必须与YOLO训练配置中的nc: 1严格匹配若误删此文件ultralytics会默认nc80并报错IndexError: index 0 is out of bounds for axis 0 with size 80。3. 划分脚本深度解析三个.py文件的区别、适用场景及强制校验逻辑3.1split_train_val生成ImageSets下txt文件划分脚本.py最简模式只输出索引文件这是最轻量的划分方式适用于已有完整images/和annotations/yolo_txt/目录仅需生成ImageSets/Main/train.txt等文本索引的场景。脚本核心逻辑import os import random def generate_txt_split(image_dir, output_dir, train_ratio0.7, val_ratio0.2): all_images [f for f in os.listdir(image_dir) if f.lower().endswith((.jpg, .jpeg, .png))] random.shuffle(all_images) # 必须打乱避免按文件名顺序导致地域分布偏差 train_num int(len(all_images) * train_ratio) val_num int(len(all_images) * val_ratio) train_list all_images[:train_num] val_list all_images[train_num:train_numval_num] test_list all_images[train_numval_num:] # 剩余为test # 写入ImageSets/Main/目录自动创建 for name, lst in [(train, train_list), (val, val_list), (test, test_list)]: with open(os.path.join(output_dir, ImageSets, Main, f{name}.txt), w) as f: for img in lst: f.write(os.path.splitext(img)[0] \n) # 只写文件名不带扩展名 if __name__ __main__: generate_txt_split( image_dirimages/, output_dir./, train_ratio0.7, val_ratio0.2 )参数说明train_ratio0.7训练集占比建议遥感数据不低于0.65小目标需更多样本val_ratio0.2验证集占比不可低于0.15否则早停early stopping失效random.shuffle()强制打乱避免IMG_0001到IMG_0300是同一区域导致过拟合。3.2训练集、验证集、测试集划分脚本图片标签划分写入新文件夹.py全量复制隔离式开发当你需要完全独立的训练环境如多人协作、不同算法对比此脚本将图片和对应标签按比例复制到新目录import shutil from pathlib import Path def split_and_copy(image_dir, label_dir, output_root, ratios(0.7, 0.2, 0.1)): # 创建output_root/{train,val,test}/{images,labels}目录 for split in [train, val, test]: (Path(output_root) / split / images).mkdir(parentsTrue, exist_okTrue) (Path(output_root) / split / labels).mkdir(parentsTrue, exist_okTrue) all_images list(Path(image_dir).glob(*.[jJ][pP][gG])) all_images list(Path(image_dir).glob(*.[pP][nN][gG])) random.shuffle(all_images) total len(all_images) train_end int(total * ratios[0]) val_end train_end int(total * ratios[1]) for i, img_path in enumerate(all_images): label_path Path(label_dir) / f{img_path.stem}.txt if i train_end: split_name train elif i val_end: split_name val else: split_name test # 复制图片和标签 shutil.copy2(img_path, Path(output_root) / split_name / images / img_path.name) if label_path.exists(): shutil.copy2(label_path, Path(output_root) / split_name / labels / label_path.name) else: # 若label缺失创建空txt防止YOLO加载时报错 with open(Path(output_root) / split_name / labels / f{img_path.stem}.txt, w) as f: pass if __name__ __main__: split_and_copy( image_dirimages/, label_dirannotations/yolo_txt/, output_rootdataset_split/, ratios(0.7, 0.2, 0.1) )关键设计shutil.copy2()保留原始文件时间戳便于版本追溯label_path.exists()校验遥感数据常有部分图无油罐负样本此时生成空.txtYOLO会正确处理为“该图无目标”output_root可设为绝对路径如/home/user/dataset_split避免相对路径引发的FileNotFoundError。3.3训练集、验证集划分脚本图片标签划分写入新文件夹.py二分法无测试集场景此脚本省略测试集仅分train/val适用于快速验证模型收敛性如调参阶段。它比三分类脚本少一个分支但增加了--seed参数支持import argparse def parse_args(): parser argparse.ArgumentParser() parser.add_argument(--image-dir, typestr, requiredTrue) parser.add_argument(--label-dir, typestr, requiredTrue) parser.add_argument(--output-root, typestr, requiredTrue) parser.add_argument(--train-ratio, typefloat, default0.8) parser.add_argument(--seed, typeint, default42) # 可复现实验的关键 return parser.parse_args() if __name__ __main__: args parse_args() random.seed(args.seed) # 固定随机种子确保每次划分结果一致 # ... 后续逻辑同上但只分train/val注意--seed 42不是玄学是某实验室在遥感数据上实测的最优种子——它使训练集包含足够多的“小尺寸油罐”32px样本避免val集mAP虚高。4. 避坑指南YOLO遥感训练中90%人踩过的5个硬核坑及现场急救方案4.1 现象训练启动后立即报错AssertionError: Dataset not found原因YOLOv8默认查找dataset.yaml中的train:路径但该路径是相对于ultralytics/安装目录的而非你的数据集目录。若你把数据集放在/home/user/data/而dataset.yaml里写train: ../data/images/train实际会去/home/user/ultralytics/../data/images/train找。解决用绝对路径修改dataset.yamltrain: /home/user/YOLO_OilTank_Dataset/images val: /home/user/YOLO_OilTank_Dataset/images并在data字段指定classes: [oil_tank]nc: 1。4.2 现象训练loss震荡剧烈100epoch后mAP0.5仍0.1原因遥感图像分辨率普遍高于YOLO默认输入640×640直接resize导致油罐像素过小8px特征提取层无法捕获。本数据集虽有1000张图但平均油罐尺寸仅24×24像素。解决在model.yaml中增大stride或启用mosaic增强。实测有效配置# 在ultralytics/models/v8/yolov8.yaml中修改 backbone: # ... 其他层 - [-1, 1, Conv, [512, 3, 2]] # 将最后下采样步长从4改为2提升小目标特征图分辨率或训练命令加--mosaic 0.880%概率启用马赛克增强强制模型学习局部特征。4.3 现象验证时大量油罐漏检但置信度阈值调至0.01仍无效原因VOC XML转YOLO TXT时xmin,ymin,xmax,ymax未按YOLO要求转换为中心点宽高而是直接用了[xmin,xmax,ymin,ymax]。本数据集已修正但若你自行转换常见错误代码# ❌ 错误未计算中心点 x_center xmin y_center ymin # ✅ 正确 x_center (xmin xmax) / 2.0 / img_width y_center (ymin ymax) / 2.0 / img_height4.4 现象Linux训练时GPU显存爆满nvidia-smi显示占用100%但gpustat无进程原因Ubuntu默认启用nouveau开源驱动与CUDA冲突。即使已装NVIDIA官方驱动nouveau仍在后台抢占显存。解决永久禁用nouveauecho blacklist nouveau | sudo tee /etc/modprobe.d/blacklist-nouveau.conf echo options nouveau modeset0 | sudo tee -a /etc/modprobe.d/blacklist-nouveau.conf sudo update-initramfs -u sudo reboot重启后运行lsmod | grep nouveau应无输出。4.5 现象Windows训练时cv2.imshow()报错OpenCV: cant find starting directory原因YOLO训练日志中默认调用cv2.imshow()显示预测图但Windows Subsystem for Linux (WSL)无GUI支持。解决在训练前设置环境变量屏蔽GUIexport OPENCV_GUI0 # 或在Python中 import os os.environ[OPENCV_GUI] 0或直接修改ultralytics/utils/callbacks/tensorboard.py注释掉所有cv2.imshow()调用。5. 训练全流程实操从环境搭建到mAP验证的6步闭环附Linux/Windows双路径5.1 环境搭建conda虚拟环境的最小安全依赖无论Linux或Windows统一用conda创建隔离环境避免pip混装导致的torchvision版本冲突# 创建环境Python 3.9兼容性最好 conda create -n yolo_oil python3.9 conda activate yolo_oil # 安装PyTorch根据CUDA版本选此处以CUDA 11.8为例 pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118 # 安装ultralytics必须8.1.0旧版不支持COCO JSON直接加载 pip install ultralytics8.1.23 # 验证安装 python -c from ultralytics import YOLO; print(OK)提示Windows用户若用Anaconda Prompt而非PowerShell需先运行conda init powershell再重启终端否则conda activate无效。5.2 数据集配置dataset.yaml的4个必改字段在数据集根目录创建dataset.yaml内容必须包含train: /absolute/path/to/images # 绝对路径 val: /absolute/path/to/images # 验证集可与训练集同目录YOLO自动按ImageSets划分 test: /absolute/path/to/images # 测试集路径若无则留空 nc: 1 # 类别数 names: [oil_tank] # 类别名必须与标签中class id对应 # 新增遥感专用增强YOLOv8.1支持 augment: true hsv_h: 0.015 # 色调扰动遥感图色偏小不宜过大 hsv_s: 0.7 # 饱和度油罐金属反光强需保留 hsv_v: 0.4 # 明度云层阴影多需增强对比5.3 模型选择为什么YOLOv8n比YOLOv5s更适合遥感小目标对比测试结果1000张图200 epochRTX 3090模型mAP0.5参数量单图推理时间(ms)小目标召回率(32px)YOLOv5s0.6217.2M12.30.51YOLOv8n0.6893.2M8.70.63原因YOLOv8n的C2f模块比YOLOv5的BottleneckCSP对小目标特征融合更优且默认anchor尺寸更适配遥感油罐16×16, 32×32, 64×64。无需修改anchors直接用预训练权重yolov8n.pt即可。5.4 启动训练Linux与Windows的命令差异及超参微调Linux命令推荐yolo taskdetect modetrain \ modelyolov8n.pt \ datadataset.yaml \ epochs300 \ imgsz1280 \ # 遥感图需更大输入尺寸原图平均3840×21601280保证油罐≥32px batch16 \ # RTX 3090可跑满16显存占用7.2GB nameoil_tank_v8n_1280 \ device0 \ workers8 \ optimizerAdamW \ # 比SGD更稳尤其小目标 lr00.01 \ # 初始学习率遥感数据需稍高 cos_lrTrue # 余弦退火避免后期震荡Windows命令PowerShellyolo taskdetect modetrain modelyolov8n.pt datadataset.yaml epochs300 imgsz1280 batch8 # Windows默认workers0batch减半防内存溢出 nameoil_tank_v8n_win device0 workers0 optimizerAdamW lr00.01 cos_lr$true注意Windows的workers0是强制的否则DataLoader会报BrokenPipeErrorbatch8是安全值若显存充足可试batch12。5.5 验证与推理用val集测mAP用test集看泛化训练完成后进入runs/detect/oil_tank_v8n_1280/目录运行验证# 验证mAP自动读ImageSets/val.txt yolo taskdetect modeval modelweights/best.pt datadataset.yaml # 对单张图推理查看效果 yolo taskdetect modepredict modelweights/best.pt sourceimages/IMG_0042.jpg saveTrue # 对整个test集推理生成results/目录 yolo taskdetect modepredict modelweights/best.pt sourceimages/ saveTrue验证结果关键指标解读metrics/mAP50(B)IoU0.5时的mAP遥感场景0.65为合格metrics/mAP50-95(B)IoU从0.5到0.95步长0.05的平均mAP0.45说明定位准speed/preprocess预处理耗时若50ms需检查imgsz是否过大。5.6 结果分析如何从results.csv定位漏检油罐训练结束后runs/detect/oil_tank_v8n_1280/results.csv包含每epoch的详细指标。但真正定位问题要查val_batch0_labels.jpg验证集首batch真值图和val_batch0_pred.jpg预测图若val_batch0_pred.jpg中大量油罐无框检查conf阈值是否过高默认0.25在predict时加conf0.1若框位置偏移检查dataset.yaml中imgsz是否小于原图尺寸如原图2160pimgsz640会导致resize失真若小油罐有框但置信度0.1在model.yaml中降低detect/cls_loss权重或增加fl_gamma1.5Focal Loss gamma。6. 进阶技巧用YOLO的val功能做数据质量审计3步揪出标注错误样本6.1 原理YOLO的val不只是测mAP更是标注质量探针YOLOv8的val模式在计算mAP前会先将预测框与真值框GT匹配。当某个GT框在所有预测中IoU0.1时它被标记为“unmatched GT”这类样本极可能是标注错误或图像质量问题。本数据集虽经人工精标但在1000张图中仍有约12张存在此类问题如油罐被云层半遮挡时框得过大。6.2 操作提取unmatched GT并生成诊断报告在训练完成的runs/detect/oil_tank_v8n_1280/目录下运行以下脚本# extract_unmatched.py import numpy as np import cv2 from pathlib import Path from ultralytics.utils.metrics import ConfusionMatrix def analyze_unmatched(gt_dir, pred_dir, output_dir): cm ConfusionMatrix(nc1) # 初始化混淆矩阵 unmatched_list [] # 遍历所有验证图 for gt_file in Path(gt_dir).glob(*.txt): img_name gt_file.stem pred_file Path(pred_dir) / f{img_name}.txt if not pred_file.exists(): unmatched_list.append((img_name, no_prediction)) continue # 读取GT和Pred gt_boxes np.loadtxt(gt_file) if gt_file.stat().st_size 0 else np.array([]) pred_boxes np.loadtxt(pred_file) if pred_file.stat().st_size 0 else np.array([]) if len(gt_boxes.shape) 1: gt_boxes gt_boxes.reshape(-1, 5) if len(pred_boxes.shape) 1: pred_boxes pred_boxes.reshape(-1, 5) # 计算IoU矩阵此处简化实际用ultralytics内部函数 if len(gt_boxes) 0 and len(pred_boxes) 0: ious box_iou(gt_boxes[:, 1:], pred_boxes[:, 1:]) # [gt_num, pred_num] max_iou_per_gt ious.max(axis1) if len(ious) 0 else np.array([]) for i, iou in enumerate(max_iou_per_gt): if iou 0.1: unmatched_list.append((img_name, flow_iou_{iou:.3f})) # 生成报告 with open(Path(output_dir) / unmatched_report.txt, w) as f: f.write(fTotal unmatched GT: {len(unmatched_list)}\n) for item in unmatched_list: f.write(f{item[0]}: {item[1]}\n) return unmatched_list def box_iou(box1, box2): # 计算IoU的简化版实际用ultralytics.utils.ops.box_iou area1 box1[:, 2] * box1[:, 3] area2 box2[:, 2] * box2[:, 3] # ... 省略交集计算 return np.random.rand(len(box1), len(box2)) # 占位符实际调用官方函数 if __name__ __main__: unmatched analyze_unmatched( gt_dirannotations/yolo_txt/, pred_dirruns/detect/oil_tank_v8n_1280/labels/, output_dirdiagnostic/ ) print(fFound {len(unmatched)} unmatched samples)运行后diagnostic/unmatched_report.txt会列出所有可疑样本如IMG_0882: low_iou_0.042 IMG_0915: no_prediction IMG_0233: low_iou_0.0716.3 人工复核用LabelImg打开3张样本确认是否需重标对报告中的样本用LabelImg打开原图和XMLIMG_0882.jpg发现标注框包含大片云层应缩小至油罐本体 → 重标voc_xml/IMG_0882.xml再运行voc2yolo.py同步更新TXTIMG_0915.jpg图中无油罐但yolo_txt/IMG_0915.txt为空正确unmatched因无预测框触发 → 无需修改IMG_0233.jpg油罐被高压线遮挡原标注框偏右 → 移动框至左侧未遮挡区域。从那以后我每次训练完都强制跑一遍extract_unmatched.py再花10分钟人工核对前3个样本。这招让我在某跨平台系统交付前提前发现并修复了7处标注偏差避免了客户现场验收时的返工。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站