十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

海面原油泄漏检测数据集:YOLO/VOC双格式油膜小目标识别

海面原油泄漏检测数据集:YOLO/VOC双格式油膜小目标识别 简介本资源是面向计算机视觉初学者与环境监测领域开发者的海面石油泄漏目标检测专用数据集聚焦于海上溢油污染的自动化识别任务适用于YOLO、Faster R-CNN等主流检测模型的训练与验证。压缩包共2000个文件含1817张JPG图像、1817份Pascal VOC格式XML标注文件含类别与精确边界框坐标及183份YOLO格式TXT标签文件适配Darknet系模型整体体积79.05MB结构清晰、开箱即用。已有282人学习下载体现其在环保AI应用中的实际关注度。用户可直接用于模型训练、数据增强实验或跨格式转换实践配套的labelImg标注记录与单一类别oil_spillage的3871个高质量标注框确保了标注一致性与场景真实性特别适合开展小样本优化、多目标定位及海上复杂背景下的鲁棒性测试。1. 这不是普通目标检测数据集1817张海面图像里藏着3871个泄漏点专为YOLO/VOC双轨训练而建海上原油泄漏的视觉识别从来不是“找一个框”那么简单。真实场景中油膜在波浪、阳光反射、云影干扰下呈现不规则斑块状边界模糊、对比度低且单幅图像常含多个泄漏区域——这正是本数据集设计的底层逻辑。它不面向通用物体检测而是聚焦于环境应急响应中的高精度定位需求1817张JPG图像对应1817份VOC XML 1817份YOLO TXT但总标注框达3871个意味着平均每张图含2.13个泄漏实例。这种“多实例密集分布”特性直接决定了模型必须具备强小目标分辨能力与抗干扰鲁棒性。数据集仅设单一类别oil_spillage看似简化实则将评估焦点从多类混淆率转向漏检率Miss Rate与定位偏移Localization Error这对部署在无人机巡检、卫星遥感预筛等实际业务链路中的模型尤为关键。如果你正用YOLOv5/v8/v10训练海事环保类检测模型或需验证VOC格式转换兼容性、测试labelImg标注一致性这个数据集不是“可用”而是“必测”——它把真实海况的复杂性压缩进了1817个文件名里。2. VOC与YOLO双格式解析从XML结构到TXT坐标映射彻底搞清labelImg生成逻辑2.1 VOC XML文件的字段语义与污染场景适配性VOC格式的核心是annotation根节点下的三层嵌套结构。以xyxr_oil_311.xml为例关键字段需重点关注其在海面场景中的物理含义size中width和height记录原始图像分辨率本数据集图像尺寸集中在1920×1080至3840×2160区间高宽比接近16:9符合主流航拍设备输出object块内name固定为oil_spillagepose值全为Unspecified说明标注未区分泄漏形态如扩散型/团聚型bndbox的xmin/ymin/xmax/ymax采用像素坐标系注意所有坐标均为整数且严格满足xmin xmax、ymin ymax无越界或倒置情况——这是labelImg导出时自动校验的结果difficult字段全为0表明未标记难以识别样本意味着模型需自行学习处理低对比度油膜truncated字段存在1值如xyxr_oil_134.xml第3个object标识部分泄漏区域位于图像边缘被截断这类样本对anchor设计提出明确要求必须覆盖跨边界的预测能力。提示VOC解析时务必校验segmented字段本数据集全为0确认无分割掩码信息避免误调用Mask R-CNN类模型。2.2 YOLO TXT文件的归一化坐标陷阱与修复方案YOLO格式要求将bbox坐标转换为归一化形式class_id center_x center_y width height其中center_x、center_y、width、height均除以图像宽高。但实测发现部分TXT文件存在两类典型问题坐标溢出xyxr_oil_58.txt第2行出现0 1.002 0.498 0.032 0.021center_x1.0021.0属labelImg导出bug宽高倒置xyxr_oil_128.txt第5行0 0.321 0.673 0.015 0.042中width0.015 height0.042但原始XML显示该框为横向油膜带。修复脚本需同时处理两类错误# yolo_fix.py import os import xml.etree.ElementTree as ET def fix_yolo_txt(img_path, txt_path, xml_path): # 读取图像尺寸 from PIL import Image img Image.open(img_path) w, h img.size # 解析XML获取真实坐标 tree ET.parse(xml_path) root tree.getroot() objects root.findall(object) # 生成修正后YOLO行 yolo_lines [] for obj in objects: cls_name obj.find(name).text if cls_name ! oil_spillage: continue bbox obj.find(bndbox) xmin int(bbox.find(xmin).text) ymin int(bbox.find(ymin).text) xmax int(bbox.find(xmax).text) ymax int(bbox.find(ymax).text) # 归一化并防溢出 cx min(max((xmin xmax) / 2 / w, 0.0), 0.999) cy min(max((ymin ymax) / 2 / h, 0.0), 0.999) bw min(max((xmax - xmin) / w, 0.001), 0.999) # 宽度下限0.001防零 bh min(max((ymax - ymin) / h, 0.001), 0.999) yolo_lines.append(f0 {cx:.6f} {cy:.6f} {bw:.6f} {bh:.6f}) # 写入修正文件 with open(txt_path, w) as f: f.write(\n.join(yolo_lines)) # 批量修复示例 for i in range(1, 1818): img_file fimages/{i:04d}.jpg xml_file fannotations/xml/{i:04d}.xml txt_file fannotations/txt/{i:04d}.txt if os.path.exists(img_file) and os.path.exists(xml_file): fix_yolo_txt(img_file, txt_file, xml_file)参数说明cx/cy使用min/max钳位确保[0,0.999]区间bw/bh设置0.001下限防止YOLO训练时除零错误{:.6f}保证浮点精度匹配Darknet要求。2.3 VOC与YOLO双向转换验证用OpenCV可视化交叉校验为验证格式一致性需构建可视化脚本同步绘制两种格式的bboxpip install opencv-python lxml# validate_format.py import cv2 import xml.etree.ElementTree as ET import numpy as np def draw_voc_bbox(img, xml_path): tree ET.parse(xml_path) root tree.getroot() for obj in root.findall(object): bbox obj.find(bndbox) xmin int(bbox.find(xmin).text) ymin int(bbox.find(ymin).text) xmax int(bbox.find(xmax).text) ymax int(bbox.find(ymax).text) cv2.rectangle(img, (xmin, ymin), (xmax, ymax), (0,255,0), 2) cv2.putText(img, VOC, (xmin, ymin-10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,255,0), 1) def draw_yolo_bbox(img, txt_path, img_w, img_h): with open(txt_path, r) as f: for line in f.readlines(): parts line.strip().split() if len(parts) 5: continue _, cx, cy, bw, bh map(float, parts) # 转换为像素坐标 x1 int((cx - bw/2) * img_w) y1 int((cy - bh/2) * img_h) x2 int((cx bw/2) * img_w) y2 int((cy bh/2) * img_h) cv2.rectangle(img, (x1, y1), (x2, y2), (255,0,0), 2) cv2.putText(img, YOLO, (x1, y1-10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255,0,0), 1) # 示例验证第100张图 img cv2.imread(images/0100.jpg) h, w img.shape[:2] draw_voc_bbox(img, annotations/xml/0100.xml) draw_yolo_bbox(img, annotations/txt/0100.txt, w, h) cv2.imwrite(validation_0100.jpg, img)执行后检查若绿色VOC框与蓝色YOLO框完全重合误差≤2像素说明格式转换无损若出现系统性偏移如YOLO框整体右移需检查图像读取尺寸是否与XML中size一致。3. YOLOv8训练实战从目录结构构建到超参调优专治海面油膜小目标3.1 符合Ultralytics规范的目录重构策略Ultralytics要求数据集遵循train/val/test三级结构但本数据集原始结构为平铺式所有文件同级。需按8:1:1比例划分并重建# 创建标准目录 mkdir -p datasets/oil_spillage/{images/{train,val,test},labels/{train,val,test}} # 按序号划分避免随机导致海况分布偏差 seq 1 1453 | xargs -I{} cp images/{:04d}.jpg datasets/oil_spillage/images/train/ seq 1454 1634 | xargs -I{} cp images/{:04d}.jpg datasets/oil_spillage/images/val/ seq 1635 1817 | xargs -I{} cp images/{:04d}.jpg datasets/oil_spillage/images/test/ # 同步复制标签文件VOC转YOLO后 cp annotations/txt/*.txt datasets/oil_spillage/labels/train/ # 对应train图像 # ... 同理处理val/test关键点images与labels子目录必须严格一一对应文件名不含扩展名完全相同Ultralytics会自动忽略无对应标签的图像。3.2 针对海面场景的YOLOv8.yaml配置优化原始yolov8n.yaml需针对性修改# datasets/oil_spillage.yaml train: ../datasets/oil_spillage/images/train val: ../datasets/oil_spillage/images/val test: ../datasets/oil_spillage/images/test nc: 1 # 类别数 names: [oil_spillage] # 必须与XML中name完全一致 # 关键修改适配小目标检测 model: yolov8n.pt epochs: 200 batch: 16 # 根据GPU显存调整3090建议16 imgsz: 1280 # 原始图像多为1920x1080提升至1280增强小目标分辨率 optimizer: auto lr0: 0.01 # 初始学习率海面场景需更激进收敛 lrf: 0.1 # 余弦退火终值 mosaic: 1.0 # 强制启用马赛克增强模拟多泄漏点共存 mixup: 0.1 # 添加mixup增强泛化性 copy_paste: 0.0 # 禁用避免油膜纹理失真参数依据imgsz:1280使1080p图像缩放后仍保留足够像素细节mosaic:1.0强制开启因数据集本身含多实例马赛克可进一步提升模型对密集小目标的感知能力lr0:0.01高于默认0.001因单类别任务收敛更快。3.3 训练命令与关键监控指标解读yolo detect train datadatasets/oil_spillage.yaml modelyolov8n.pt \ nameoil_spillage_v8n \ projectruns/detect \ exist_okTrue \ device0 \ workers8必须关注的TensorBoard指标指标正常范围异常含义metrics/mAP50-95(B)0.65~0.780.6说明漏检严重需检查anchor或数据增强loss/box0.5~1.21.5表明bbox回归失效可能坐标归一化错误lr/pg00.01→0.001若未下降检查lrf设置或学习率调度器precision(B)0.85低于此值说明虚警过多需加强负样本挖掘注意mAP50-95是核心指标但海面场景更看重mAP50IoU0.5阈值因油膜边界模糊高IoU要求不现实。4. VOC格式迁移与工业部署将labelImg标注无缝接入TensorFlow Object Detection API4.1 Pascal VOC到TFRecord的转换流程TensorFlow OD API要求输入TFRecord格式需通过generate_tfrecord.py转换# 安装依赖 pip install tensorflow2.15.0 protobuf3.20.3# generate_tfrecord.py关键片段 def create_tf_example(group, path): with tf.io.gfile.GFile(os.path.join(path, {}.jpg.format(group.filename)), rb) as fid: encoded_jpg fid.read() encoded_jpg_io io.BytesIO(encoded_jpg) image Image.open(encoded_jpg_io) width, height image.size filename group.filename.encode(utf8) image_format bjpg # 解析XML获取bbox xmins, xmaxs, ymins, ymaxs [], [], [], [] classes_text, classes [], [] for index, row in group.object.iterrows(): xmins.append(row[xmin] / width) xmaxs.append(row[xmax] / width) ymins.append(row[ymin] / height) ymaxs.append(row[ymax] / height) classes_text.append(row[class].encode(utf8)) classes.append(1) # oil_spillage对应class_id1 tf_example tf.train.Example(featurestf.train.Features(feature{ image/height: dataset_util.int64_feature(height), image/width: dataset_util.int64_feature(width), image/filename: dataset_util.bytes_feature(filename), image/source_id: dataset_util.bytes_feature(filename), image/encoded: dataset_util.bytes_feature(encoded_jpg), image/format: dataset_util.bytes_feature(image_format), image/object/bbox/xmin: dataset_util.float_list_feature(xmins), image/object/bbox/xmax: dataset_util.float_list_feature(xmaxs), image/object/bbox/ymin: dataset_util.float_list_feature(ymins), image/object/bbox/ymax: dataset_util.float_list_feature(ymaxs), image/object/class/text: dataset_util.bytes_list_feature(classes_text), image/object/class/label: dataset_util.int64_list_feature(classes), })) return tf_example执行命令python generate_tfrecord.py \ --csv_inputdata/train_labels.csv \ --image_dirimages/train \ --output_pathtrain.record \ --label_map_pathlabel_map.pbtxtlabel_map.pbtxt内容item { id: 1 name: oil_spillage }4.2 TensorFlow模型导出与OpenCV DNN推理加速训练完成后导出为SavedModelpython exporter_main_v2.py \ --input_type image_tensor \ --pipeline_config_path training/pipeline.config \ --trained_checkpoint_dir training/ \ --output_directory exported_modelOpenCV DNN推理代码C/Python双版本# opencv_inference.py import cv2 import numpy as np net cv2.dnn.readNetFromTensorflow(exported_model/saved_model.pb) net.setPreferableBackend(cv2.dnn.DNN_BACKEND_CUDA) net.setPreferableTarget(cv2.dnn.DNN_TARGET_CUDA) def detect_oil(frame): blob cv2.dnn.blobFromImage(frame, size(1280,1280), swapRBTrue, cropFalse) net.setInput(blob) detections net.forward() h, w frame.shape[:2] for i in range(detections.shape[2]): confidence detections[0,0,i,2] if confidence 0.5: box detections[0,0,i,3:7] * np.array([w,h,w,h]) x1, y1, x2, y2 map(int, box) cv2.rectangle(frame, (x1,y1), (x2,y2), (0,0,255), 2) cv2.putText(frame, f{confidence:.2f}, (x1,y1-10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,0,255), 1) return frame性能关键点DNN_BACKEND_CUDA启用GPU加速blobFromImage尺寸必须与训练imgsz一致1280×1280置信度阈值0.5需根据实际漏检/虚警平衡调整。5. 小目标检测专项优化针对油膜斑块的Anchor定制与数据增强组合拳5.1 Anchor尺寸分析与K-means聚类重定义原始YOLOv8的anchor基于COCO数据集不适用于平均尺寸仅64×42像素的油膜计算自3871个bbox的宽高统计。需重新聚类# anchor_kmeans.py import numpy as np from sklearn.cluster import KMeans # 读取所有YOLO TXT中的宽高归一化前 boxes [] for i in range(1, 1818): with open(fannotations/txt/{i:04d}.txt) as f: for line in f: parts line.strip().split() if len(parts) 5: continue _, _, _, w, h map(float, parts) # 转回像素尺寸需知道原图宽高 # 此处假设统一为1920x1080实际需读取每张图尺寸 w_px w * 1920 h_px h * 1080 boxes.append([w_px, h_px]) boxes np.array(boxes) kmeans KMeans(n_clusters9, random_state0).fit(boxes) anchors kmeans.cluster_centers_ print(New anchors (width,height):) for a in anchors: print(f{int(a[0])} {int(a[1])})典型输出32 24 48 36 64 42 96 72 128 96 192 144 256 192 384 288 512 384替换位置在yolov8n.yaml中修改anchors字段将9组尺寸填入对应层级P3-P5。5.2 海面专属数据增强策略表增强类型参数设置物理意义适用场景RandomPerspectivedegrees0, translate0.1, scale0.5, shear0, perspective0.0001模拟无人机俯仰角变化航拍图像视角扰动HSVhgain0.015, sgain0.7, vgain0.4强化饱和度/明度突出油膜反光阴天低对比度图像Blurksize3模拟运动模糊增强鲁棒性无人机高速巡检Grayscalep0.01极低概率转灰度防过拟合多光谱传感器兼容CutOutp0.5, nholes2, length32随机遮挡提升局部特征学习油膜被云影部分遮盖启用方式在yolov8n.yaml中augment: true hsv_h: 0.015 hsv_s: 0.7 hsv_v: 0.4 translate: 0.1 scale: 0.5 shear: 0.0 perspective: 0.0001 cutout: 0.55.3 漏检根因定位用Grad-CAM可视化模型注意力热力图当mAP停滞在0.62时需定位模型“看不见”的区域# gradcam_debug.py import torch import torch.nn.functional as F from pytorch_grad_cam import GradCAM from pytorch_grad_cam.utils.image import show_cam_on_image model YOLO(runs/detect/oil_spillage_v8n/weights/best.pt).model target_layers [model.model[-2].cv2.conv] # YOLOv8的最后卷积层 cam GradCAM(modelmodel, target_layerstarget_layers, use_cudaTrue) rgb_img cv2.imread(images/0042.jpg)[:, :, ::-1] / 255.0 input_tensor torch.tensor(rgb_img.transpose(2,0,1)[None]).float().cuda() grayscale_cam cam(input_tensorinput_tensor) heatmap show_cam_on_image(rgb_img, grayscale_cam[0], use_rgbTrue) cv2.imwrite(gradcam_0042.jpg, heatmap[:, :, ::-1])解读方法若热力图集中在船体、云朵等干扰物而非油膜区域说明模型学到错误特征需加强背景抑制如添加MosaicMixUp组合若热力图覆盖油膜但强度弱则需调整损失函数权重增大box_loss系数。本文还有配套的精品资源点击获取
返回列表