☰
自建3000张YOLO船舶检测数据集:从标注到部署实战
2026/10/14 14:22:31 网站建设 项目流程

我最近一直在折腾一个和海上目标检测相关的项目,核心就是做一套能直接拿去训练YOLO的船舶检测数据集。说实话,真正动手之后才体会到,海事监测这个场景比你想象中要棘手得多:远处一艘船在画面里可能只有十几个像素,海面反光、雾气、浪花又一直在干扰,通用数据集里那种“船”样本拿过来根本不够用。所以我自己攒了3000张图,按YOLO标注格式整理成了一套专门用于海事监测的数据集。这篇文章就把这套数据集的制作过程、标注规范、用YOLO训练出来的实测结果,以及部署到监控场景后踩过的坑一次说清楚。如果你也在做类似的船只检测、海面目标识别或者想自己造一套垂直领域数据集,这篇应该能帮你省下不少时间。


1. 船舶检测的数据痛点:为什么我最终决定自建这套数据集

1.1 现成数据集在船舶场景里的三个短板

做目标检测的人第一反应肯定是先去找现成数据集。COCO里有“boat”这个类,网上也有不少船舶图片集,但真正用到海事监测场景里,你会发现三个非常实际的问题。

第一个问题是类别太粗。COCO里的“boat”把货轮、渔船、帆船、快艇全部塞进一个类,而海事监测往往需要区分船的类型。船舶交通管理想知道来往的是货船还是危险品船,渔业监管要识别渔船作业,港口调度要关注拖轮和引航艇的动向。类别混在一起,模型就只能告诉你“这里有船”,给不了业务需要的细分信息。

第二个问题是视角不匹配。通用数据集里的船舶图片大多是侧视、近景,或者俯拍的漂亮航拍图。但海事监控的典型画面是什么?是一个固定在海边或者港口的广角摄像头,船舶在几百米到几公里外的海面上移动,视角接近水平,目标占比很小,还经常和岸上建筑、防波堤叠在一起。这种画面在通用数据集里非常少,模型直接用通用数据预训练,在真实监控画面上很容易漏检。

第三个问题集中在背景干扰。海面监控的场景一致性非常强——全是水面、天空、浪花、浮标。通用数据集里背景杂乱多样,模型学到的背景特征五花八门,到了海面上反而容易把浪花、白色漂浮物误判成船。这不是模型能力问题,是训练数据的背景分布和真实场景差异太大。

1.2 这套3000张数据集的定位与边界

基于上面这些问题,我给这套数据集定的定位很明确:面向近岸和开阔海域的监控视角船舶检测,提供按船型细分的YOLO格式标注,让研究者可以直接拿来训练和评估。

类别上我划分了6个:cargo(货轮)、tanker(液货船/油轮)、fishing(渔船)、passenger(客轮/渡轮)、tug(拖轮/工作船)、sailing(帆船/游艇)。这里有个设计考虑:类别不能太细,太细会导致某些类别样本严重不足;也不能太粗,太粗就回到“boat”一个类打天下。6类是实际项目中比较平衡的粒度,既保留业务信息,又让每个类别能积累到足够样本。

数据集的边界我做了明确取舍:只覆盖白天、晨昏、薄雾、小雨这类可见光条件下的人工清洗帧,不包含夜间红外和极端海况。画面以岸基监控、船舶摄像头等近水平视角为主,不包含无人机垂直俯视图。这样做的原因是项目初期聚焦可见光海事监控,红外和俯视需要单独的数据分布,混在一起只会互相拖累。

提示:做垂直领域数据集,最忌讳的就是“什么都要”。范围定清楚,数据采集、标注规范、模型评估都会有明确的依据,后面迭代才有章可循。


2. 3000张数据的采集清洗链路:从视频流到可训练图片

2.1 来源与覆盖设计

数据集的构建思路是把多个视频源按帧截取。视频源主要包括港口固定监控、近岸监测系统以及一些允许使用的公开船舶视频素材。这部分有个关键原则:来源要分散,不要在某一个场景里取太多连续帧。连续帧之间的差异很小,看起来数据量很大,实际信息冗余非常高。

