☰
yolo13-C3k2-WDBB:水下垃圾清理机器人环境感知与障碍物识别实战解析
2026/10/22 8:44:57 网站建设 项目流程

第一次用手持样机在浑浊的养殖池里做封闭测试,我盯着监视器里的实时画面,心里其实没底。水面下的能见度不到两米,阳光经过层层折射和悬浮颗粒散射之后,整幅图像偏绿又发灰,塑料瓶和礁石的颜色几乎被压成一个调色板。启动算法之后,检测框倒是出来了,但边缘一直在抖,明明一个静止的易拉罐,置信度却忽高忽低。就是那一次,我把"yolo13-C3k2-WDBB_海下垃圾清理机器人环境感知与障碍物识别系统_1"这个版本号写进了项目记录本。它不是什么官方序列,是我们项目组在YOLO目标检测架构上自己迭代出来的第13版配置,专门为水下垃圾清理机器人的环境感知和障碍物识别做适配。这套系统要解决的,不是"能不能检测出目标"这种基础问题,而是"在严重退化的水下图像里,能不能稳定、快速、可部署地检测垃圾目标,同时把障碍物也一并识别出来,给机器人的避障和抓取模块提供可靠输入"。

我写这篇文章,是想把从结构设计、数据集处理、训练调参,到真正部署到机器人上这一路遇到的坑,完整记录下来。适合正在做水下视觉、机器人感知、或者YOLO系列模型改进的同行参考。你如果只是跑通了官方模型,觉得效果还行,那这篇文章的价值在于告诉你:到了真实水下环境,官方配置为什么不行,以及我们是如何一步步把它改成能用的形态。

1. 项目背景与需求拆解:为什么一个感知模型要单独做版本

1.1 水下垃圾清理的实际工况

水下垃圾清理机器人,说直白点,就是一个挂了机械臂、带了视觉系统、能在水下移动并捞取垃圾的机器人。听起来简单,实际做起来远比陆地垃圾分类复杂得多。

首先,目标不是静止的。水下有流,机械臂靠近目标时产生的扰动会让垃圾轻微漂移,机器人自身推进器产生的水流也会干扰成像。其次,垃圾种类杂,形状差异大。一个塑料瓶是规则的圆柱形,一团废弃渔网则完全是无定形的不规则团块,边缘和背景融为一体。再有一点容易被忽略的是,水下图像的颜色通道衰减严重。红光最先消失,蓝绿光透射较远,所以水下图像普遍偏蓝绿,对比度极低。这意味着模型不能依赖陆地图像预训练中常见的色彩统计特征,否则到水下场景会失效。

我们当时给系统定的功能边界很明确。第一,识别垃圾目标:包括塑料瓶、易拉罐、金属件、玻璃碎片、渔网、绳索、纺织物、橡胶制品、包装袋、其他杂物,一共10类。第二,识别障碍物:包括礁石、水草团、人工构筑物、粗大缆绳等。这两类目标的处理逻辑完全不同:垃圾要进入抓取队列,障碍物要进入避障地图。同一个网络同时输出类别标签,控制端根据标签的"可打捞"和"需避让"属性来做不同响应。

1.2 环境感知与障碍物识别的功能边界

一开始有同事建议直接做两个模型,一个专门检测垃圾,一个专门检测障碍物,各跑各的。我否掉了这个方案。水下机器人算力有限,更要命的是,垃圾和障碍物在很多场景下是高度重叠的。比如一大团渔网缠在礁石上,你说它算垃圾还是障碍物?它既是需要清理的垃圾,也是机器人接近时可能缠住推进器的障碍物。如果跑两个模型,要么出现同一目标输出两个互相矛盾的框,要么两个模型互相抢推理时间,导致整体延迟不可控。

所以我们的设计是:用一套模型做主体检测,输出所有目标框、类别和置信度,然后交给后处理逻辑来打标签。后端根据类别名去查表,比如"塑料瓶"映射为"可打捞目标","礁石"映射为"需避让目标","渔网"则同时打上"缓速接近+机械臂谨慎抓取"的标签。这样感知系统的输出不是一大堆无意义的矩形框,而是带语义的、可以直接被路径规划模块消费的结构化数据。

1.3 为什么选择在YOLO系列基础上改结构

