钢水罐检测这件事,听起来像是传统工业视觉里一个很垂直的细分场景,但真正做过的人才知道,它几乎是目标检测领域里最难啃的骨头之一:目标尺度大、边缘特征不清晰、环境光照剧烈变化、红外与可见光混合成像,再加上罐体表面附着钢渣导致形态千奇百怪——常规的检测框架根本hold不住。折腾了几个月,我最终把方案收敛到Mask R-CNN搭配RegNetX骨干网络,同时处理钢水罐和“未定义物体”两类目标,这里把完整的技术路线、踩坑过程和工程细节都记录下来,希望能给做工业视觉或者实例分割方向的朋友一些参考。
需要先说明,这个项目是我在某工业实验室做的模拟课题,场景原型是冶金车间的罐体转运与异物监控,所有数据和设备信息均已脱敏处理。项目中“未定义物体”不是指某个具体类别,而是指“不属于已知训练类别、但出现在关键区域内需要告警的一切目标”,比如掉落的工具、翻倒的渣块、非授权人员携带的物品等。这种开集检测需求在工业现场非常普遍,也是这个系统区别于普通检测项目的地方。
1. 项目概述与核心需求拆解
1.1 钢水罐检测场景为什么这么难
先聊聊钢水罐本身。钢水罐是炼钢工艺里盛装高温钢水的容器,外形上是一个大吨位的桶状结构,但在视觉系统里它有几个非常麻烦的特点:表面是深色金属材质,经常覆盖着氧化铁皮和钢渣,轮廓和背景的灰度差极小;罐体在吊运过程中会旋转、倾斜,不同角度下形态差异巨大;车间里蒸汽、粉尘、强光交替出现,普通摄像头拍出来的画面对比度极低。这些因素叠加起来,意味着靠传统边缘检测或者颜色阈值分割的办法,根本拿不到稳定结果。
更麻烦的是,钢水罐在产线里是移动的,经常和其他冶金设备重叠。比如吊车横梁从罐体前方经过时,在画面里会形成大面积的遮挡;罐体倾倒时,钢水的强辐射光会让周围一片过曝。所以这个检测任务一开始就需要实例级别的理解能力——不仅要找到目标在哪,还要精确到像素级轮廓,才能区分罐体、吊具、地面设备以及各种无关物体。这也是我选择Mask R-CNN的初衷:它输出的掩码能给出目标在图像中的精细占位,为后续的空间关系判断和告警规则提供基础。
1.2 “未定义物体”到底指什么
项目名字里的“未定义物体”是一个比较绕的概念,我先用大白话解释清楚。常规目标检测模型是在一个封闭类别集合上训练的,比如检测“人”、“车”、“罐体”,模型只认识这几类,其他一切物体都会被忽略。但工业现场的真实需求恰恰相反:你需要重点盯防的是“不该出现在这里的东西”,而这些物体的具体外形事先无法枚举。
举个例子,现场曾有工人在罐体附近遗落了一把扳手,扳手本身不是任何一个训练类别,但它如果掉进钢水罐口,就是重大安全隐患。传统模型绝对不会报警,因为模型眼里根本没有“扳手”这个概念。这个系统的思路是:放弃对未知物体的类别识别,转为检测“任何与已知安全目标发生空间冲突的独立前景物体”。简单说,就是用Mask R-CNN分割出罐体和其他已知目标的像素区域,然后通过背景差分、区域生长等预处理提取出不属于任何已知类别的连通区域,再判断这些区域是否进入危险边界。这样,未知物体不需要被“识别”出来,只需要被“发现”出来。
1.3 系统最终要交付什么
从工程交付的角度,这套系统包含四个模块:图像采集与预处理、实例分割推理、未定义物体发现逻辑、告警联动接口。最终交付物是一个可以跑在工控机上的检测服务,输入是车间摄像头的实时视频流,输出是两类信息:一是钢水罐的像素级掩码和位置框,二是未知物体的告警事件,附带目标在画面中的位置、面积占比和进入危险区域的时间戳。告警事件会通过消息队列推送给现场的中控平台,由现场人员二次确认,这也是我特意保留的一个人工兜底环节。
整套系统对性能的要求也很明确:单路1080P视频流,推理延时控制在200毫秒以内。因为罐体吊运速度不算快,这个延迟足够满足实时性,但也不能再低了——钢包移动过程中,如果检测结果滞后太多,空间位置判断就会失真。
2. 技术方案选型:为什么是Mask R-CNN和RegNetX
2.1 Mask R-CNN的不可替代之处
选Mask R-CNN不是因为它是“最先进”的,而是因为它在做这项任务时综合性价比最高。先看其他方案:如果只做钢水罐位置检测,基于YOLO系列的目标检测就够了,速度快、部署简单,但YOLO给不出来像素级轮廓,只有矩形框。矩形框在罐体检测里有个致命弱点:罐体是斜的、圆的,矩形框会把大量背景算进目标区域,导致后续的空间冲突判断严重失真。而如果换成纯分割模型比如U-Net,又没有实例概念,两个罐体连在一起时会被合并成一个整体,无法区分编号。
Mask R-CNN是“检测+分割”的混合体,它先通过区域建议网络找出候选框,再在候选框里做像素级分类。这意味着它天然区分不同实例,同时精度能达到像素级别。在钢水罐场景里,我需要知道罐口朝向哪里、罐体是否倾斜、罐口边缘是否与异物重叠,这些需求只有实例分割能满足。另外,Mask R-CNN的两阶段结构对目标外观变化比较鲁棒,不像单阶段模型那样依赖严格的锚点设置——钢水罐形态多变,这个特性很实用。
2.2 RegNetX当骨干网络的优势
骨干网络的选择,按常规思路会用ResNet50或者ResNet101,这也是Mask R-CNN最经典的搭配。但ResNet有两个问题在这个场景里被放大了:一是参数量大,推理速度不够理想;二是ResNet的通道数配置是手工设计的,拿来迁移到工业场景时,特征提取效率不是最优。
RegNetX是我在一次对比测试中发现的替代方案。它是基于搜索空间设计出来的网络族,核心思想是把网络宽度、深度、分组数等超参放在一个参数化空间里统一搜索,最终得到一组规则化的网络配置。相比ResNet,RegNetX在同等FLOPs下的精度更高,推理时延更低。我选的是RegNetX-4.0GF这个档位,权重文件大小适中,在工控级的GPU上能达到不错的实时性。
从实际的迁移效果看,RegNetX作为骨干网络有一个直观的好处:它对纹理较弱的深色物体——比如钢水罐表面那种低对比度区域——能保持更好的特征响应。这可能是因为RegNetX设计空间里对channel width和组卷积的配置更均衡,深层的语义特征保留得更完整。当然这只是我的经验性观察,没有做严格的消融实验,但最终测试里RegNetX确实比ResNet50稳定。
2.3 选型对比与取舍记录
测试过程中我做了几组对比,具体数据就不贴了,给出结论性的经验值供参考。
| 骨干网络 | 推理时延(ms) | mask mAP | 训练收敛速度 | 现场稳定性 |
|---|---|---|---|---|
| ResNet50 | 95 | 中等 | 较快 | 小目标漏检多 |
| ResNet101 | 140 | 较高 | 慢 | 精度高但跑不满实时 |
| RegNetX-4.0GF | 80 | 较高 | 中 | 综合表现最均衡 |
这里需要说明,时延是在同一块推理卡上测的,包括预处理和后处理。RegNetX不是在所有指标上都吊打ResNet,但它在“精度可接受”和“速度够用”之间找到了最好的平衡点。特别是当系统还需要跑额外的未定义物体检测逻辑时,骨干网络的推理速度余量非常重要。
3. 数据集构建与标注工程实战
3.1 现场数据采集方案
数据集决定了模型的上限,这句话在这个项目里感受特别深。一开始我试图用公开数据集做迁移,但很快发现工业场景的域差异太大了:公开数据里的容器类物体大多是干净、光照均匀的日常场景,钢水罐那种高温、粉尘、低对比度的画面完全不在同一个分布里。
数据采集我做了三路并行。第一路是在实验场地的模拟工位拍摄,用1:1的缩比模型模拟罐体在不同角度、不同光照条件下的状态;第二路是从现场的监控视频里截帧,每隔2秒抽一帧,覆盖白天、夜间、蒸汽干扰、强光直射各种工况;第三路是做合成数据,用渲染引擎把三维罐体模型摆到不同背景里生成图像,再用脚本自动生成掩码标注。
三路数据合在一起,最终筛选出大约12000张有效图像,其中现场真实帧占60%,模拟场占25%,合成数据占15%。训练集和验证集按8:2切分,注意切分时必须保证同一个罐体连续轨迹的画面只在训练集或只在验证集,避免数据泄漏导致评估指标虚高。
3.2 标注规范与质量把控
钢水罐的标注不是简单的框选,需要用多边形工具精确勾勒罐体轮廓。但真实数据里,罐体边缘经常和背景融合在一起,标注员很难分辨边界。我定的规则是:罐口边缘以最明显的亮度跳变点为准,罐体侧边以钢渣堆积轮廓为准,被其他设备遮挡的罐体部分不纳入掩码范围,但要给出被遮挡的完整矩形框——因为后续判断空间关系时,需要知道罐体的实际占地范围。
质量控制分两层。第一层是交叉标注,每张图由两个人独立标注,用IoU衡量一致性,低于0.9的需要返工。第二层是算法预筛,用预训练模型跑一遍所有图像,找出预测掩码和标注掩码差异大的样本,人工重点复查。这套流程听起来繁琐,但在实例分割任务里值得投入,因为掩码标注质量直接决定分割边界的精细度,而分割边界又直接决定未定义物体检测的准确性。
3.3 数据增强与样本平衡
工业场景数据增强不能乱用,这一点吃过亏。我最初套用了常规的图像增强组合,包括随机翻转、随机裁剪、颜色抖动,训练时发现验证集mAP不仅没提升,反而掉了一点。原因是钢水罐的外观特征对翻转是完全对称的,没问题,但颜色抖动改变了罐体表面钢渣和氧化铁的色偏分布,这和真实场景不符,属于引入无效甚至有害的域偏移。
调整后的增强策略是:保留随机翻转、随机缩放(0.8到1.2倍)、随机旋转(角度限制在10度以内)、高斯模糊模拟蒸汽干扰、随机亮度和对比度调整模拟车间光照变化。这些增强手段都控制在“不改变物体本质外观”的范围内。另外,样本不平衡问题也明显:正常状态的罐体图片很多,但罐体倾斜、罐口有钢渣、强光过曝等边缘状态的图片很少。解决办法是对稀少状态做过采样复制,同时配合马赛克增强——把4张不同状态的图片拼接成一张训练样本,让模型在单次迭代里看到更多样化的外观。
4. 模型训练与调参全过程
4.1 迁移学习与骨干网络冻结策略
训练起步时必须用预训练权重,从头训练工业分割模型基本没有可能。我用的方式是:加载在COCO上预训练的Mask R-CNN权重,其中RegNetX骨干网络部分先冻结5个epoch,只训练RPN和检测头/掩码头。这背后的考虑是,骨干网络提取的是基础视觉特征,比如边缘、纹理、颜色分布,这些通用特征在COCO上已经学得很好了,不需要在早期大规模调整;而检测头和掩码头的任务语义是和具体类别强相关的,需要从第一轮就重点训练。
5个epoch之后再解开骨干网络,使用较低的学习率微调全部层。微调时需要注意:RegNetX和ResNet的网络结构差异较大,加载预训练权重时,部分层的名称和维度对不上,不能直接用torch的load_state_dict,需要写一个映射脚本,把COCO预训练权重里的key对应过去,缺失的层用默认初始化。
4.2 关键超参设定与理由
参数设定上,我踩了不少坑,给出最终的配置和理由。
学习率用1e-4作为基准,配合余弦退火策略。最开始我用固定的1e-3,前两个epoch还好,第三个epoch损失开始震荡,loss曲线上下跳得很厉害,典型的lr过高表现。降到1e-4之后稳定多了。batch size定为8,这是单张显卡的显存上限。Mask R-CNN对batch size比较敏感,因为它的loss包含多个分支的加权和,batch太小的话RPN的采样不稳定,导致训练早期loss波动大。
RPN部分,anchor的比例设置成[0.5, 1.0, 2.0],另外加了[3.0]这个比例,专门适配细长形状的物体——比如天车吊钩、工具杆这些潜在异物。anchor的大小按[32, 64, 128, 256, 512]的尺度设计,和输入分辨率对应。还有ROI Align的采样分辨率设置成7x7,输出mask的分辨率是28x28——这是Detectron2的默认值,对于钢水罐这种大目标来说28x28的掩码分辨率略显粗糙,但改大会明显增加显存消耗,权衡后先维持默认,后期用后处理来平滑边界。
4.3 训练过程观察与收敛判断
训练了大约80个epoch,总耗时一天半。前20个epoch里,总loss从2.5缓慢降到1.0左右,mask分支的loss下降速度明显慢于检测分支,这正常,因为像素级分类比框分类难。40个epoch之后,mask分支的loss降到0.4左右,模型已经能稳定分割出罐体的主体轮廓。但从验证集可视化结果看,罐口边缘的掩码仍然有锯齿状缺口,钢渣覆盖区域经常被误判为背景。
这时候我做了一个关键决定:用更小的学习率3e-5继续调10个epoch,同时放宽掩码分支的loss权重,让模型更关注边缘细节。效果是mask mAP提升了约2个百分点,锯齿问题有所改善。收敛判断依据是验证集mAP不再明显上升,我习惯再跑5个epoch确认没有过拟合迹象。关于过拟合,工业场景数据集规模有限,确实容易出现训练loss很低但验证mAP上不去的现象。我用的缓解手段没有用dropout或weight decay超标,而是靠数据增强的多样性来硬扛。
4.4 模型评估指标选择
实例分割模型的标准评估指标是COCO的mask mAP和mask mAP@0.5:0.95,但在这个项目里我会额外关注mask mAP@0.5——因为工业告警系统更看重“目标有没有被覆盖住”,而不是“分割边界的精确程度”。从实际效果看,mask mAP@0.5稳定在0.94左右,mask mAP@0.75在0.87左右,这说明定位基本可靠。另外我还单独评估了小目标检测能力,把面积小于图像1%的目标单列统计,漏检率在3.5%左右,主要集中在距离摄像头较远的区域——这为后续的摄像头布点优化提供了依据。
5. 未定义物体检测机制的设计
5.1 开集检测的工程近似方案
既然模型无法识别未知物体,那怎么让系统发现它?我的做法是走“排除法”。具体流程如下:先跑一次Mask R-CNN,拿到钢水罐和其他已知目标(比如人员、天车)的像素掩码;然后对原始图像做背景建模,提取出“不属于静止背景”的前景区域;把这个前景区域和所有已知目标掩码做差集运算,剩下那些“有运动、但不在任何已知目标里”的连通域,就视为未定义物体候选。
这里的关键点是背景建模。工业车间里背景不是静止的:地面反光会变、蒸汽会飘、灯光会闪烁,因此不能用简单的帧差法,我用的是改进的高斯混合模型(MOG2),学习率设置成0.02,对光照变化比较鲁棒。实测下来,背景建模的误检率偏高,因为它会把罐体本身的姿态变化也当作前景——罐体旋转时轮廓变化剧烈,几乎必然被MOG2当成运动目标。我的解决办法是对罐体掩码区域做膨胀处理,把罐体周围的一圈像素都排除在“未知物体”判断之外,这样罐体自身运动和轻微抖动不会触发告警。代价是紧贴罐体边缘的小物体可能漏报,但考虑到安全问题宁可漏一点也不能让告警风暴淹没中控室。
5.2 后处理规则与告警联动
未定义物体候选出来后,还需要一套规则决定是否需要告警。我设计了三个判断层级。第一层是面积阈值:候选区域的像素面积必须大于80个像素,小于这个值的噪声直接滤除。第二层是驻留时间:目标必须在连续5帧以上都被检测到,才判定为“稳定出现”——这个设计大大减少了飞鸟、飘浮的粉尘颗粒带来的误报。第三层是危险区域判定:把罐口中心向外扩展30像素作为危险边界,候选区域的几何中心落入这个边界内才触发告警。
告警事件会写成一个结构化消息,包含目标掩码、时间戳、位置坐标和置信度,通过MQTT推送给中控平台。中控平台上有一个人工确认界面,操作员看到告警后可以选择“挂起”或“忽略”并给系统反馈。这些反馈积累起来是后续迭代的重要数据——比如某个位置频繁告警但人工大多忽略,就说明该区域的规则参数需要调整。
5.3 误报控制与阈值寻优
误报率是这个系统能否落地的关键。试运行期间每天产生80到150条告警事件,其中约75%是误报,主要来源是钢水表面辐射导致的热噪声、地面水渍反光以及摄像头上的飞虫。我花了不少精力做阈值寻优。
面积阈值从最初的50像素调高到80像素,误报率下降了约18%;驻留帧数从3帧调高到5帧,误报率再降约12%。但注意,阈值不是越高越好,调高后漏报率也随之上升——现场工人反馈说小件工具掉落没有被发现。最终我采用了一个动态策略:白天和夜间的阈值不同,白天光照充足、画面噪声大,面积阈值取80;夜间噪声小,面积阈值降到60。这个动态策略不算复杂,但效果比单一固定阈值好得多。
6. 部署实践与推理优化
6.1 硬件选型与部署架构
部署环境是现场的工控机,配置了一张中端的工业级推理卡,显存8GB,CPU是8核的Xeon级别处理器。整个推理服务用Docker容器封装,模型用TensorRT导出的engine文件加载。架构上是典型的单机多路视频处理:取流模块通过RTSP拉取摄像头画面,做抽帧和缩放后送进推理队列,推理结果通过消息队列转发给上层应用。
8GB显存是限制条件。Mask R-CNN全精度模型占用约2.5GB显存,同时处理两路视频流就会逼近显存上限。因此我做了两个优化:一个是用TensorRT的FP16推理,显存占用降到1.3GB左右;二是把预处理任务放在CPU端,只让TensorRT处理GPU计算部分。最终可以同时运行4路视频流,每路推理时延约80毫秒,满足要求。
6.2 TensorRT加速与精度保持
TensorRT加速实例分割模型有几个常见问题需要处理。Mask R-CNN里的ROI Align和Proposal层在TensorRT里的适配比较麻烦,需要自定义插件。我用的是社区已经适配好的插件实现,但在导出时发现插件版本和TensorRT版本不匹配会报错,折腾了一晚上才找到原因。所以这里有个关键经验:记录好所使用的框架版本和插件版本,别盲目升级。
FP16精度损失在这个场景里几乎察觉不到,mask mAP下降不到0.5个百分点,对于工业告警应用完全可接受。但如果你的场景对分割边界精度要求特别高,建议对FP16做逐层敏感性分析,找出哪些层需要回退到FP32。这个项目里我没做逐层分析,因为测试阈值之下,FP16的掩码边界和FP32在肉眼上基本看不出差异。
6.3 日志监控与模型迭代
部署系统必须做好监控,否则模型漂移会让你在不知情的情况下失去检测能力。我做了三个维度的监控。第一个是推理时延监控,统计P99时延,连续超过300毫秒就报警,说明GPU计算可能有瓶颈或视频流出现卡顿。第二个是推理结果监控,统计每秒检测到的目标数量,正常情况下应该在一定范围内波动,如果突增说明模型可能出现了幻觉——比如蒸汽干扰导致大面积误判。第三个是告警确认率监控,现场操作员对告警的确认率如果持续走低,说明告警质量在恶化,需要重新评估阈值或更新模型。
模型迭代是持续性的工作。我设了一个每月一次的重新训练计划,把过去一个月的误报样本和漏报样本收集起来,加上新增的真实标注,重建训练集微调模型。这样能保证模型始终贴合当前现场的实际工况,避免几个月后因为设备外观磨损、车间改造等原因导致精度下降。
7. 实测效果与踩坑记录
7.1 现场测试数据与运行表现
系统在实验平台连续跑了两周,统计下来基本能达到设计要求。钢水罐的检测召回率在98%以上,漏检主要发生在罐体被大型设备完全遮挡的瞬间——这个场景我认为可以通过增加一个侧方位摄像头来解决,单路相机的信息确实不够。分割掩码的边界精度在罐体轮廓清晰时很好,但在低对比度场景下边界会有5到8像素的偏移,考虑到罐体本身有半米以上的物理尺寸,这点偏移在空间判断上完全可接受。
未定义物体检测的告警准确率大约65%,误报集中在蒸汽扰动和水渍反光。这个准确率乍一看不高,但别忘了它的任务是“发现任何未知目标”,本身就是在做开集检测,误报率可以通过人工反馈不断压缩。更让我满意的是,系统在运行期间确实发现了几次有价值的异常事件——比如一次现场人员遗落的测温枪,虽然最后没有造成实际影响,但证明了这个机制在真实使用中是有作用的。
7.2 经典问题排查速查表
把踩过的坑整理成一个表,方便后续同学排查类似问题。
| 现象 | 可能原因 | 排查方向 |
|---|---|---|
| 训练loss不下降 | 学习率过高或过低 | 检查lr曲线,尝试log-scale网格搜索 |
| 掩码边缘锯齿严重 | mask分辨率不足或后处理缺失 | 增大mask head输出分辨率,加CRF后处理 |
| 小目标漏检 | anchor尺度覆盖不够 | 增加小尺度anchor,或提升输入分辨率 |
| 未定义物体误报多 | 背景建模学习率不合适 | 调整MOG2的learning rate和history参数 |
| TensorRT导出报错 | 插件版本与TRT版本不匹配 | 核对插件源码的适配版本,不要盲升 |
| GPU显存OOM | batch size过大或输入分辨率过高 | 减小batch,使用FP16,或者裁剪输入尺寸 |
| 蒸汽干扰导致误检 | 数据增强里缺少蒸汽样本 | 增加高斯模糊样本,或加入真实蒸汽帧 |
7.3 个人实操心得
最后分享一点个人体会。工业视觉项目和学术demo最大的区别是:不是模型越复杂越好,而是系统越可靠越好。Mask R-CNN做钢水罐分割,技术上不算新奇,但真正把它部署到产线上,要考虑的问题全在工程细节里。模型训练只占整个项目不到三分之一的精力,剩下的时间几乎都花在数据标注、规则调优、误报控制和部署适配这些“脏活累活”上。
如果让我重新做一遍,我会更早开始做未定义物体检测的规则设计。这个模块在项目初期容易被忽略,因为大家都以为“检测出已知目标就够了”,但实际现场反馈里,更值钱的反而是对未知物体的发现能力。把它前置到架构设计阶段,和主检测模型一起联调,可以省掉后面很多重复工作。
另外一个经验是:任何工业检测系统都要给自己留一个人工确认的兜底口子。哪怕模型再准,现场出一次重大误报就会让用户对系统失去信任;反之,如果每次告警都有一个人工复核的流程,即使准确率只有60%,用户也愿意持续用下去。这个项目里,中控平台的人工确认反馈机制是我最不后悔的设计。