
搞机器视觉检测这几年我最大的体会就是模型选型永远不是越新越好而是越贴合场景越好。这次想认真聊聊我做过的YOLO船舶识别项目属于很典型的水面目标检测任务——用YOLO系列模型从监控视频或图像里自动圈出船只位置、给出类别和置信度常见于航道监控、港区管理、海上搜救、渔业监管这类场合。说实话船舶识别和通用的行人检测、车辆检测比起来坑更多远距离目标太小、水面反光强烈、海雾雨雪天气频繁、船只姿态角度差异大而且一旦漏检可能就是安全事故。这篇文章我会按项目推进的顺序把数据集怎么攒、标注怎么做、模型怎么选、参数怎么调、训练怎么盯、部署怎么落完整讲一遍。适合有基础的目标检测初学者也适合已经跑了几个通用检测项目、想往行业场景转型的工程师。1. 项目概述与核心需求解析1.1 船舶目标检测到底在解决什么实际问题很多人以为船舶识别就是把图里的船框出来真做起来会发现甲方要的远不止这个。一个港口或者一条航道的监控体系里核心诉求通常是三种一是违规船舶闯入禁航区、危险水域时的告警二是对航道内船舶流量做统计为调度提供数据三是搜救场景下快速发现落水人员附近的船只或无人救生艇。第一种场景要求低漏报、快速响应第二种要求计数准确、能长期稳定运行第三种要求极高召回率宁可多报也不能漏报。这些诉求直接决定了模型评估指标的选择。通用检测比赛喜欢看mAP50-95但业务落地时很多场景里召回率、误报率、单帧推理耗时、连续跟踪稳定性这些指标反而更关键。做项目要先弄清楚这一点否则训练阶段死磕mAP部署后甲方照样不满意。1.2 模型的输入输出与业务约束从技术角度拆解YOLO船舶识别模型的输入通常是单帧图像训练时统一缩放到640×640或更大分辨率输出是若干组检测结果每组包含边界框坐标、类别、置信度。但到真实系统里模型只是中间一环前面接视频解码、抽帧后面接目标跟踪、告警规则、数据入库。船舶识别的特殊约束在于运行环境。岸基摄像头常年风吹日晒画面里会有波浪反光、桥梁阴影、岸边杂树晃动海面监控还会遇到逆光、海雾、夜间红外成像等极端条件。模型不光要在干净的数据集上准更要在这些恶劣条件下维持稳定这就倒逼我们在数据集构建阶段就要把恶劣场景当成一等公民来对待而不是事后补救。2. 数据集准备与标注质量把控2.1 数据来源与采集策略我见过很多项目死在数据上模型结构没问题训练参数也没问题就是识别效果忽好忽坏最后排查下来全是数据集分布偏差引起的。船舶识别项目的数据来源一般是两条腿走路公开数据集打底自采数据补齐场景。公开数据集可以解决有没有的问题但覆盖的场景往往偏理想天气好、目标大、画面干净。真实项目里必须自己做补充采集。我当时给某航道管理单位做模拟项目X时花了将近两周从不同点位、不同时段的监控录像里截取样本筛选原则有三条天气维度要覆盖晴天、阴天、雾天、雨天、夜间红外至少五类距离维度要保证远、中、近三个尺度都有充足样本远处小目标至少占三成角度维度要尽量覆盖船艏、侧舷、船尾不同朝向。在这里要多说一句远距离小目标样本不足是船舶检测项目里最常见的坑。很多标注者习惯挑清晰的、大的目标来标导致模型在小目标维度上严重偏科。我后来在采集阶段就加了硬性要求每批新增数据里目标宽度在原图占比低于5%的样本不得少于20%。2.2 标注规范与YOLO的标签格式标注是整个流程里最枯燥但最重要的环节。YOLO系列使用的标签格式是归一化的中心点坐标加宽高一行一个目标格式为类别id x_center y_center width height其中x_center、y_center、width、height都是除以图片宽高后的归一化值范围在0到1之间。比如一张1920×1080的图里某艘船边界框左上角在(500, 260)、右下角在(760, 480)那么中心点就是(630, 370)宽高为(260, 220)归一化后这一行标签就是0 0.3281 0.3426 0.1354 0.2037。标注时有几个细节特别容易出错。第一个是船尾浪花要不要框进去我的经验是不要浪花的形状会随着船速变化把浪花框进去会污染目标真实轮廓尤其是小目标框大了会影响IoU计算。第二个是紧挨着的多条船边界框可以有轻微重叠但不要为了框住两艘船而把中间水域也圈进去这会让特征学习混乱。第三个是锚泊船和航行船的区分如果业务需要就要分成两个类别训练前先想清楚类别体系不要训练到一半再改标签。2.3 数据增强与分布均衡数据增强是弥补场景覆盖不足的核心手段。YOLO训练时默认会开启马赛克增强把四张图拼在一起训练这对提升小目标检测和上下文理解特别有效。除此之外我针对水面场景额外加了三种增强亮度对比度扰动、高斯噪声模拟雨天、随机的水平翻转。亮度对比度扰动要做得比通用场景更重一些因为水面反光和太阳角度变化导致同一个机位不同时刻的光比差异非常大。高斯噪声增强要适度太强容易让模型学到去噪而不是找船一般sigma取5到15就够。水平翻转对船舶识别基本无损因为船的左右对称性很强除非你的业务要区分船艏朝向那就要谨慎使用了。类别均衡的问题也要重视。货船、渔船、客船这类样本量悬殊时最简单的做法是设置类别权重小众类别在采样时提高概率更彻底一些的做法是用扩充数据来拉齐比如专门去采集某类小渔船的素材。我当时用后者效果比调权重稳定得多。3. 模型选型与YOLO版本对比3.1 不同YOLO版本的取舍逻辑YOLO系列从诞生到现在迭代了多个版本每个版本都有明确的设计取向。做船舶识别这类垂直场景我不建议盲目追新而是看几个硬指标易用性、生态成熟度、部署便利性、对目标尺度变化的适应性。从我实际踩坑经验看v5和v8是两个最稳妥的选项。v5的社区资料最多遇到问题搜得到答案网络结构也足够成熟v8做了anchor-free改造检测头设计更简洁对小目标和细长目标的回归更友好训练收敛速度也更快。后面更新的版本在推理效率上有提升数据处理流程也整合得更完善但如果你团队里没人用过学习成本要算进去。3.2 模型尺寸与精度权衡同一个版本下通常有多个尺寸的模型从n到x依次变大。它们的基本区别是骨干网络的深度和宽度参数量和计算量差异很大精度也随之变化。我做过的两个项目对比很明显模型参数量级别单帧CPU单帧GPU典型场景n/s百万级可用极快嵌入式盒子、多路视频并行m/l千万级吃力快单路高清、精度优先x亿级不现实较慢离线批量分析、科研实验嵌入式设备跑多路视频时我建议优先选n或s配合半精度推理实测下来稳定性和速度都能兼顾。服务器端做重点航道单路分析时m和l的精度提升能直接减少误报值得付出算力成本。x级在实时场景里很难落地一般只用来刷离线指标。3.3 迁移学习与预训练权重船舶类别在通用数据集里覆盖稀少但这不代表要从零训练。预训练权重里的低层特征——边缘、纹理、形状轮廓——是通用的船在水面的轮廓、船体的几何结构这些特征都能从预训练骨干网络里继承下来。正确做法是加载预训练权重然后带着少量自己业务数据做全网络微调。如果自己的数据集非常小比如少于几千张可以先用冻结骨干的方式训练前面几十轮让检测头先学会基本输出再解冻全部网络微调。这个策略能有效避免小数据集在小样本场景下的不稳定性我自己在冷启动阶段用这个办法比直接全量微调收敛得更稳。4. 训练环境配置与参数调优4.1 训练环境搭建训练环境这部分不用追求特别豪华一张显存足够的GPU就能跑完中小型数据集。基础配置是深度学习框架、对应的GPU加速库、以及YOLO仓库依赖。pip install torch torchvision pip install -r requirements.txt版本匹配上我吃过亏GPU加速库版本和框架不匹配训练时静默回退到CPU速度慢了几十倍排查了很久才发现是驱动与运行库的版本冲突。建议搭环境时先用一条简单的命令验证GPU是否真的被识别再开始跑训练省得白等半天。4.2 关键超参数解析训练超参数里最核心的是输入尺寸、批大小、学习率和训练轮数。输入尺寸默认640对船舶这种存在大量远距离小目标的任务可以后续提高到960甚至1280小目标召回会有明显提升代价是训练时间和显存占用增加。批量大小决定梯度估计的稳定性一般设成16或32显存不够就调小输入尺寸不要硬扛。学习率设置建议遵循YOLO默认策略初始学习率设0.01左右配合warmup前几轮从0缓慢升上去再按余弦退火逐步降低。权重衰减对防止过拟合有帮助但设太大会让模型学不到细节0.0005是一个比较安全的基准值。训练轮数要看数据规模上万张数据跑到200到300轮几千张跑到150轮左右主要靠早停机制在验证指标不再提升时自动截断。4.3 训练过程中的监控与调优训练不是设好参数就撒手不管了要盯两个关键曲线损失曲线和验证指标。box_loss和cls_loss应该呈现持续下降的趋势如果出现先降后升的拐点排除学习率过高的可能那就是过拟合了需要回退到拐点位置附近保存的权重。验证集上最常见的问题是mAP到了0.8左右就上不去而训练集损失还在降。这时候先看是不是单类别把指标拉低了如果是大船类别很好、小船类别很差说明小目标样本不足优先补数据不要急着改模型结构。改结构是最后手段数据的问题数据解决。我自己的习惯是每轮训练都保存验证集最优权重同时记录每个类别的单独mAP这样能清楚看到瓶颈到底在哪。很多次模型不行的判断最后都变成了某类样本不够的数据问题。5. 训练过程与核心环节实现5.1 数据集目录与配置文件训练前要把数据集整理成YOLO约定的目录结构train和val分开images和labels一一对应dataset/ ├── images/ │ ├── train/ │ └── val/ └── labels/ ├── train/ └── val/然后写一个数据集配置文件声明路径、类别数和类别名train: ./dataset/images/train val: ./dataset/images/val nc: 3 names: [cargo, fishing, passenger]这里有个容易踩的坑标签txt文件里的类别id必须和names里的顺序保持一致否则训练时模型学到的类别语义完全错乱。我曾经因为中途调整了names顺序忘记同步改历史标签导致训练指标看起来正常、实际推理时类别张冠李戴。5.2 训练执行与结果评估单卡训练的命令很简单核心参数按上一节的思路设置python train.py --data ship.yaml --weights yolov8n.pt --epochs 200 --batch-size 32 --img 640 --device 0训练结束后重点看验证集上的这些指标精确率、召回率、mAP0.5、mAP0.5-0.95。它们各自含义不同精确率回答检测出来的目标里多少是对的召回率回答图片里所有船有多少被找到了mAP是综合排序质量的指标。船舶安全监控场景我更看重召回率因为漏掉一艘船可能带来的后果远大于多叫醒一个值班人员。在一个质量良好的船舶数据集上mAP0.5达到0.9以上、mAP0.5-0.95达到0.7以上是比较现实的基线。如果明显低于这个水平优先怀疑数据问题而不是修改网络。5.3 训练过程的关键现象我在训练时观察到一个反复出现的现象验证集召回率在训练早期的提升很快从0.3一路冲到0.8但mAP0.5-0.95上涨缓慢。这其实正常模型先学会找到船再慢慢学习框得更准前者靠检测头后者靠回归头的精调。如果训练后期回调出现明显震荡大多是批量大小太小或者学习率衰减策略不合理。多尺度训练也是一个值得开的选项。YOLO官方实现里可以在每训练批次中随机调整输入尺寸相当于隐式做了尺度增强。船舶识别场景里目标尺度变化极大开多尺度训练通常能让小目标和大目标的表现更均衡代价是训练轮数要适当增加。6. 常见问题与排查技巧实录6.1 小目标与远距离船舶检测不稳定这是船舶识别被问到最多的问题。岸基摄像头视野动辄几公里远处一艘小船在1080p画面里可能只有20×20像素检测头下采样后特征已经非常微弱。解决思路有三个方向。第一个方向是提高输入分辨率这是见效最快的方式。把训练和推理的imgsz从640提到1280小目标召回通常能提升5到10个百分点。代价是推理耗时增加需要在部署时做速度验证。第二个方向是推理时使用切片或分块策略把监控画面切分成多个有重叠的区域分别检测再把结果合并这对超高清大画面尤其有效。第三个方向是采集专门的小目标样本人为把远处船的样本裁剪缩放、贴到多样化背景里增加模型对小这个特征的样本量。6.2 误检与重复检测船舶场景的误检源比较典型波浪被误识别成白色船体、岸边的浮标被当成小船、桥墩阴影形成类船轮廓。YOLO本身的NMS只能消除同一目标的重复框没法处理语义上像船但实际不是的假阳线。我的经验是不要让检测模型单打独斗。把YOLO检测结果接到一个轻量级时序滤波器上比如对每个跟踪轨迹统计连续若干帧的检测置信度稳定出现时才触发告警。航道上漂动的杂物可能被检测为船一两帧但不会有稳定的轨迹这个简单策略能过滤掉大量瞬时误检。重复检测方面降低低置信度框的容忍度、适当提高NMS的IOU阈值是常用操作但要注意别误伤真正贴近并行的船舶。6.3 极端天气与夜间成像退化海雾和暴雨天气会让可见光图像对比度骤降模型会退化得很厉害。我在项目里用过两种策略一是在训练阶段强化天气类数据增强让模型见过足够多的低对比度样本二是在推理前加一个自适应的图像增强预处理比如限制对比度直方图均衡化恢复部分纹理后再送进模型。夜间场景通常有两种传感器选择红外相机或带补光的可见光相机。红外图是灰度单通道与训练的彩色图像分布差异非常大直接在白天模型上跑效果会很差。最稳妥的做法是收集夜间样本单独训练一个分支模型白天用可见光模型夜晚切红外模型部署时根据光照或时间段自动切换。这也是我后来觉得最能落地的方案。7. 部署落地与后续扩展7.1 模型导出与推理加速训练完的模型不能直接拿来上线要先转换成推理引擎。通用流程是把PyTorch权重导出为ONNX格式再针对目标硬件做优化。导出命令大致是python export.py --weights best.pt --include onnx --simplify --half导出后先在验证集上用转换后的模型跑一遍指标对比确认导出没有造成精度损失。ONNX在GPU上可以直接跑但如果追求极致性能可以继续转换成TensorRT格式。半精度推理通常能让速度提升一倍左右精度损失在0.5个百分点以内属于性价比很高的优化。我在嵌入式设备上实测s级模型半精度推理在1080p画面下能达到实时处理的要求而且温度控制比全精度跑更好。7.2 从能检出到会告警、能统计模型部署上去只是第一步真正让业务跑起来的是模型外围的工程整合。检测结果要进入目标跟踪模块常见的轻量跟踪算法都能胜任打上稳定的跟踪ID后才能统计船舶数量、判断目标是否停留、计算移动方向。再往上挂上业务规则比如监控区域里设置电子围栏船一旦进入就触发告警或者检测到航速异常的轨迹就报送人工复核。从我的实践看一个完整的船舶识别系统YOLO模型只是其中一部分前面有视频解码和图像预处理后面有跟踪、告警、统计、存储模型与这些环节的衔接往往比模型本身更费功夫。做项目时不要一头扎进训练指标里先想清楚整条链路再回来打磨模型细节能少走很多弯路。最后提一个让我印象深刻的经验教训当时为了保证港口场景的识别精度我把大量精力花在提高mAP上结果现场部署后发现白天强逆光时误报频繁值班人员对系统的信任度直线下降。后来真正解决问题的是在数据采集阶段就补充逆光时段的样本同时加入时序告警过滤比我再怎么调模型参数都管用。做船舶识别这类强场景依赖的目标检测任务多和一线使用人员聊多去现场看摄像机画面往往比盯着训练曲线更能找到问题的要害。希望这篇分享能帮准备动手做船舶识别项目的朋友少踩几个坑。