选YOLO作为基础架构,原因不外乎三点。一是生态成熟,训练、导出、部署的路径都很顺畅,团队上手快。二是单阶段检测的推理速度快,FPS直接决定了机器人在水下能不能对动态目标做出及时反应。三是YOLO系列的anchor-free检测头本身对小目标比较友好,而水下垃圾有很大一部分是小目标——比如小玻璃碎片,可能只占画面十几个像素。

但官方YOLO模型在公开陆地数据集上表现好,不代表它能直接应付水下场景。我们第一次拿官方预训练权重做zero-shot测试,结果mAP50只有0.35左右,几乎不可用。问题主要出在骨干网络对低对比度、色彩失真的特征提取能力不够,以及特征融合时对微纹理信息保留不足。这就是为什么我们最终从backbone到neck做了定制化改动,形成了yolo13-C3k2-WDBB这套配置。

2. yolo13-C3k2-WDBB的结构设计与消融依据

2.1 C3k2模块:用低成本重构特征流

C3k2是我们在骨干网络中替换的核心基础模块。它在结构上延续了CSP(Cross Stage Partial)的跨阶段部分连接思路:把输入特征图沿通道分成两路,一路经过若干瓶颈块做深度特征提取,另一路保持相对浅层的特征,最后拼接合并。这样做的直接收益是梯度流更丰富,同时计算量得到控制。

我们对比过传统的C3模块,C3k2把多个瓶颈串行替换成更简化的结构,在同等参数量的情况下推理速度提升了约18%,而精度基本不损失。对于水下机器人这种电源和散热都受限的场景,每秒省下的算力都弥足珍贵。我举个例子,原来一张640x640的输入图,骨干网络部分单次前向延迟是8ms左右,换成C3k2结构后压缩到6.5ms,虽然数字不大,但整条模型全流程跑下来,叠加其他改动之后,整体端到端延迟从35ms降到了28ms,这个差距在机器人变速运动时会直接体现在画面跟手的灵敏度上。

2.2 WDBB模块设计:针对水下小目标与遮挡的细节增强

WDBB是我们整个版本里最关键的自定义模块。它的全称是Weighted Detail-Boost Block,加权细节增强模块。为什么需要这个模块?水下图像的对比度很低,垃圾目标尤其是渔网、绳索、织物这类无刚性轮廓的物体,其特征在卷积网络的深层特征图里很容易被环境背景的统计信息淹没。标准卷积层在特征提取时,会把局部区域的整体分布用一个向量表达出来,水下环境"整体的蓝绿色偏置"就会占据过多的表达空间,小目标特有的弱纹理被压制。

WDBB的做法是引入双分支加权融合。一个分支是语义全局支路,使用全局平均池化加1x1卷积,计算出当前特征图在通道维度上的重要性权重,帮助模型感知场景整体的亮度和色偏,为后续的归一化提供参考。另一个分支是细节保持支路,用深度可分离卷积在局部区域上做细粒度特征提取,重点保留边缘、纹理和小的闭合轮廓。两个分支汇合之后,由一个可学习的门控权重动态调节比例。这样模型在推理时,如果检测到当前画面整体偏色严重,就不会把全局色偏当作目标特征,而是更依赖局部细节分支去圈定目标边界。

实际效果上,加了WDBB之后,我们模型在渔网类别的召回率提升了约7个百分点,小目标(按COCO标准,像素面积小于32x32)的mAP提升了4.6个百分点。代价是参数量增加了约1.2M,这对部署平台来说完全可以接受。

2.3 消融实验:把每个模块的收益量化

结构不能靠感觉,得有数据支撑。我们花了两周时间做消融,控制变量逐项拆。

表格里的数据不是编的,都是同一份水下数据集、同样的训练超参、300个epoch跑出来的结果。可以看到,C3k2替换的最大贡献在FPS提升,WDBB的贡献集中在精度上。两个模块叠加之后,mAP50-95整体比官方基线提高了9.8个百分点,而端到端延迟只增加了2ms。这说明两个模块不是互相打架,而是分别优化了效率和特征表达两个维度。

配置mAP50mAP50-95单帧推理延迟参数量
官方YOLO基线0.5810.39223ms23.7M
基线+C3k20.5870.40119ms21.3M
基线+WDBB0.6220.44325ms24.9M
基线+C3k2+WDBB0.6340.49021ms23.8M

