ARTICLE DETAIL

资讯详情

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

基于改进Yolov5的船舶目标检测:小目标与复杂场景优化实践

基于改进Yolov5的船舶目标检测:小目标与复杂场景优化实践 简介面向计算机视觉与船舶智能监控领域研究者的一份完整研究文档基于Yolov5算法深入探讨船舶目标检测的改进方案。文档从研究背景与现状切入系统梳理图像预处理、特征提取及Yolov5算法原理并横向比较多种目标检测算法帮助读者快速建立技术坐标系。改进部分重点阐述数据增强随机旋转、随机裁剪、颜色变换、网络结构优化卷积层、池化层、注意力机制以及损失函数调整正负样本、类别不平衡三类策略兼顾理论分析与工程实现细节。实验章节完整展示数据集准备、标注规范、模型训练与验证流程并通过性能指标和结果对比评估改进效果。资源仅含1个docx文档约80KB篇幅紧凑、目录结构清晰可按章节逐段研读。目前已有45人学习适合目标检测入门者、船舶识别研究者及算法调优工程师快速获取一套从理论到实验的完整参考。1. 项目定位到底要解决什么问题1.1 从标题拆出三个关键词基于改进Yolov5算法的船舶目标检测研究这个题目三句话就能说清模型是Yolov5重点是改进场景是船舶目标检测。别小看这三个词每一个拆开都有大量文章可做。船舶检测不是把通用目标检测里的车换成船那么简单海上目标尺度悬殊、背景复杂、拍摄视角多变通用模型直接上效果往往不理想。我决定以Yolov5为基线原因是它工程成熟、调起来顺手、社区资料多特别适合做算法改进方向的课题而不是一上来就选那些框架新但部署麻烦的模型。这篇文章就是围绕这三件事展开船的视觉场景到底难在哪怎么在Yolov5上做针对性改进以及实操中踩过的坑。只要是做毕业设计、船舶视觉课题或者想拿Yolov5做自定义目标检测的人都可以参考这条路径。1.2 船舶检测场景的特殊性真实场景下的船舶图像远比你想象中乱。图像可能来自岸基CCTV、船载摄像头、无人机甚至卫星遥感视角和分辨率差异巨大。海上光照变化剧烈顺光和逆光下同一艘船的颜色、纹理完全不同雾气、反光、浪花飞沫都会成为干扰背景。最要命的是目标尺度远处的货轮可能只有十几像素近处的渔船能占满整个画面。港口里船只密集时船和船相互遮挡船与岸边的吊机、建筑在纹理上也有很强相似性。这些因素叠加起来让船这个目标在检测器里并不总是清晰可分。所以做船舶检测时数据分析环节不能省你得知道自己的困难样本长什么样再决定模型往哪个方向改。1.3 为什么选Yolov5当基线我选Yolov5不是因为它榜单上多能打而是因为它作为研究基线实在太合适。结构上Backbone、Neck、Head分得清清楚楚你想做改进有明确的下手点代码上从数据准备、训练到验证、导出一条龙都能跑通部署上ONNX、TensorRT、rknn这些生态都很成熟。相比Yolov8或者RT-DETR这些新框架Yolov5的代码更直白改动更容易被看见踩坑时也容易定位。单阶段检测器在速度上的优势对岸基监控这类需要实时处理的场景非常重要。船舶目标数量不算极端密集用anchor-based的Yolov5来平衡精度和速度是相对理性的选择。1.4 整个研究路径怎么安排我的实践路径是先定基线和指标再做数据盘点然后设计改进点接着训练验证最后做可视化分析。这个顺序很重要但很多人在拿到数据后第一件事就是改网络结构这是反的。我先把baseline跑通用同一个验证集看指标确认数据没有大问题再开始动手改造。整个改进围绕三个问题展开小目标漏检、复杂背景误检、训练样本不均衡。改进策略分成特征融合、注意力机制、损失函数三条线每一步单独评估最后再组合成最终方案。这样做的最大好处是你能说清楚每一个模块到底带来了多少提升而不是糊里糊涂地看着分数涨了。2. 我的改进思路不是堆模块是逐点拆问题2.1 小目标漏检从特征融合下手船舶检测最典型的痛点就是小目标漏检。一艘轮船在距离摄像头两三公里的地方目标框可能只有10x10像素经过骨干网络32倍下采样后对应特征图上的目标可能连一个网格都占不满。我第一版改进不是换Backbone而是从特征融合下手增加一层更高分辨率的P2输出层让模型在160x160尺度的特征图上做预测同时调整PANet的上下采样路径让浅层细节更直接地传到检测头。这样改完之后小目标的Recall提升非常明显。代价是计算量增加因为高分辨率特征图参与预测FLOPs会变大训练显存也会涨。如果显存吃紧可以考虑只在推理阶段启用P2训练时用知识蒸馏来弥补不过这个方案工程量大一些新手先不用急着做。2.2 复杂背景误检引入轻量注意力机制海上反光、雾天、浪花飞沫这些背景很容易被模型误判成目标。直接加SE或者CBAM是有效的但会带来额外参数和推理延迟。我选择把注意力模块放在Backbone最后几个stage之后并且用参数更少的ECA模块。ECA实际上就是把SE里的全连接瓶颈层去掉改用一维卷积来学习通道依赖效果好、开销低。加入之后模型对船舶轮廓的响应会更聚焦误检率明显下降。这里有个实操提醒不要在每个Concat节点后面都塞注意力模块那样推理变慢不说还容易过拟合常常是验证集好看、测试集打回原形。注意力不是越多越好关键是放对位置。2.3 样本不均衡损失函数加数据增强船舶数据集的另一个特点是样本不均衡。远处小目标和近处大目标数量悬殊而且大量样本是晴天大船这种容易识别的类型真正困难的样本也就是被遮挡、雾天、小目标反而很少。我采用损失函数和数据增强双管齐下的方案。损失函数上尝试了Focal-EIoU让模型更关注困难样本数据增强上除了Yolov5自带的Mosaic和MixUp之外我还加了随机裁剪加局部放大这种针对小目标的增强方式模拟远处船舶突然靠近的效果。最好用的一个技巧反而是欠采样把训练集里那些几乎一模一样的重复帧去掉防止模型学偏到某一艘船的外观上。这个操作对防过拟合的作用比换一个复杂loss明显得多。3. 数据集怎么搞最容易被低估的工作量3.1 公开数据集与自建数据的搭配我用的数据集是SeaShips加从监控视频中抽帧补充的数据。SeaShips是船舶检测领域比较经典的数据集包含货船、渔船、客船等多个类别图像质量不错但场景相对单一如果只靠它训练模型换一个港口就很容易失效。从视频抽帧补充数据时不能只挑好看的帧黄昏、逆光、起雾、雨滴遮挡这些困难样本都要抽出来。抽完帧还要做相似性去重否则等于让模型反复记忆同一艘船验证指标会虚高。我实际统计过去掉重复帧后训练集可能少掉四分之一但最终泛化能力反而更好这说明数据质量比数据数量更重要。3.2 标注规范与格式转换船舶标注比通用目标标注更讲究。我踩过一个坑一开始标注时把船体连同倒影一起框进去结果模型经常把岸边建筑或码头上的吊机也框进来。后来我统一了规范只标船体主轮廓甲板以上结构可以适当放宽但绝对不能包含倒影和明显不属于船体的涟漪。标注完以后要转成YOLO格式每张图对应一个txt文件每行是类别 cx cy w h其中cx、cy是中心点坐标w、h是宽高都归一化到[0,1]。转换脚本本身不复杂但要注意图片尺寸和标注框坐标的对应关系尤其是做过resize、letterbox之后归一化坐标必须重新计算否则训练出来框的位置全是偏的。3.3 数据划分与增强参数控制划分数据集的时候一定不要用纯随机划分。视频连续帧之间高度相似如果同一段视频画面同时出现在训练集和验证集相当于让模型背答案验证分数会很好看但部署到新场景立刻露馅。我一般按视频片段或拍摄场景划分训练、验证、测试的比例控制在8:1:1。数据增强方面Mosaic概率可以开到1.0但旋转角度不建议超过30度。船头船尾是有方向含义的转得太离谱会让模型学到错误的空间关系。HSV增强里的饱和度扰动可以调大一点海上光照变化丰富适当的颜色扰动反而能提升鲁棒性。4. 实操过程从环境配置到改代码跑通4.1 环境配置与显存规划Yolov5的环境配置在深度学习项目里算轻松的PyTorch、CUDA、OpenCV等基础组件装好就能跑。真正头疼的是显存。如果训练时把输入分辨率提到1280batch size一不小心就爆显存。我的做法是先在640分辨率下把流程跑通确认改进代码没有问题再用1280分辨率做精细训练。单卡显存不够就开AMP混合精度实测能把显存占用降差不多一半。这个话题还可以延伸一下如果目标是树莓派5这类嵌入式设备本地训练完以后要导出成TensorRT或者ONNX再量化精度会有损失但推理速度会快很多。工程上永远是在精度、速度和资源三者之间做取舍提前想清楚部署环境训练参数会更好定。4.2 训练参数与anchor重聚类Yolov5的超参数很多但没有一组是万能的。我建议先把img-size、epochs、batch-size这类基础参数定下来再动loss权重和anchor阈值。对船舶小目标场景训练前重新聚类anchor几乎是必做项。Yolov5自带了autoanchor脚本会自动计算当前数据集的anchor分布但如果你只是改了img-size而不改anchor小目标很可能收敛得很慢。训练轮数我一般设150到200patience设30配合早停省电也省时间。超参数遗传算法可以跑但非常耗时。我是先手动调几轮再用遗传算法在小范围搜索这样不容易把训练过程带跑偏。4.3 改进模块的代码落地以增加P2输出层为例它并不需要从零写一个检测头。在models/yolo.py里注册新的检测层再在模型yaml配置里增加一个输出节点就可以。常见做法是在Detect类初始化时设置对应的输出anchor数量和grid大小在forward里返回多个尺度的预测结果。代码结构大致是这样class Detect(nn.Module): def __init__(self, nc80, anchors()): super().__init__() self.nc nc self.no nc 5 self.nl len(anchors) self.na len(anchors[0]) // 2 self.grid [torch.zeros(1)] * self.nl self.anchor_grid [torch.zeros(1)] * self.nl self.m nn.ModuleList(nn.Conv2d(x, self.no * self.na, 1) for x in ch) def forward(self, x): z [] for i in range(self.nl): x[i] self.m[i](x[i]) bs, _, ny, nx x[i].shape # 这里补充动态grid生成和decode逻辑 return x if self.training else (torch.cat(z, 1), x)实际改的时候要同步修改yaml里的anchors配置让特征图尺度和anchor层级一一对应。我遇到过很多次shape不匹配的报错基本都是nc、nl、anchors三者的数量没对上。报错后先检查Detect的m模块输入通道是否与yaml里的ch一致再检查数据集的类别数nc有没有传对。这个排查逻辑大家改网络时可以直接套用。5. 实验结果与分析每一步改进带来了什么5.1 评估指标怎么选我一般同时看mAP0.5、mAP0.5:0.95、Precision、Recall、参数量和FPS。mAP0.5反映的是大概框得准不准mAP0.5:0.95更严格能体现框和真实目标的重合质量。做改进对比时所有方法必须用同一批数据、同样的训练轮次、同样的输入分辨率才能保证公平。另外千万不要拿自己改进后的模型跟别人论文表格里的数字硬比。数据集、设备、训练配置都不一样直接比数值没有意义只会制造焦虑。5.2 一组典型的改进前后对比为了让你心里有个数我列一组我在自建船舶数据集上的结果这里只表示趋势不代表绝对水平模型mAP0.5 (%)mAP0.5:0.95 (%)参数量 (M)FPS (RTX 3080)Yolov5s baseline82.455.17.296 P2输出层85.659.79.174 ECA注意力86.961.39.368 Focal-EIoU87.462.09.368从表里能看到改进点是一步一步叠加上去的精度逐步提升FPS虽然下降但还在可接受范围。这里也提醒一下如果做工程部署不一定所有改进都要上。有时候Baseline P2 合理数据增强已经比很多花哨结构实用因为实时监控场景对推理速度同样敏感。做研究和做产品对改进项的取舍标准完全不同。5.3 可视化分析指标之外的细节指标之外我强烈建议把检测结果可视化出来看。我遇到过一类典型失败场景两艘船并排停靠时模型把两艘船框成一个目标还有渔船密集作业时船与船之间的锚链被误框成船。这些问题在mAP上不容易暴露但可视化一眼就能看到。把特征图的热力图导出来可以帮助定位是特征融合的问题还是分类置信度的问题。我最终在NMS阶段稍微调低了IoU阈值让重叠目标更容易保留为两个框同时增加对小目标的置信度修正。这个改进很小但在密集停泊场景下效果非常直接。6. 常见问题与排查技巧实录6.1 问题速查表训练和改进过程中有几类问题是出现频率最高的我整理成了一张速查表现象可能原因解决办法loss输出为nan学习率过高、浮点溢出、AMP精度设置不当降低学习率关闭AMP检查标签是否存在异常值训练时显存OOMbatch size过大、输入分辨率过高、缓存未释放调小batch size开AMP使用梯度累积小目标全部漏检anchor尺寸不够小、没有P2层、增强方式把目标截掉重聚类anchor增加高分辨率特征图调整增强参数验证指标高但实测崩数据集按帧随机划分、重复帧泄露按视频序列划分数据增加相似度去重不同尺度船舶混淆类别样本数不均衡、待识别类别粒度过细做数据重采样调整loss类别权重简化类别粒度模型在雾天表现差训练数据缺乏该类场景补充雾天或低照度样本增加HSV饱和度扰动这张表不是标准答案但排查问题的顺序是通用的先看数据再调参数最后动结构。别一上来就怀疑模型代码有bug。6.2 排查思路与独家技巧遇到精度不涨先别急着加模块。第一步把训练集和验证集的loss曲线拉出来对比如果训练loss持续下降、验证loss不再降说明过拟合优先加数据增强或降低模型容量如果两个loss都下不去说明模型容量不足或特征提取有问题这时再考虑改结构。我每轮训练完必做一件事把验证集里被漏检的图片单独存到一个文件夹按漏检次数排序然后逐张看。很多问题不用看复杂曲线看图就能定位。还有一个土办法很管用把预测结果里的class概率分布打印出来如果某几个类别概率总是很低就去数一下这类样本在训练集里有多少。如果数量不少但概率低大概率是特征区分度不够这时可以考虑合并相近类别比如把渔船和帆船归成一个大类检测难度瞬间下降。整个项目做下来我最大的体会是所谓改进Yolov5不能变成给模型缝补丁。每一个改动都应该来自对数据和场景的观察。船舶目标检测真正难的往往不是网络结构本身而是对复杂海况和尺度差异的理解。如果你也在做类似课题我建议先把baseline跑稳再把最多的精力花在数据处理和问题定位上最后再动模型结构。改结构时一次只加一个变量记录好每步实验。最后再分享一个小技巧训练前花十分钟把anchor重新聚类同时统计一下训练集里小目标的数量这两个动作基本决定了你这个项目的上界。祝你的船也能被稳稳找到。本文还有配套的精品资源点击获取
返回列表