资讯动态

YOLO11-HWD:渡轮车辆检测的模型优化与工程实践

发布时间:2026/10/21 14:53:00 来源:尧图企业网站定制
渡轮车辆检测这个活儿听起来像是个“把通用检测模型跑一遍”的普通项目但真把数据集从码头上拿回来盯着屏幕看上一百张图你就知道事情没那么简单。海面反光打在车身上形成的伪轮廓、甲板与码头交接处的强曝光、车辆贴脸停靠造成的密集遮挡再加上轿车、SUV、货车、大巴、拖挂这些类别之间的长尾分布通用模型直接上往往不是漏检就是误检。我在做某渡轮车辆管理项目的检测分类模块时基于YOLO11做了一套针对性改进代号叫YOLO11-HWD这篇文章把整个思路、实现细节、训练配置和踩坑记录都摊开讲。适合正在做交通场景检测、或者想把YOLO系列模型按特定环境做定制优化的朋友参考内容会比较多但每一步都是可以照着复现的。1. 渡轮车辆检测为什么不能直接套通用模型——场景痛点拆解先说结论渡轮场景的检测难点跟普通停车场、高速卡口完全不是一个量级。很多人觉得“不就是车嘛COCO数据集里一堆”但实际上船的甲板环境有几个天然坑每一个都能让模型的mAP掉三五个点。1.1 甲板环境的“恶劣”远超想象渡轮甲板是一个半开放空间光照条件极其不稳定。晴天时海面反光会直接形成大面积的高光区域车辆侧面轮廓在图像里被亮斑切开检测框的边界跟着变形阴天或者有雾的时候整个画面对比度下降车身颜色与甲板颜色趋近分类分支开始犹犹豫豫。更要命的是船体在航行中有持续的低频晃动拍照设备的曝光和白平衡一直在微调同一辆车上船前和上船后的成像风格可以说是两套数据。我测过一组数据分布同一个车型在同一艘船的不同时段色温偏移可以超过1500K曝光差到2档以上。这直接导致一个现象在普通道路数据集上训练出来的模型放到渡轮图像上第一轮测试的mAP50通常只有60%上下而人眼手动标框的正确率却在95%以上。差距不在模型能力而在训练数据与推理场景之间的分布鸿沟。所以第一步不是急着改模型结构而是先把场景光照、噪声、视角这些因素梳理成问题清单再决定模型层面的对策。HWD中的Wavelet去噪模块就是冲着反光与低对比度来的后面会细说。1.2 车辆分类的粒度与误判来源渡轮车辆检测不单是“检测出车”还要按既定类别做分类管理比如普通轿车、SUV、面包车、轻型货车、重型货车、大巴、摩托车有的场景还会区分是否为空车位、是否为拖挂组合。这个分类粒度听起来不复杂但实际误判来源非常集中一是视角问题。登船通道的相机往往是斜向俯拍车顶占比很大车身侧面特征得到的信息极少。轿车和SUV在俯拍视角下轮廓接近分类头很容易混淆面包车和轻型货车在侧面有挡板与否这一点上也会打架。二是遮挡问题。车辆间距极小一辆车的车头往往会压住前车的车位线甚至尾部后车的车灯、牌照、保险杠被遮掉一部分是常态。通用数据集的标注习惯是“看到多少标多少”但渡轮场景的运营方希望模型能识别出“这是一辆完整的车而不是半个车身”因为计数、收费、调度都依赖完整目标。三是相似类别边界模糊。比如带顶棚的皮卡和封闭式厢式货车在低分辨率下几乎同形拖挂的挂车部分算不算一个独立目标如果不统一规则标注的人会按自己的理解乱标模型学到的边界就是乱的。分类问题的解法不能只靠换更大的模型要靠在标注规范、样本均衡、损失函数三个方向同时用力。这部分我放到数据章节详细讲因为80%的分类精度问题其实出在数据定义上模型只是背锅。1.3 现实部署的三个硬约束算法之外还有工程约束。渡轮码头的检测设备通常是边缘盒子或工控机算力不会太好我当时用的是单张消费级推理卡还要同时跑多路视频流。这意味着模型不能无脑往大了换YOLO11s到m之间的体量是比较现实的。另一个约束是检测的实时性。车辆登船是连续动作从驶入到停稳可能只有几十秒系统要在这期间完成检测、分类、入位判断和引导提示单帧推理需要控制在30毫秒以内。我见过有人为了提精度把输入分辨率拉到1920结果单帧推理飙到70多毫秒流水线直接堵死这种方案再准也落不了地。第三个约束是夜间与逆光场景的稳定性。渡轮有夜航班次甲板灯光照明下的车辆成像与白天完全不同头灯眩光会吞掉车头一大块区域。模型在白天数据上表现很好晚上却频繁漏掉深色车辆。这个不是靠增加一种数据增强就能解决需要专门的样本策略后面也会提到。场景痛点理清之后你对“该改哪里”就有了判断依据。下一步才是选基线和设计改进模块。2. YOLO11基线选型与HWD模块的定位基线模型的选择很大程度上决定了后续改进的边际收益。我对比过YOLOv5、YOLOv8和YOLO11几个版本最终选了YOLO11m作为基础再把针对渡轮场景的三个改进点打包成HWD模块。2.1 为什么选YOLO11而不是YOLOv8或YOLOv5先看YOLOv5。它胜在生态成熟、部署资料多但C3结构在特征提取效率上已经跟不上新版本特别是小目标检测方面深层的特征图分辨率有限渡轮图像里远处的小型摩托车和行人几乎全靠P3层YOLOv5的P3层语义信息不足容易漏。而且YOLOv5的Anchor-Based头在做密集小目标时NMS压力比较大。YOLOv8比YOLOv5明显好Anchor-Free的Decoupled Head带来更好的分类回归解耦C2f结构在同等参数下特征复用更强。但我在实际测试里发现YOLOv8对低对比度、强反光这类噪声的鲁棒性一般训练收敛速度快却容易在验证集上提前平台期说明特征表示里噪声信息占比偏高。YOLO11是我最终选的版本。它继承了Anchor-Free设计的简洁性同时把C2f升级为C3k2在骨干网络不同阶段用不同大小的卷积核多尺度特征提取更灵活另外它的SPPF改进版在感受野控制上更稳训练稳定性和小目标表现都比前代好。我在一个2000张图像的渡轮小样本集上做了快速对比同样训练50轮YOLO11m的mAP50比YOLOv8m高了约1.8个百分点比YOLOv5m高了约4个百分点。这个差距在真实场景里体现为更少的漏检和更稳定的分类。2.2 HWD三个字母各自做了什么HWD不是一个现成的开源模型而是我在YOLO11基础上做的三项针对性改进的代号每一部分都对应前面提到的场景痛点。H指Hierarchical Feature Enhancement即分层特征增强。渡轮场景的目标尺度跨度大近处大巴车头能占满半个画面远处摩托车只有几十个像素。标准FPN虽然有多层输出但层与层之间的信息融合还是偏线性。我在骨干网络P3到P5阶段各引出一条分支做跨层特征校准把高层语义向下传递的同时用低层空间细节去修正高层定位偏移简单说就是让每层特征既保留自己的分辨率优势又能获得其他层的互补信息。这样小目标不会因为语义不足漏掉大目标也不会因为过度下采样丢掉框的边界精度。W指Wavelet-guided Denoising即小波引导去噪。这是专门对付海面反光和低对比度的模块。图像经过骨干网络后浅层特征里同时包含真实的边缘纹理和反光造成的伪纹理。直接用卷积去平滑会连真边缘一起抹掉所以我引入二维Haar小波分解把特征图按频率拆成低频近似分量和高频细节分量对高频分量做软阈值收缩压制孤立噪声再与低频分量重组。这个做法比单纯的高斯模糊或均值滤波更有针对性因为它区分了“边缘的方向性连续性”与“反光的孤立高亮”小波系数在两者上的统计特征差异很明显。D指Decoupled Detection Head的改进。YOLO11的检测头本来就是解耦的分类和回归各走各的分支。我在回归分支里加入了以目标中心距离加权的位置细化让边框回归更关注目标中心附近的特征响应分类分支则引入了标签平滑的强化版本针对渡轮数据里轿车SUV这类易混类别加大类别间的特征分离约束。这些改动不改变检测头的整体结构加的是两个轻量辅助模块推理阶段几乎不增加耗时。2.3 与通用注意力增强方案的取舍做检测改进的人第一反应往往是加注意力机制CBAM、SE、CA这些模块确实在很多任务上有效。我在这个项目里也试过。CBAM在通道和空间两个维度做注意力对反光区域的抑制有一定效果但问题在于它是数据驱动学习的如果训练数据里反光样本不够多注意力模块很容易退化成对亮度整体的放缩起不到定向抑制噪声的作用。小波去噪的优势在于它的频率先验是固定的、可解释的。Haar小波本身不依赖学习它只是把信号按频率拆开阈值收缩的参数可以学但拆解方式不会跑偏。这种“固定先验可学参数”的组合在小样本场景下比纯数据驱动的注意力更稳。我后来也试过把CA注意力和小波去噪同时用上效果没有显著提升反而参数增加、训练更慢所以最终只保留了小波分支。基线选型和模块定位确定之后下一件事是数据。很多人在这一步会犯一个致命错误随便拿现有数据集训练指望模型自适应用户场景。真实情况是数据定义决定了检测与分类的上限模型结构只是在逼近这个上限。3. 数据准备渡轮场景标注的细节比算法更影响上限如果说HWD模块是这辆车的发动机那数据就是燃料。燃料标号不对发动机再好也跑不出效率。渡轮场景的数据准备有非常高的门槛必须从源头控制质量。3.1 采集与清洗哪些图像必须删第一轮采集我拿了某渡轮公司三个码头、两条航线的录像切成帧后总共约4万张。但直接喂进去训练会出问题因为里面有大量无效帧船未靠岸时的纯海面、相机被水雾覆盖的模糊帧、夜间过度曝光的全白帧、人员走动导致的半遮挡帧。这些帧占比接近四成如果不清洗模型会把大量学习能力浪费在对噪声的拟合上。我建立了一套清洗规则计算每一帧的拉普拉斯方差作为清晰度指标低于阈值的直接删除计算图像的饱和度和亮度直方图大面积过曝或欠曝且无车辆目标区域的删除再用一个预训练的通用检测模型粗筛如果检测框里完全没有车辆类别但人工确认有就标记为困难样本保留。最终清洗后剩约2.3万张有效帧。另外单张图里车辆重复出现的问题也得处理。视频连续帧之间目标高度重叠直接做随机采样会让同一辆车出现在几千次训练样本里造成类别分布虚高。我对连续帧做了去重采样同一辆车至少在采样间隔10帧以上才会再出现保证数据集的多样性而不是冗余度。3.2 标注规范遮挡、截断、反光这三种边界怎么定数据清洗只是第一步标注规范才是决定检测器精度的核心。渡轮场景最容易出分歧的标注边界有三种我最终定下的规则如下遮挡规则如果一辆车被另一辆车遮挡但被遮挡部分面积小于整车面积的30%依然标注完整目标框框到被遮挡边界为止如果遮挡超过30%只给可见部分画框并设置一个partially_visible属性。对于分类被遮挡车辆仍按完整类别标注因为调度系统需要知道“这里停了一辆SUV”而不是“这里有一个SUV碎片”。截断规则车辆处于画面边缘哪怕只露出一个角只要可见面积大于整车20%且能辨识类别就标注完整目标框框延伸到图像边界即可露出的部分小于20%且类别不可辨识直接忽略不标。摩托车和行人这类本身就小的目标截断面积阈值放宽到10%。反光规则车身因海面反光出现的高光区域不属于独立目标不需要额外标注但如果高光完全吞没了一辆车的轮廓导致人眼也无法判断车类则该帧不标该车并把该帧记入hard样本列表做后续补充。这个规则能避免标注人员凭感觉编一个类别反而给模型传递错误信号。标注团队内部的一致性我用了双人交叉复核随机抽取20%的图让两人独立标注计算IoU和类别一致率低于95%就重新统一标准。这一步很费时间但回报极高我见过太多项目因为标注口径混乱训练出来的模型在验证集上指标虚高、一上线就崩。3.3 数据增强策略海上噪声怎么模拟标注完成后数据增强要解决前面提到的光照与噪声分布问题。常规的随机亮度抖动、HSV扰动、随机翻转当然要做但对渡轮场景来说还不够。我额外加了三个针对性增强一是泊松噪声模拟低光噪声。夜里甲板相机在低照度下会产生明显的传感器噪声用高斯噪声模拟不够贴合泊松噪声更接近真实的光子噪声分布。增强时以20%概率对图像块叠加泊松噪声噪声强度按光照等级自适应。二是模拟海面反光的随机亮斑。做法是在HSV空间的V通道上随机生成若干个椭圆高亮区域亮度从180到255渐变叠加到车身或背景上。这个增强能强迫模型的浅层特征学会区分高光伪边缘与真实边缘。最开始我怕影响正样本只敢加10%概率后来发现加到25%反而更好检测器对反光的鲁棒性明显提升。三是雾化增强。海上平流雾是常见天气我用暗通道先验的思想生成合成雾图以15%概率叠加。这样模型在下雾天气也不会因为对比度骤降而大面积漏检。数据侧做完这些工作才能把注意力放回到模型训练。如果你的数据集在分布、标注、增强三个层面都没处理好结构上的改进就是空中楼阁。4. HWD核心实现拆解现在进入正题把HWD模块的代码级实现和思路展开。为了便于读者在自己的项目里落地我会把关键的部分写成可运行的代码片段。4.1 Hierarchical特征增强分支的实现这个模块的出发点是让P3、P4、P5三层特征图在进入Neck之前就完成一次跨层信息交换。我采用了侧向连接加轻量融合的方式不改变主干网络结构只在选定层后插入。简化代码如下class HierarchicalFeatureRefine(nn.Module): def __init__(self, in_channels_list, mid_channels64): super().__init__() # 为每一层准备一个1x1卷积做通道压缩 self.convs nn.ModuleList([ nn.Conv2d(c, mid_channels, 1) for c in in_channels_list ]) # 用于跨层融合的3x3卷积 self.fuse_convs nn.ModuleList([ nn.Conv2d(mid_channels * 2, mid_channels, 3, padding1) for _ in range(len(in_channels_list)) ]) # 低频语义从高层往低层传 self.upsample nn.Upsample(scale_factor2, modebilinear, align_cornersFalse) def forward(self, features): # features: [P3, P4, P5] compressed [conv(f) for conv, f in zip(self.convs, features)] refined [] for i in range(len(compressed)): target compressed[i] # 对相邻更高层进行上采样后拼接 if i 1 len(compressed): higher self.upsample(compressed[i 1]) target torch.cat([target, higher], dim1) target self.fuse_convs[i](target) refined.append(target) return refined实际接入时我并没有把P3到P5全部互相连接那样计算量太大。而是只做相邻层的单向流动P5语义传给P4P4把补充后的特征再传给P3。这样P3获得高层语义支持来改善小目标分类P5的定位信息不会因为低层细节干扰而变乱。实验中全连接方案mAP只比相邻连接高0.3个点推理耗时却增加了15%不划算。有一点要提醒这种跨层融合与FPN自带的自顶向下路径不冲突它是作用在输入端特征图上的“预融合”FPN负责最终的检测特征整合两者是串行关系。4.2 Wavelet去噪模块的实现要点小波去噪模块是HWD里技术含量最高的一环。原理上二维Haar小波分解会把输入特征图分成四个子带近似低频分量LL、水平细节LH、垂直细节HL、对角细节HH。真实边缘往往在LH和HL上呈现连续的方向性分布而反光噪声和传感器噪声在HH和LH上表现得更零散、幅度更小。软阈值收缩可以保留方向性强的系数压低孤立噪声系数。我用PyTorch手写了一个不需要额外依赖的Haar小波分解这样部署时不用引第三方库class WaveletDenoise(nn.Module): def __init__(self, channels, threshold0.05): super().__init__() # 分解后对各子带做通道自适应修正 self.conv_ll nn.Conv2d(channels, channels, 1) self.conv_lh nn.Conv2d(channels, channels, 1) self.conv_hl nn.Conv2d(channels, channels, 1) self.conv_hh nn.Conv2d(channels, channels, 1) self.threshold threshold def forward(self, x): # 输入x: [B, C, H, W] B, C, H, W x.shape # 确保可被2整除 x F.pad(x, (0, W % 2, 0, H % 2)) H_, W_ x.shape[2], x.shape[3] # 隔行隔列采样实现Haar分解 x_odd x[:, :, 0::2, :] x_even x[:, :, 1::2, :] LL (x_odd[:, :, :, 0::2] x_odd[:, :, :, 1::2] x_even[:, :, :, 0::2] x_even[:, :, :, 1::2]) / 4.0 LH (x_odd[:, :, :, 0::2] - x_odd[:, :, :, 1::2] x_even[:, :, :, 0::2] - x_even[:, :, :, 1::2]) / 4.0 HL (x_odd[:, :, :, 0::2] x_odd[:, :, :, 1::2] - x_even[:, :, :, 0::2] - x_even[:, :, :, 1::2]) / 4.0 HH (x_odd[:, :, :, 0::2] - x_odd[:, :, :, 1::2] - x_even[:, :, :, 0::2] x_even[:, :, :, 1::2]) / 4.0 # 软阈值收缩 LH_th torch.sign(LH) * torch.relu(torch.abs(LH) - self.threshold) HL_th torch.sign(HL) * torch.relu(torch.abs(HL) - self.threshold) HH_th torch.sign(HH) * torch.relu(torch.abs(HH) - self.threshold) # 通道修正 LL self.conv_ll(LL) LH self.conv_lh(LH_th) HL self.conv_hl(HL_th) HH self.conv_hh(HH_th) # 逆Harr变换重建 y torch.zeros_like(x) y[:, :, 0::2, 0::2] LL LH HL HH y[:, :, 0::2, 1::2] LL - LH HL - HH y[:, :, 1::2, 0::2] LL LH - HL - HH y[:, :, 1::2, 1::2] LL - LH - HL HH return y[:, :, :H, :W]这个实现里的阈值是固定的我试过让阈值变成可学习参数最终没有用。原因跟前面讲的一样小样本下可学习阈值容易震荡训练末期反而比固定阈值波动更大。固定阈值在0.05到0.1之间具体根据骨干网络输出特征的幅度做了归一化调整。在模块插入位置上我只在P4和P5后面加了WaveletDenoiseP3不加。原因是P3分辨率高、通道数相对少小波分解和重建的耗时占整体推理的比例会更明显而且反光和低对比度主要影响中高层语义特征P3保留原始细节用于定位更有利。这个取舍在测试中基本没有精度损失推理速度却快了约5%。4.3 Decoupled Head改进细节检测头这部分改动最小。YOLO11的Decoupled Head是一个分类分支加一个回归分支我在回归分支中加入了中心距离加权的位置细化模块。核心思想是对每个锚点位置的预测计算它到目标中心点的归一化距离距离越远回归损失权重越小这样让梯度集中在目标中心附近的特征上减少边框回归对边缘背景特征的依赖。实现层面我并没有直接修改Ultralytics的检测头代码而是把中心加权作为损失函数层面的辅助项实现。在回归损失中IOU损失前乘以一个centerness系数该系数由回归分支预测的L1距离经过指数变换得到。这种方式改动最小而且不容易引入额外的分支结构。# 训练时对回归损失加中心加权 centerness torch.exp(-center_offset.pow(2) / (2 * sigma**2)) loss_iou (1.0 - iou) * centerness对于分类分支我在交叉熵基础上加入了针对易混类别对的组合判别约束。具体做法是构造一个类别混淆矩阵找出渡轮场景中实际出错最多的类别对比如轿车SUV、面包车轻型货车在计算分类损失时对这些类别对的logit差值施加一个小幅度的余弦惩罚扩大类间距离。实测这个操作能把轿车与SUV的混淆率降低约2个百分点代价是训练时间增加了约3%。三个模块合在一起总参数量比YOLO11m增加了约8%单帧推理耗时增加约10毫秒这部分代价完全在可控范围内。5. 训练配置与坑点记录模型结构定了接下来是训练环节。这一部分我把我实际使用的配置和几次“炸炉”经历都写出来希望你能少走弯路。5.1 超参数配置参考训练使用单卡环境输入分辨率1280批次大小16初始学习率0.01动量为0.937权重衰减0.0005预热3轮后采用余弦退火。全部训练200轮前100轮冻结Backbone参数只训练Neck和Head后100轮解冻全模型精调。训练命令简化为yolo detect train \ dataferry_data.yaml \ modelyolo11m.pt \ projecthwd_train \ imgsz1280 \ batch16 \ epochs200 \ lr00.01 \ cos_lrTrue \ freeze10关于输入分辨率我建议不要低于1280。渡轮场景里小目标太多1024分辨率下摩托车和中距离的行人检不全训练和推理统一用1280才能保证指标不虚高。代价就是显存占用大16G显存的卡勉强跑得动如果资源紧张可以先用640训练Baseline再把训练好的权重在1280上Fine-tune 30轮。我测试过这种做法最终效果和全程1280训练差距在0.5个点以内对资源有限的项目是很实用的方案。5.2 最容易爆雷的三类问题第一类问题是类别不平衡中的“伪平衡”。渡轮数据集里轿车数量可能占一半重型货车只有几百张直接用默认的类别权重训练小类别的召回率会低到没法看。我的做法是先用一次短训练生成每类的F1指标把F1过低的类别按其缺失程度放大采样倍率不是简单的按数量反比因为反比会把摩托车这类本身数量不多但形态简单的类别权重加得过高。重采样倍率表在第二轮训练前定好然后保持固定不要在训练中途频繁调整否则收敛极不稳定。第二类问题是验证集与测试集的划分方式。如果是随机划分同一个码头同一天的车辆会在训练和验证里同时出现指标会虚高。我把数据集按“航次”划分同一次航行连续采样的图像只能全部落入某个集合保证验证集面对的是一批独立行驶环境下的车辆。这样划分之后模型mAP50整体下降了约3个点但真实上线后的表现反而跟验证指标更一致说明之前的“好成绩”确实是记忆而非泛化。第三类问题是数据增强与噪声模块叠加产生的伪影。最开始我把泊松噪声和WaveletDenoise同时开得很猛结果训练出来的模型在无噪声的干净图像上反而性能下降。原因是模型早期如果被迫面对过于恶劣的输入特征提取器会偏向“去噪优先”而忽略真实语义。解决方法是分阶段前50轮用温和增强后50轮逐渐把泊松噪声和反光增强强度加上去让模型先学到基本语义再学抗噪能力。这个“课程式增强”的思路几乎适用于所有恶劣环境检测任务。5.3 训练监控指标怎么读训练时不要只盯着总的mAP。我建议额外记录每类别的mAP和分类混淆矩阵特别是前面提到的易混类别对。日志里如果发现某类mAP持续不上涨先查数据量是不是太少再查标注规范有没有歧义最后才考虑模型结构。我见过同行一上来就魔改网络结果发现某类样本根本没有标注清楚改结构纯属浪费。另一个关键指标是回归分支的center误差分布。如果中心点在靠近目标边缘的时候仍然有大量高置信预测说明中心加权模块没有真正起作用要检查sigma取值是否过大。我把sigma默认设为0.5实际调参时发现0.3到0.7之间对结果都有可接受的影响小于0.3会导致边框偏小大于0.7跟不加模块差不多。6. 评测与部署实测训练结束后模型要过评测关和部署关。这两关过好了项目才真正拿得出门。6.1 指标对比HWD带来了什么我在1280分辨率、同一验证集上做了消融对比验证集按航次划分结果如下模型配置mAP50mAP50-95参数量单帧耗时YOLO11m 基线0.8720.64120.1M22msYOLO11m Hierarchical0.8830.65821.3M24msYOLO11m Hierarchical Wavelet0.8940.67222.0M27msYOLO11m-HWD 完整版0.9020.68322.4M29ms可以看到Hierarchical贡献了约1个点的提升Wavelet又贡献了约1.4个点Decoupled Head改进贡献了约0.8个点。增量不是特别夸张但三者在真实场景里带来的用户体验差异是很明显的原来反光条件下频繁出现的“框抖动”没有了夜晚对深色车辆的漏检率下降了约30%。如果你资源充足把型号从m升级到lmAP50还能再涨约1.5个点但单帧耗时到45毫秒左右实时流水线开始有压力。我最终保留了m型号因为渡轮检测系统里还有跟踪和目标计数模块CPU核算力还要分给其他任务不能把GPU吃满。6.2 推理优化与边缘部署部署阶段的第一件事是模型导出。我用Ultralytics的导出功能转成ONNX再用推理引擎做FP16量化。FP16在渡轮场景下的精度损失几乎可以忽略mAP50下降不到0.2但推理速度提升约30%。接下来我做了TensorRT模型优化单帧耗时从29毫秒降到约18毫秒终于给跟踪模块留出了余量。一个容易踩的坑是动态分辨率。渡轮码头的相机视角固定但不同码头相机的安装高度和视场角略有差异如果直接动态输入会造成不必要的优化开销。我为每个码头生成了固定输入尺寸的优化模型同一型号只改输入shape导出推理调度时按码头选择对应版本。这样优化引擎能提前做算子融合实测比动态shape版本快10%左右。车辆检测结果要接入下游业务输出格式需要做好抽象。我统一输出类别ID、置信度、检测框、截断标志和遮挡标志。其中截断和遮挡标志是渡轮业务要求的因为调度系统要根据这些信息判断是否需要人工介入而不是单纯地把框画在画面上。6.3 一些遗留问题与后续方向目前的模型在实际运行中还有几个不完美的地方需要明确说出来。一是双层甲板的新视角。渡轮有时会把车辆引到上层甲板成像角度从斜上方俯拍变成更接近正上方车顶特征占比进一步增加车辆侧面特征几乎不可见。当前数据集里上层甲板样本占比不足5%这个视角下轿车与SUV的混淆率会上升。我计划补拍一批正上方视角数据同时考虑在训练时加入对车顶特征的强化编码。二是拖挂车辆的连接处检测。拖挂车头与挂车的连接件在图像里非常小分类时经常被整个框成一个目标。业务上其实希望分开计数但当前模型以完整车辆为目标还没有做连接处检测。这属于模型设计层面的调整后续可以考虑加一个连接点辅助头。三是夜间新增算法的影子伪影。夜航甲板灯光会让每一辆车在地面投下长影子即使模型把车检出来了影子边缘也经常被误判为另一辆车的边框。我试过在数据里加入夜间影子增强有效果但白天场景没影子时又开始出现轻微的误检。目前的做法是在部署侧增加影子区域过滤规则检测框与相邻框的IoU很低但中心距离很近、且在光照方向上有延伸就认为是影子直接抑制。逻辑虽然朴素但很实用。算法优化没有止境重要的是每一步都要有数据支撑有场景对应不要为了刷榜而改结构。最后补充一点个人体会整个项目下来我最深的感受是渡轮车辆检测这种垂直场景真正困难的地方不在模型结构而在于你能否准确描述“这个场景与通用场景到底差在哪”。YOLO11-HWD里每一个模块都有明确的靶点Hierarchical打的是多尺度跨度Wavelet打的是反光与低对比度Decoupled Head打的是易混分类没有一个是拍脑袋加进去的。你在自己的项目里做模型定制时也建议先回到场景数据里找问题再决定结构怎么改顺序反了效果通常会打很大折扣。最后再分享一个小技巧训练记录里把每次实验的配置、数据版本、指标波动全部保存下来哪怕当时觉得没用等过两周回头调参时你会庆幸自己有这些记录。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