3. 数据集、标注策略与水下图像增强

3.1 自采数据与公开数据混合

做水下目标检测,数据集的性别比——不是,是"干净数据vs退化数据"的占比,很大程度上决定了模型上真机后的表现。我们一开始完全依赖公开的水下目标检测数据集做训练,效果一般。后来我们自己搭了一个水深1.5米、长宽6x4米的室内水池,把真实垃圾样本投进去,用机器人搭载的工业水下相机在0°、30°、60°三个俯仰角度下拍摄,录制了12小时视频,抽帧得到约8500张真实水下图像。

公开数据带来的是类别多样性,自采数据带来的是部署场景的像素分布一致性。两者的比例我们最终调到了4:6,公开数据偏少一点。原因很实际:公开数据场景大多在光照较好的近岸浅水区,而我们实际作业区域包括浑浊养殖池和近海礁石区,这部分分布只能靠自采数据兜底。

3.2 标注规则的统一

水下垃圾检测的标注,最忌讳的是标准不统一。同一个目标,两个人标出来的框可能差20%。渔网这类不规则物体尤其麻烦,标矩形框会包含大量背景,导致模型学到的特征被背景污染。

我们定了几条硬性标注规范。第一,所有物体按可见区域的紧密外接矩形框标注,不把被遮挡、被水草半埋的部分硬性地标进去。第二,渔网、绳索这类无刚性轮廓目标,标"主团块",不标散落的小线头,避免一个目标产生十几个碎片框。第三,对"垃圾缠绕礁石"这种复合场景,两个类别同时标注,垃圾框和礁石框允许高度重叠,这样可以逼模型学会用上下文区分边界。第四,置信度模糊的帧直接删除,绝不带到训练集里。这些规则听起来琐碎,但直接影响模型final的精度。我们第一批数据用比较松散的规则标注,模型mAP怎么调都上不去,后来统一重标了一遍,同样的训练轮次直接涨了3个点。

3.3 水下图像预处理与数据增强

水下图像的退化不是均匀的。距离越远,散射越严重;不同水质下,颜色偏移的方向也不一样。所以我们在数据增强里加入了专门针对水下的扰动项。

除了常规的HSV扰动、mosaic、旋转、缩放之外,我们重点做了两项自定义增强。第一项是随机水下色偏模拟,在蓝绿色相区间内随机改变整幅图像的色调和饱和度,让模型适应不同水质环境。第二项是随机局部模糊,模拟水体悬浮颗粒造成的前景区域锐度下降。这两项增强在训练初期会稍微拉低收敛速度,但到了后期明显提升泛化能力,尤其是在水质环境切换时,模型不会出现性能骤降。

预处理方面,我们尝试过几种水下图像恢复算法,包括基于暗通道先验的方法,但最终在训练流程里只保留了最轻量的白平衡校正。理由很实际:暗通道类方法计算开销高,而且在某些水下场景会产生偏色伪影,反而引入新噪声。模型本身经过WDBB的抗色偏设计之后,对轻度偏色已经有足够的鲁棒性,预处理做得太重反而是负优化。

4. 训练细节与超参数的选择逻辑

4.1 分阶段训练策略

水下目标检测的训练不能一上来就用整份数据集全量开跑。我们的做法是分三阶段。

第一阶段,使用官方陆地数据预训练权重作为初始化,在公开水下数据集上训练100个epoch,学习率设置在0.01,让模型先从陆地区分特征过渡到水下大体特征。第二阶段,加载第一阶段的权重,用自采数据的干净子集微调100个epoch,学习率降到0.002,这个阶段的目标是让模型记住真实部署场景的像素分布。第三阶段,全部数据混合训练100个epoch,学习率用cosine退火从0.001降到0.0001,同时在最后30个epoch关闭mosaic增强。为什么关闭mosaic?因为mosaic生成的合成图像里包含大量拼接痕迹,在小目标细节学习上反而有害,最后阶段用自然分布数据做精细修正,mAP能再涨1-2个点。

4.2 关键超参数与损失函数调整