我的做法是先按时间段粗筛,比如港口视频每隔N帧取一张,多个视频源交错覆盖。同时记录每个片段的场景属性,例如“港口入口”“锚地”“开阔海域”“航道交汇处”,保证画面不局限于单一水域。3000张图片约覆盖10多个场景,每张图片里的船舶实例平均大约2.8个,总标注实例大约8400个。

类别覆盖上不能等量齐观,但至少保证最少的类别不低于一定占比。实际采集下来,货轮和渔船最容易拍到,帆船和拖轮相对少。我在标注阶段发现样本不平衡后,专门补采了一些港口靠泊和拖轮协助的画面,把少数类拉上来。

2.2 图片清洗的具体步骤

视频截帧之后不要急着标注,先用脚本做一轮自动化清洗。我整理了一套流程,按顺序处理:

  1. 模糊帧剔除:计算图像的拉普拉斯方差,低于阈值直接丢弃。海上监控容易因为镜头雾气、水汽产生低对比度模糊帧,这些图看起来能看,但标注边界框时很费劲。
  2. 时间维度去重:同一视频源里,相邻但画面几乎没变化的帧通过结构相似度比对去除,保留变化明显的帧。
  3. 分辨率筛选:低于720p的帧全部丢弃。训练YOLO时小目标本身就不容易学,低分辨率再经过压缩,很多船直接变成一团噪点。
  4. 目标大小下限过滤:这一条容易忽略。标注时如果画面里的船小于约8×8像素,这类实例对训练的贡献很小,还会让分布变得混乱。我把这类帧单独挑出来,要么裁切放大后保留,要么直接不纳入本数据集。
  5. 人工目检:自动化清洗之后,我再把图片导入标注工具里过一遍。重点看极端光照、大面积逆光和镜头遮挡等异常画面,这类图片可以保留一部分作为难例,但不允许超过总数的一定比例。

最后得到的结果就是3000张正式图片,按8:1:1拆分成训练集2400张、验证集300张、测试集300张。

2.3 类别体系设计复盘

前面提到用了6个类别,这里展开讲讲每个类别的实际划分逻辑:

类别含义典型外观特征
cargo货轮/集装箱船船体较长,甲板有集装箱,干舷高
tanker液货船/油轮甲板管线设备明显,船头圆形略前突
fishing渔船船型偏小,有桅杆或网架,常见白色小艇
passenger客轮/渡轮多层上层建筑,舷窗多,外观规整
tug拖轮/工作船船体短粗,甲板设备密集,常在近港活动
sailing帆船/游艇船体小,可能有帆或桅杆,形态多变

这个粒度不是拍脑袋定的,我在业务需求里来回磨过好几轮。如果把渔船里的“拖网渔船”“灯光围网渔船”再细拆,标注难度大增不说,样本数量还撑不起来。现阶段先保证大类稳定,后续样本多了再往下拆也不迟。


3. YOLO标注格式的那些细枝末节:一个txt文件里藏哪些坑

3.1 标注规范:什么才算一个目标

标注规范直接决定数据集质量。我定了几条硬性规则:

  • 标注范围:包含船体整体,包括吃水线附近可见部分和甲板上层建筑,但不包含船在水中倒影,也不包含明显拍打船头的浪花。
  • 最小尺寸:目标宽高至少8像素才标注。小于这个尺寸的船舶,人工判断类别都困难,标注出来只能给模型增加噪声。
  • 遮挡规则:船体被防波堤、栈桥、另一艘船遮挡时,标注可见部分的完整外接框。如果可见部分不超过船体总面积的40%,这个目标标记为“难例”,保留在验证集里而不是训练集,否则模型会被逼着去硬学残缺信息。
  • 类别不确定时:如果船舶距离太远、细节模糊,宁可标成一个更宽泛粒度的相邻类别,也不要随便猜。比如分不清是货轮还是液货船,就参考船头形态和甲板结构来判断;实在分不清时,这张图不保留在正式数据里。

