ARTICLE DETAIL

资讯详情

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

船舶识别数据集驱动采砂检测:从标注映射到YOLO训练落地

船舶识别数据集驱动采砂检测:从标注映射到YOLO训练落地 简介这份船舶识别数据集面向计算机视觉与智能监控方向的开发者、算法工程师及环境监管研究人员用于训练和测试采砂监控场景下的船只检测模型。数据集共包含3016张船舶图像以JSON格式完成标注图像尺寸不统一多数为800×240像素标注类别覆盖大型船只、小型船只、巨型船只和中型船只四类可支撑目标检测模型的训练与验证。资源包为zip格式共2000个文件其中1841个jpg、158个png图像文件及1个json标注文件整体约228.85MB图像文件用于模型输入json文件承载标注信息。目前已有155人学习下载。借助该数据集读者可快速搭建采砂船只识别实验环境理解多尺度船舶目标的标注组织方式并基于四类船只标签训练检测模型为非法采砂监控、航道安全监管等应用提供数据基础与验证支撑。1. 船舶识别数据集与采砂检测从数据到落地的关键一步内河与近海非法采砂的监管长期面临一个尴尬现实雷达能发现“有船”却分不清是运砂船、采砂船还是普通货船更判断不出它是否正在作业。船舶识别数据集正是为解决这个“看得见、认不出”的问题而生——它把船舶目标检测所需的大量标注图像打包成可直接训练的数据集专门服务于采砂检测这类场景。你拿到的不是一份泛泛的通用检测数据而是围绕船舶类别、船体姿态、作业状态构建的样本集合。适合谁用做水利监管算法、港口安防、遥感船舶检测的工程师以及需要快速验证采砂船识别方案的技术团队。这一章先把“数据集到底解决什么、为什么采砂检测离不开它”讲清楚后面再拆怎么用、参数怎么调、坑在哪。采砂检测的核心难点不在“检测船”而在“区分作业行为”。普通货船和采砂船在可见光图像里外形接近真正的差异藏在船体附属结构、作业时的位置分布、以及是否伴随抽砂管、传送带等特征。船舶识别数据集如果只标注了“ship”一个类别那对采砂检测几乎没有直接价值只有当数据集包含采砂船、运砂船、普通货船等细分标签或者至少包含能区分作业状态的标注时它才真正可用。这也是为什么很多团队拿到公开船舶数据集后第一件事不是直接训练而是先做标签映射和类别裁剪。从落地路径看船舶识别数据集的使用通常分三步先确认标注格式与类别体系再根据采砂检测需求做类别合并或重映射最后接入检测模型训练并针对小目标、水面反光、船体遮挡做专项调优。这三步里第一步决定数据能不能用第二步决定模型学什么第三步决定实际部署效果。很多项目翻车不是模型不行而是数据集类别和业务目标错位——比如用只标了“船”的数据集去训采砂船识别模型学到的只是“有船”根本分不出作业类型。提示拿到任何船舶识别数据集先看标注文件和类别列表不要急着跑训练脚本。类别体系不对后面全是白工。2. 船舶识别数据集的标注体系与采砂检测的类别映射2.1 常见标注格式与采砂检测的适配关系船舶识别数据集常见的标注格式有 VOC XML、COCO JSON、YOLO TXT 三种。VOC 和 COCO 通常带图像尺寸、边界框坐标和类别名YOLO TXT 则是归一化后的中心点加宽高。采砂检测场景下我一般优先选 COCO 或 YOLO 格式因为后续要接的检测模型大多是 YOLO 系列或基于 COCO 预训练权重做迁移格式统一能省掉大量转换脚本的调试时间。但格式只是表层真正影响采砂检测的是类别粒度。公开船舶数据集里类别体系大致分三档第一档只有“ship”一个类第二档区分货船、渔船、客船、采砂船等船型第三档还会标注“作业中/非作业中”或“有抽砂设备/无抽砂设备”。采砂检测至少需要第二档最好有第三档。如果只有第一档你得自己补标注或找辅助数据否则模型无法区分采砂船和普通货船。下面是一个典型的类别映射脚本把 VOC 格式的船舶数据集转成采砂检测可用的 YOLO 格式并做类别裁剪import xml.etree.ElementTree as ET import os # 原始类别到采砂检测类别的映射 # 只保留采砂船和运砂船其余归为普通船只或丢弃 CLASS_MAP { sand_dredger: 0, # 采砂船 sand_carrier: 1, # 运砂船 cargo_ship: 2, # 普通货船 fishing_boat: 2, # 渔船归为普通船只 passenger_ship: 2, # 客船归为普通船只 } def voc_to_yolo(xml_path, img_w, img_h, out_path): tree ET.parse(xml_path) root tree.getroot() lines [] for obj in root.findall(object): name obj.find(name).text.strip() if name not in CLASS_MAP: continue # 丢弃与采砂检测无关的类别 cls_id CLASS_MAP[name] 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) # 转成 YOLO 归一化格式中心点 x,y 和宽高 w,h cx (xmin xmax) / 2.0 / img_w cy (ymin ymax) / 2.0 / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h lines.append(f{cls_id} {cx:.6f} {cy:.6f} {w:.6f} {h:.6f}) with open(out_path, w) as f: f.write(\n.join(lines))这段脚本的关键在CLASS_MAP它决定了哪些原始类别被保留、哪些被合并、哪些被丢弃。采砂检测里采砂船和运砂船必须独立成类普通货船可以保留作为负样本参考但不要和采砂船混在一起。img_w和img_h必须从对应图像读取不能硬编码否则归一化坐标全错。输出文件每行一个目标格式是类别 id 中心点 宽高这是 YOLO 训练的标准输入。2.2 采砂船与普通货船的标注边界怎么定标注边界是采砂检测数据集里最容易扯皮的地方。采砂船和普通货船在远距离图像里都是“长条形水面目标”如果标注员只凭轮廓判断很容易把运砂船标成采砂船。我的经验是定三条硬规则第一看船体是否有抽砂管、传送带、抓斗等作业结构第二看船位是否长期停留在采砂区或砂石码头附近第三看 AIS 轨迹是否呈现低速往复或定点作业特征。图像标注只能覆盖前两条第三条需要融合 AIS 数据做后处理。如果数据集本身没有细分到采砂船只有“ship”标签那采砂检测就不能直接端到端训练。常见做法是先用通用船舶检测模型做第一级筛选再对检测到的船体做第二级分类第二级分类器用少量采砂船正样本和普通货船负样本训练。这种两级方案对数据集要求低但推理延迟会增加适合对实时性要求不高的监管场景。注意类别映射一旦确定训练集、验证集、测试集必须用同一套映射不能训练时合并、验证时又拆开否则指标完全不可信。3. 用船舶识别数据集训练采砂检测模型的完整流程3.1 数据划分与采砂场景的样本均衡船舶识别数据集直接按 8:1:1 随机划分在采砂检测里往往效果很差。原因是采砂船样本通常远少于普通货船随机划分会导致验证集里采砂船极少mAP 看起来高但实际漏检严重。我一般按类别分层抽样先统计每个类别的图像数再按比例分配到训练集、验证集和测试集确保采砂船在三个集合里都有足够样本。import os import random from collections import defaultdict def split_dataset(label_dir, img_dir, train_ratio0.8, val_ratio0.1): # 按类别分层先统计每张图包含哪些类别 img_classes defaultdict(list) for label_file in os.listdir(label_dir): if not label_file.endswith(.txt): continue img_name label_file.replace(.txt, .jpg) classes set() with open(os.path.join(label_dir, label_file)) as f: for line in f: cls_id int(line.split()[0]) classes.add(cls_id) for cls_id in classes: img_classes[cls_id].append(img_name) train, val, test [], [], [] for cls_id, imgs in img_classes.items(): random.shuffle(imgs) n len(imgs) n_train int(n * train_ratio) n_val int(n * val_ratio) train.extend(imgs[:n_train]) val.extend(imgs[n_train:n_train n_val]) test.extend(imgs[n_train n_val:]) # 去重同一张图可能包含多个类别 train list(set(train)) val list(set(val)) test list(set(test)) return train, val, test这段代码的核心是img_classes字典它记录每个类别出现在哪些图像里然后按类别分别划分。这样采砂船不会因为数量少而被随机分到一边。train_ratio和val_ratio可以根据采砂船样本量调整如果采砂船特别少验证集比例可以降到 0.05把更多样本留给训练。3.2 YOLO 训练配置与采砂检测的关键参数采砂检测模型我一般选 YOLOv8 或 YOLOv9因为对小目标和遮挡场景的改进比较明显。训练配置文件里有几个参数直接决定采砂船能不能被检出来参数推荐值作用imgsz640 或 1280输入分辨率采砂船在图像里通常较小1280 更稳batch8 或 16根据显存调整太小会导致 BN 层不稳定epochs100 到 300采砂船样本少时需要更多轮次收敛lr00.01初始学习率配合余弦退火mosaic1.0马赛克增强提升小目标检测mixup0.1混合增强防止过拟合copy_paste0.3复制粘贴增强对采砂船这类少样本类别很有效训练命令示例yolo detect train \ dataship_sand.yaml \ modelyolov8m.pt \ imgsz1280 \ batch8 \ epochs200 \ lr00.01 \ mosaic1.0 \ mixup0.1 \ copy_paste0.3 \ device0ship_sand.yaml里要写清楚训练集、验证集路径和类别名。copy_paste对采砂检测特别有用因为它能把采砂船实例复制到不同水面背景上增加样本多样性。但copy_paste不能开太大超过 0.5 会导致背景失真模型学到不真实的纹理。3.3 采砂检测的推理后处理与告警逻辑模型输出只是边界框和类别采砂检测还需要后处理判断“是否在作业”。我一般加两层逻辑第一层是类别置信度过滤采砂船置信度低于 0.5 的直接丢弃第二层是时序关联同一位置连续多帧检测到采砂船才触发告警避免单帧误检。from collections import deque class SandDredgerTracker: def __init__(self, max_len10, threshold3): self.history deque(maxlenmax_len) self.threshold threshold # 连续多少帧检测到才告警 def update(self, detections): # detections: list of (cls_id, conf, x, y, w, h) has_dredger any(d[0] 0 and d[1] 0.5 for d in detections) self.history.append(has_dredger) if sum(self.history) self.threshold: return True # 触发采砂告警 return Falsemax_len控制历史窗口长度threshold控制触发灵敏度。内河监管场景下我一般设max_len10、threshold3既能抑制单帧误报又不会漏掉短暂出现的采砂船。如果摄像头帧率低max_len要相应调大。4. 采砂检测落地中的避坑与排查记录4.1 水面反光导致采砂船漏检现象模型在晴天正午的图像上漏检率明显升高采砂船被水面高光淹没。原因是水面镜面反射改变了船体边缘的梯度特征卷积核学到的边缘响应被削弱。解决方式是在训练集里加入不同光照条件的样本同时用 HSV 变换做颜色增强把亮度通道的对比度拉高。推理阶段可以加一个简单的预处理对图像做 CLAHE 自适应直方图均衡再送入模型。4.2 类别映射后采砂船样本归零现象按脚本做类别映射后训练集里采砂船样本数变成 0。原因是原始数据集的类别名和CLASS_MAP里的键不一致比如原始标注写的是dredger而不是sand_dredger。解决方式是先跑一遍类别统计脚本打印所有唯一类别名再对照映射表逐项确认。不要凭记忆写映射键。4.3 验证集 mAP 高但实际漏检严重现象验证集 mAP0.5 达到 0.85但实际视频里采砂船经常检不到。原因是验证集和训练集来自同一批图像分布太接近且采砂船样本在验证集里占比过高。解决方式是单独构建一个“困难验证集”专门放远距离、遮挡、反光、模糊的采砂船图像用这个集合评估模型真实能力。4.4 小目标采砂船在 640 分辨率下消失现象采砂船在图像里只有几十个像素640 分辨率训练后完全检不到。原因是下采样过程中小目标特征被池化层抹掉。解决方式是把imgsz提到 1280或者在模型里加 P2 小目标检测层。YOLOv8 可以通过修改配置文件增加 P2 层但计算量会上升需要权衡。4.5 推理时采砂船和运砂船混淆现象模型把运砂船大量误判为采砂船。原因是两类船在图像上高度相似且训练集里运砂船样本不足。解决方式是增加运砂船负样本或者在损失函数里对采砂船类别加权让模型更关注采砂船的特征差异。也可以引入船体长度、宽长比等几何特征做后处理过滤。提示避坑记录里的每一条都来自实际项目不是理论推演。遇到类似现象时先按“现象→原因→解决”逐条对照不要一上来就换模型。5. 采砂检测数据集的进阶用法与验证技巧5.1 用 AIS 数据做弱监督标注补全船舶识别数据集通常只有图像标注没有 AIS 轨迹。采砂检测里AIS 能提供船位、航速、航向这些信息可以用来做弱监督标注把 AIS 轨迹和图像时间戳对齐如果某艘船在采砂区低速往复就自动给它打上“疑似采砂”的软标签。软标签不直接参与检测损失而是作为分类头的辅助监督能显著提升采砂船识别准确率。import pandas as pd def align_ais_to_image(ais_df, img_time, img_bbox, time_window60): # ais_df: 包含 mmsi, timestamp, lat, lon, speed, course # img_time: 图像时间戳 # img_bbox: 图像中检测到的船体边界框 window ais_df[ (ais_df[timestamp] img_time - time_window) (ais_df[timestamp] img_time time_window) ] # 筛选低速目标航速低于 3 节可能是采砂作业 slow_ships window[window[speed] 3.0] if len(slow_ships) 0: return 1 # 软标签疑似采砂 return 0time_window控制 AIS 和图像的时间对齐窗口内河场景一般设 60 秒。speed 3.0是采砂作业的典型航速阈值但不同水域可能不同需要根据当地数据调整。这个方法的局限是 AIS 覆盖不全很多小型采砂船不装 AIS所以只能作为辅助手段。5.2 模型验证用混淆矩阵定位采砂船误判训练完模型后不要只看 mAP。采砂检测必须看混淆矩阵确认采砂船和运砂船、普通货船之间的误判比例。YOLO 训练结束后会输出confusion_matrix.png重点看采砂船那一行如果采砂船被大量判成运砂船说明两类特征区分度不够需要增加运砂船负样本或调整类别权重。我一般还会做一个“采砂船专项测试集”只包含采砂船图像统计召回率。召回率低于 0.8 就不建议上线因为漏检一艘采砂船可能意味着一次非法作业没被记录。精确率可以适当放宽误报可以通过人工复核过滤但漏检没有后悔药。5.3 一个具体技巧用切片推理提升小目标召回采砂船在广角监控里往往只占几十个像素直接推理容易漏。我的习惯是用 SAHI 切片推理把大图切成重叠的小图分别检测后再合并结果。这样小目标在切片里变成大目标召回率能提升 10 到 20 个百分点。代价是推理时间增加适合离线分析或对实时性要求不高的场景。from sahi import AutoDetectionModel from sahi.predict import get_sliced_prediction detection_model AutoDetectionModel.from_pretrained( model_typeyolov8, model_pathbest.pt, confidence_threshold0.3, devicecuda:0 ) result get_sliced_prediction( test.jpg, detection_model, slice_height640, slice_width640, overlap_height_ratio0.2, overlap_width_ratio0.2 )slice_height和slice_width根据采砂船在图像里的典型尺寸设定一般取 640。overlap比例设 0.2 能避免切片边界处的目标被切断。切片推理的合并逻辑会自动做 NMS不需要手动处理。这套方案我从数据映射一路做到切片推理踩过的坑基本都写在上面了。采砂检测不是训一个模型就完事数据集的类别体系、验证集的构建方式、后处理的时序逻辑每一环都影响最终能不能真正抓到非法采砂。如果你手头的数据集只有“ship”一个类别硬上先补标注或走两级方案。希望帮到你。本文还有配套的精品资源点击获取
返回列表