损失函数部分,我们在官方的分类损失、边界框回归损失和DFL分布焦点损失的基础上,重新调整了边界框损失的权重系数。水下目标边缘模糊,模型对边界框的精确定位能力天然偏弱。我们尝试把回归损失的权重从默认的0.05调高到0.08,对定位精度的提升有正收益,代价是分类损失相对被稀释,前几个epoch收敛变慢。这个举措需要配合延长前100个epoch的warmup来消化。

Batch size我们使用了64,配合多卡训练。如果显存不足,不建议把batch减半然后硬跑,因为BN层的统计量对水下图像的多尺度特征影响很大。batch太小时,BN均值方差抖动剧烈,训练十分钟就能看到损失曲线异常振荡。我们后来把输入分辨率放在640x640,batch保持64,每张卡的显存占用约22GB,这个配置下训练稳定得多。

另外EMA的设置很关键。我们给EMA衰减系数设了0.9998,保留最后20轮验证的EMA权重。实际测试中,EMA前后模型在mAP50-95上差了约1.7个百分点,这不算小数字。别偷懒,EMA一定要开,最后取权重的时机也要选在验证指标不再上升之后。

4.3 训练过程中的监控指标

训练过程中,我们不只是盯着mAP曲线,还会在验证集里单独统计几个重要类别的小目标召回率。这里有个经验:全局mAP看起来不错,往往掩盖了小目标的崩塌。我们有个内部监控面板,单独显示渔网类、玻璃碎片类、绳索类这三类目标的召回率变化曲线。一旦出现分类别召回率突然下降,那大概率是某一种数据增强策略过强了。比如有一次,我们把HSV饱和度扰动范围调大,结果整体mAP升了,但玻璃碎片类的召回率掉了5个点。因为玻璃碎片本身无色透明,过度饱和度扰动让模型把"透明"特征学乱了。这种交叉影响,不分开监控根本发现不了。

5. 模型部署、实时性与机器人决策联动

5.1 模型轻量化与推理加速

训练结束只是第一部分,部署才是另一半工程。我们目标平台是一块嵌入式GPU板卡,算力远不如训练卡,内存带宽也有限。模型从PyTorch导出到ONNX,再做半精度和int8量化。

这里我特别想强调int8量化在水下场景的坑。水下图像信噪比低,直接套用常规的量化校准数据集很容易让模型精度的下降幅度超过3个百分点。我们做int8量化的时候,专门准备了500张涵盖不同浊度、不同光照角度的真实水下图像作为校准集,绕开了默认校准集里"过干净"的样本。量化后模型的mAP50-95损失被控制在0.9个百分点以内,推理速度却从原来的21ms降到了不到10ms。如果你的板端算力吃紧,先用半精度跑通功能,再评估能不能上int8,不要一上来就量化。

5.2 如何把检测结果变成避障和抓取指令

模型的输出不能直接给机器人。我们从检测后处理到决策下发之间加了一个中间层。

  • 检测输出的每个目标框经过类别映射,分为"可打捞"和"需避让"两类。
  • 可打捞目标按置信度降序进入抓取队列,机械臂会根据目标中心坐标和估算深度执行抓取。
  • 需避让目标按最近距离排序,如果目标框下边缘接近机器人的安全距离阈值,则触发减速或转向。
  • 同一目标连续多帧的检测结果会做简单的时间滤波,避免单帧抖动导致机械臂反复启停。

这个中间层代码量不大,但对稳定性至关重要。我们最初直接把每一帧的检测结果传给控制端,结果机器人像抽风一样,一个塑料瓶刚被识别就被判定为障碍物,机械臂来回空抓。加了时间滤波和区域锁定之后,情况才正常。

5.3 延迟与功耗的实测

整条链路实测,在高清视频流输入下,从采集一帧图像到控制端收到结构化输出,端到端延迟大约是37ms。这个延迟包含相机曝光传输约12ms、预处理约5ms、模型推理约9ms、后处理加决策映射约11ms。37ms在速度较慢的清理作业场景中完全够用,但如果机器人后期要提升移动速度或者加装自动巡航,这个延迟需要进一步压缩。

功耗这块反而更让我头疼。模型推理本身功耗还好,板卡整卡功耗在15W左右,但加上相机、补光灯、工控风扇之后,整套感知系统的功耗逼近60W。水下机器人的电池容量有限,我们不得不在补光灯亮度和帧率之间做取舍。最终选择了30FPS采集、15FPS送入检测模型的处理策略,也就是说模型在空闲帧时直接跳过推理,控制端拿最近一帧的结果做外推。视觉上损失不大,但功耗降了将近三分之一。