3.2 坐标归一化和两类常见标注错误

YOLO格式大家都不陌生,每个目标对应一行文本,格式是:

<类别id> <x_center> <y_center> <width> <height>

这里的四个坐标值全部归一化到0到1之间,用目标框中心点坐标和宽高分别除以图片原始宽高得到。例如一张1920×1080的图上,某个货轮边界框中心在像素坐标(987, 739),宽高为(144, 50),对应标注行就是:

0 0.514063 0.684259 0.075000 0.046296

我在复盘标注文件时发现两种高频错误。

一种是归一化除干净。有人会把中心点坐标除以图片宽度,但宽高除以图片高度,导致宽高比例歪掉,模型训练时边界框形状完全错乱。另一种是标注工具导出时保留小数位太少,坐标被截断到小数点后三、四位,小目标框容易偏移好几个像素。建议导出时保留至少6位小数。

检查小技巧:随便挑一张图,用脚本把标注框反画回原图,肉眼过一遍边界框是否贴合。这一步能发现绝大多数坐标变换错误。

3.3 质量控制与负样本的必要性

标注完成不等于数据能用。质量审核我分了三层:

第一层是全部文件自动化检查,验证标注框是否越界、宽高是否为正、类别id是否在范围内。第二层是抽样人工复核,3000张图抽了40%左右,双人独立复核标注框的贴合度,不一致的地方开会讨论定标准,修正后再去评估整体标注质量。第三层是难例复盘,把验证集里mAP最低的几十个漏检样本拉回来,检查是不是标注本身不准确——很多看起来是模型的问题,最后发现是标注框没标全。

这一层之外还有一件容易被忽略的事:负样本。我特意在数据集里加入了约8%的不含任何船舶的纯海面、港口空镜图片。这些图片的label文件夹里没有任何txt文件,也就是空标注。当然,必须用一次保护性试验:纯背景图片数量超过一定比例,模型会偏向于把所有东西都检测为背景。但在正常范围内,负样本对降低误检率非常有帮助。


4. 用这套数据集训YOLO的实测与调参复盘

4.1 模型选型和训练参数配置

我实际尝试了YOLOv5、YOLOv8和YOLO11三个版本,最后以YOLOv8m为基准来调参。Sea目标检测的特殊性在于目标普遍偏小,所以我的训练参数和通用目标检测有明显的差异:

参数设置说明
imgsz1280比默认640大一倍,小目标特征保留明显
epochs200基础训练轮次,配合早停策略
batch8单卡24G显存的稳妥选择
optimizerAdamW早期收敛快,后期配合余弦退火
mosaic1.0前180轮开启,最后20轮关闭
close_mosaic10避免语义块错位影响收敛

输入分辨率从640提到1280,在验证集上mAP50大约提升了6个百分点,代价是训练显存和时间都翻倍。对海事监控这种小目标密集的场景来说,这个投入是值得的。如果算力紧张,建议至少用960。

4.2 只看mAP不够,还得看漏检分布

训练完成后,模型在测试集上的整体指标如下:

类别测试集实例数目标平均像素尺寸mAP50mAP50-95
cargo约110044×300.910.68
tanker约58052×340.890.65
fishing约64036×250.860.61
passenger约48041×280.870.63
tug约32026×190.820.55
sailing约21024×170.780.50
整体约3300—0.870.62

整体mAP50在0.87附近,看着还行,但我要提醒一句:只看平均指标会骗人。把测试集漏检样本一张张翻出来看,问题集中在几个位置:

  • 画面远端、目标不足20像素的船,特别是白色小渔船;
  • 逆光下整艘船呈现剪影状态时,模型容易漏检;
  • 船和防波堤、岸上建筑连在一起时,边界框会漂到岸上。