6. 实测表现与踩坑记录

6.1 水池封闭测试

封闭水池测试是我们最常用的一环。把垃圾样本分区域随机放置,机器人按照预设路径慢速巡航。测试结果比预期好一些:可打捞目标的整体召回率达到0.91,其中塑料瓶和金属罐两类最高,因为刚体形状规整;渔网类召回率最低,约0.78,主要问题还是形态多变和背景粘连。

但测试中也发现了一个印象深刻的坑:机器人在水池边转弯时,由于推进器搅动水流,大量原本沉在池底的细小沙粒和碎片被掀起,形成临时"雪暴"效果。画面里出现大量随水流漂移的高亮细小颗粒,模型把它们中的一部分误判为"玻璃碎片"或"其他杂物",误检率瞬间飙升到15%。这个是纯动态场景带来的问题,静态图像数据里根本模拟不出来。

我们后来在训练数据里专门合成了带动态悬浮颗粒的模拟图像,并且在后处理里加入了对小目标连续帧运动轨迹的约束——如果一个小目标框在连续多帧内移动方向与水流方向高度一致,且位移量超过了阈值,就将其标记为"疑似悬浮物",降低抓取优先级。这不算算法上的根除,但误检率被压回到了5%以内。

6.2 开放水域实测

开放水域测试选的是近海的礁石区,水深3到5米,能见度悲剧地只有1米左右。第一次下水的成绩不太好看,模型mAP直接掉了近20个百分点。分析下来发现,开放水域和室内水池最大的差异不只是浊度,而是自然光照的波动。水面波浪会不断改变底部照度,画面时而过曝时而过暗,这种亮度大幅波动的帧,模型输出极不稳定。

我们补充了两类数据:一是用不同曝光参数拍摄的同一场景帧,二是从多段视频里截取的过曝/欠曝异常帧,加入训练集。此外,把测试流程从"固定巡航"改为"短停-检测-抓取"的步进式动作模式,也就是机器人移动到目标附近后先停下来,待画面相对稳定后再执行检测。这个操作层面的改变对mAP的提升,比任何模型结构调整都来得直接。

6.3 几个典型的误检漏检案例

整理几个对我们后续改进最有价值的案例。

第一个是海胆被误判为"金属件"。海胆的棘刺在图像上呈现放射状高亮纹理,和小型金属碎片在特征空间里高度接近。我们的应对方式不是增加海胆类别,而是在数据增强中增加含海胆背景的负样本,并调整了金属件类的分类损失权重。

第二个是半埋在沙里的玻璃瓶被漏检。目标只有约15%的体积露出沙面,模型输出的置信度只有0.2左右,低于我们0.5的阈值。后来我们加入"半埋物"标注类别,将露出程度作为单独的语义特征,模型对这类场景的响应明显增强。

第三个是透明塑料袋完全融入背景。这个问题直到文章写作时仍然没有完全解决。透明塑料在低对比度水下环境里几乎没有固定纹理,单靠可见光图像很难稳定识别。我们最后的缓解手段是增加红外补光灯作为辅助光源,在检测时融合红外通道的灰度特征。有条件上双目或者声呐融合的,可以在后续版本里做多传感器融合,单纯追求模型复杂度收益有限。

7. 后续可以这样扩展

回头看我记录的这套yolo13-C3k2-WDBB版本,其实只是第一个能稳定运行的迭代。如果说最后有什么值得复盘的体会,那就是水下感知项目的成败并不完全取决于模型结构设计。数据分布的贴合度、后处理逻辑的稳健性、部署阶段的量化细节,甚至机器人的运动模式,每一项都可能比模型本身多值几个点的精度。模型永远只是整个感知系统的一个组件,而不是全部。很多团队把精力全押在调模型上,忽略了对数据和场景的理解,结果到了水下就翻车。我自己踩过的这些坑,核心收获就一条:拿到一个感知任务,先用最小模型和最少数据跑通闭环,再一步一步加复杂模块,每一步都要有指标证明它值回票价。希望这篇文章能帮正在做类似系统的同行少走几段弯路。

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

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

立即咨询