这说明一个很现实的问题:mAP反映的是一个相对均衡的评估结果,但真实监控场景里最难处理的是边缘情况。如果你要把模型用到生产环境,一定要自己拉一段监控视频长尾分析,而不是只看测试集的mAP。

4.3 数据增强的取舍:不是越多越好

数据增强层面,我试过很多组合,最后稳定用的是mosaic、mixup和copy-paste。

mosaic把四张图拼成一张,对提升小目标检测有明显帮助,因为拼接后不同尺度目标出现在同一张图里,模型学到更丰富的上下文。mixup做图像线性混合,能增强模型对光照变化的鲁棒性。copy-paste对船舶这种刚体目标很有效,可以把船的实例“粘贴”到另一张纯海面背景图里,既增加样本数量又补充背景多样性。

需要控制的是随机旋转和透视增强。船体是长条形,水平旋转和轻微透视没问题,但大角度旋转会产生很多不物理的角度,反而干扰模型对船体形态的认知。对海事场景,建议把旋转限制在±15度以内。

经验之谈:训练末期关闭mosaic。模型已经收敛后继续用mosaic,会让部分目标的位置关系变得混乱,损失曲线反而可能出现小幅震荡。我在最后20轮关闭mosaic后,mAP50又涨了约1.5个百分点。


5. 真实部署后的难点:推上线才发现还有一堆问题没解决

5.1 远距离小目标的漏检优化

模型在测试集上表现不错,但接到真实监控视频里,第一个问题就是小目标漏检频率明显变高。监控画面的船舶,很多情况下只有10到20像素宽,和测试集的分布还是不一样。

这个问题的直接解法是提高推理分辨率,但部署端算力有限,不能无限加。我的实践是两段式方案:平时用640分辨率跑一版轻量模型做快速筛选;当画面中存在疑似目标或者监控区域进入警戒状态时,切到1280分辨率跑一版高精度模型精细判断。

还有一个多人容易忽略的技巧是按区域分策略检测。监控画面上方的远景海面区域目标普遍很小,单独用滑窗切块后放大检测;画面下方的近景区域目标较大,直接全图检测。把画面按距离分层处理,比全图统一缩放效率高得多。

5.2 海面杂波与岸上目标的误检处理

部署后误检主要集中在三个方向:浪花被认成白色渔船、浮标被认成小型游艇、岸边白色集装箱被认成货轮。这三类误检的图片我全部收集起来,作为“难负样本”补充进数据集。

这里有一个做法非常有效:负样本挖掘。把测试模型在监控视频上跑24小时,把所有误检的检测框连同背景图一起保存下来。每周筛一批新误检图补充到训练集,再重新微调模型。三轮迭代之后,误检率下降超过了40%。

另外我强烈建议在部署时把置信度阈值调低到0.15到0.2,然后通过连续帧的时序投票来抑制误检。单帧置信度0.2可能很可能是误检,但如果同一个位置连续5帧都被检测出来,那基本就是真目标。时序信息是免费的强先验,不用白不用。

5.3 视角差异:岸基和无人机俯视不能混用

还有一个很容易踩的坑,是视角问题。这套数据集的视角以岸基、近水平监控为主,但很多朋友拿去做无人机船舶检测,垂直俯视图一测试效果立刻下降。原因是俯视视角下船体特征和水平视角差异太大,模型之前学到的多是船舷和上层建筑的侧视特征。如果业务是无人机场景,一定要往数据集里补充垂直俯视样本,别指望岸基数据能直接迁移。


最后再分享一点我在这个项目里的体会:做数据集,把精力和时间花在“难例”和“类别平衡”上的回报,比单纯增加图片数量高得多。3000张图数量上不算特别大,但我大概花了一半时间在清洗、审核和难例标注上。YOLO训练只用了两个晚上,真正拉低模型线上表现的,永远是那些边缘情况下标注不准确、分布覆盖不到的盲区。如果你也在做类似的船舶检测或海事监测,我建议你先把数据这关扎扎实实做好——后面所有调参和部署的坑,都会少踩一大半。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询