ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

基于PaddleSeg的钢筋长度超限监控方案与落地实践

基于PaddleSeg的钢筋长度超限监控方案与落地实践 钢筋定尺剪切之后“长度超限”这四个字能让加工厂质检负责人头大一整晚。我这边在上一套基于PaddleSeg的钢筋长度超限监控方案之前也差不多在这个问题上耗了小半年。超长料混进合格品轻则打包断线、装车超宽重则整批被客户退回到那时再想解释是哪根料出了问题根本说不清楚。这篇内容我按自己完整落地的顺序来写从产线痛点、方案选型、相机标定、数据标注、模型训练一直讲到部署接PLC和现场排障。里面所有参数都是常见量级的参考值具体到你自己的产线相机安装距离、允许偏差这些一定要重新测不能直接抄。1. 定尺切“超长”一条产线的真实痛点1.1 超长钢筋从哪里来剪切链路的三个误差源很多人以为定尺剪切是“切一刀就固定长度”上了产线才发现完全不是这么回事。钢筋在辊道上高速行进靠测长轮或者编码器累计长度到设定值触发飞剪这个链路里至少有三个地方会积累误差第一个是测长轮打滑。钢筋表面带着氧化皮和水膜测长轮压上去后偶尔空转丢掉的脉冲直接变成长度误差。轮子用久了直径还会磨损每个脉冲对应的长度本身就变了这是机械层面的缓慢漂移。第二个是热态和冷态的差异。很多厂是热剪切钢筋剪切时温度可能还在几百度冷却之后会收缩。如果剪切系统没有做温度补偿或者补偿系数是根据昨天、上周的炉温拍脑袋定的今天换了一炉钢温长度就跟着偏。第三个是飞剪本身的响应延迟。钢筋速度波动时剪切信号发出到刀口真正落下有一段时间差这段延迟内的位移是动态变化的。切出来的每一根料长度并不是一条直线而是一个有波动的分布。这几类误差叠加起来超长并不稀奇稀奇的是没被发现。1.2 人工抽查为什么兜不住这个隐患很多厂现在的做法是质检员拿卷尺在冷床旁边抽检一百根里量个四五根。问题就在于抽检根本不是连续覆盖漏掉一根超长料后面打包、装车、工地使用才会爆雷。更现实的是定尺12米的钢筋一个人来回量也费劲现场有高温、粉尘、噪声要求工人每隔几分钟就去量一次本身就不符合人的生理极限。夜班和交接班时段注意力下降漏检率更高。所以我当时立项的时候跟领导说得很直接这个岗位的痛点不是人不努力是人工抽检这个模式在物理上就覆盖不住所有料。2. 方案选型为什么最终落在PaddleSeg上2.1 传统机器视觉方法在钢筋场景的局限最早我也被建议用传统机器视觉毕竟以前做过不少“找边、测量”的项目。但钢筋端部这个场景有个特点它根本不是一条干净的直线或圆弧。出轧之后的钢筋端头带氧化皮、毛刺、铁屑有时还有水渍和油污。自然光下拍摄金属表面会出现大范围镜面反射阴影和反光的边界跟真实端部混在一起。传统方法里最常用的阈值分割光照一变就得重新调阈值今天晴天一个参数明天阴天又不行。Hough直线找边就更勉强钢筋端头轮廓经常是不规则曲线强行拟合直线误差大得没法用。这不是说传统视觉不行而是它适合“受控环境里的演示”不适合产线上一年四季、白班夜班连续运行。2.2 PaddleSeg解决了什么问题从“框”到“掩膜”如果换成目标检测模型比如YOLO它会输出一个框住钢筋的矩形。但矩形框有个麻烦框的边界并不等于钢筋的真实边界尤其是端部往往会被阴影或背景干扰框边要么切在阴影里要么多出一段背景。我们的下游计算是“端部极值点坐标”这需要知道钢筋在图像里精确占了哪些像素。语义分割正好干这个事它对每个像素做分类钢筋区域的边界能做到像素级后面再基于连通域做统计端部位置就稳定得多。PaddleSeg这个框架在国内工业场景用得挺广中文文档完整训练、评估、导出、部署一条链都是现成的团队上手成本低。它自带的PP-LiteSeg等轻量模型对部署环境要求不苛刻一台RTX级别的工控机就能跑得很顺。2.3 模型选型对比PP-LiteSeg、BiSeNetV2与DeepLabV3当时我对比了三个模型方向都是在PaddleSeg里直接改配置文件就能跑的模型特点我实测的大致单帧耗时FP32适合场景PP-LiteSeg-T轻量、速度快、显存占用小RTX 3060上约15-25ms高速产线、边端部署BiSeNetV2实时性好但细长物体分割要多试RTX 3060上约10-20ms实时性要求更高的场景DeepLabV3 ResNet50精度高模型大、推理慢约80-150ms离线统计或服务器端处理我最终选了PP-LiteSeg-T。原因是钢筋这种“细长条”物体在高分辨率图像里占的像素不算少不需要特别大的感受野轻量模型在产线工控机上能跑出稳定帧率后续加帧间滤波时还有性能余量。如果你现场用的是Jetson这类低功耗设备优先考虑PP-LiteSeg-T的量化版本效果和速度会更平衡。注意这块的耗时数据只代表我自己的测试环境不同分辨率、不同光照、不同GPU驱动版本都会有波动。选型时拿你自己的现场图像跑一遍再定不要只看网上公开的benchmark。3. 相机、光源与标定先让图像“能测”3.1 硬件选型与安装位置测量类视觉项目里图像采集质量决定了整个系统的上限模型只能在图像质量之上做补救。所以我先把相机和镜头方案定死。我用的是500万像素GigE工业相机分辨率大约2448×2048。视场范围设定在600×450毫米左右算下来单像素对应约0.24毫米这个精度对长度超限监控来说足够用。如果只监测端头局部区域视场还可以再缩小精度会更高。镜头选择上我建议8到16毫米的定焦镜头光圈收到F8-F11别用最大光圈。钢筋在辊道上多少会有跳动景深太小容易拍虚稍微虚一点分割出来的端部边界就会抖测量值跟着跳。安装位置的核心原则是相机光轴尽量垂直于钢筋轴线拍端头所在平面相机离端头区域保持一个固定距离然后用支架锁死。现场振动大的话支架上要加减振垫别直接拧在振动剧烈的机架上。相机加防护罩配合气吹或风冷防止铁屑粉尘落在镜头上。3.2 光源方案与防腐防尘设计钢筋是金属曲面如果光源直射上去会产生高光的镜面反光导致图像里端头区域直接过曝过曝区域在分割时会被当成背景端部坐标就偏了。我试了几种方案最终用了低角度前向光加漫射板的组合。光线从侧面低角度打过去钢筋与背景之间的灰度差稳定端头的反光也不至于过曝。这里有个教训千万别为了“对比清晰”去用背光方案。背光下毛刺和铁屑会在端头前方投射出虚假阴影阴影边缘很容易被模型误判成钢筋边界。光源尽量用常亮灯不要用闪光。产线是连续触发的闪光灯的寿命和散热都会出问题。红外光源也是一个选项好处是可以搭配红外滤光片把现场可见光干扰挡掉但红外下钢筋和背景的灰度差需要重新验证。3.3 像素-毫米换算和镜头畸变修正很多人只算“一个像素等于多少毫米”忽略镜头畸变结果边缘区域测出来偏大或偏小。我这边用OpenCV的棋盘格标定先拿现场相机拍十几张不同角度的标定板用cv2.calibrateCamera算出内参和畸变系数在每次推理前对图像做cv2.undistort。做完畸变修正之后再把标定板平放在钢筋端面所在的平面拍一张图对图像做透视校正。为什么要透视校正因为相机很难做到绝对垂直于钢筋轴线稍微有一点倾角图像上的长度比例就不是均匀的左边一个比例、右边另一个比例。校正完得到单应性矩阵后用标定板上已知距离的两个点换算像素-毫米比例。我建议把这个换算系数写进配置文件不要每次启动程序都重新标定但每隔一个月检查一次因为相机会因为振动产生轻微位移换算系数会漂。4. 数据标注与模型训练把钢筋端部稳定抠出来4.1 标注规范与数据增强模型要分割的目标很简单背景一类钢筋区域一类。但数据标注的质量直接决定后端测量稳不稳。我团队用PaddleSeg配套的EISeg做交互式标注第一轮标了500张一张图大概30到60秒。标注时有一个硬性规范端头被阴影或者铁屑遮挡的部分按可见像素标不要凭想象把钢筋“补全”。原因很简单后端要算的是极值点你多补一段端部坐标就多偏一段。数据增强里我开了随机亮度、对比度、饱和度扰动模拟白天晚上光照变化。还加了小幅旋转和缩放。有一点要特别提醒如果你跟我一样后台要用掩膜判断左右端部水平翻转这种增强要谨慎。因为翻转后极值点方向变了训练时模型虽然无所谓但下游逻辑如果写死了“右侧是端部”遇到翻转过的图像就会出问题。我采用的是只做垂直翻转不碰水平翻转省得后期给自己埋坑。4.2 一次可复用的训练配置PaddleSeg的训练配置是YAML我用的是PP-LiteSeg-T下面这个是能直接改路径跑起来的基础配置exp_name: rebar_length_overshoot model: type: PP_LiteSeg_T num_classes: 2 backbone: type: STDC2 pretrained: true train_dataset: type: Dataset dataset_root: ./data/rebar num_classes: 2 train_path: ./data/rebar/train_list.txt mode: train transforms: - type: ResizeStepScaling min_scale_factor: 0.5 max_scale_factor: 1.5 scale_step_size: 0.25 - type: RandomDistort brightness_range: 0.6 contrast_range: 0.6 saturation_range: 0.6 - type: RandomVerticalFlip - type: Normalize val_dataset: type: Dataset dataset_root: ./data/rebar num_classes: 2 val_path: ./data/rebar/val_list.txt mode: val transforms: - type: Normalize optimizer: type: SGD momentum: 0.9 weight_decay: 0.0005 learning_rate: value: 0.01 decay: type: poly power: 0.9 end_lr: 0.0001 loss: types: - type: CrossEntropyLoss - type: DiceLoss coef: [1.0, 0.5] batch_size: 8 iters: 30000 log_iters: 100 eval_iters: 1000 save_interval: 3000训练命令很简单python tools/train.py --config configs/rebar_seg.yml --do_eval --save_dir output/rebar_seg这里说下损失函数为什么要叠加DiceLoss。钢筋分割里背景占比很大钢筋区域相对小纯CrossEntropyLoss会让模型倾向于把所有像素预测成背景端部细节丢失。加DiceLoss之后模型会更关注前景区域的重合度端部的轮廓保留得更好。4.3 验收指标别只看mIoU训练结束后我会同时看两个指标一个是PaddleSeg输出的mIoU另一个是自己写脚本算的“端部极值点偏差”。mIoU能反映整体分割质量我这边最终跑到94%左右但这个数值不能直接证明测量能用。真正的验收口径是随机抽200张验证图人工标出每根钢筋端部真实坐标跟模型预测掩膜的极值点坐标对比统计平均绝对误差和最大误差。我当时的验收线是平均绝对误差小于2毫米最大误差小于5毫米。如果最大误差太大多半是某几张图里端头反光导致掩膜断裂这时候不是单纯加数据的问题而是回到采集端调光源。5. 超限判定逻辑从掩膜到报警信号5.1 端点坐标提取连通域与极值点拿到模型输出的0/1掩膜后下一步是提取端部坐标。我的处理思路是先做形态学闭运算把掩膜里因为反光造成的小孔和断裂补上然后找连通域对每个连通域取坐标极值。核心代码大概是这样的import cv2 import numpy as np def extract_tail(pred, min_area80, tail_side-1): # pred: 0/1 mask1 表示钢筋 mask np.where(pred 1, 1, 0).astype(np.uint8) # 闭运算补洞防止反光把钢筋拆成两段 mask cv2.morphologyEx( mask, cv2.MORPH_CLOSE, np.ones((3, 3), np.uint8), iterations2 ) num, labels, stats, _ cv2.connectedComponentsWithStats(mask, 8) results [] for i in range(1, num): area stats[i, cv2.CC_STAT_AREA] if area min_area: continue x stats[i, cv2.CC_STAT_LEFT] y stats[i, cv2.CC_STAT_TOP] w stats[i, cv2.CC_STAT_WIDTH] h stats[i, cv2.CC_STAT_HEIGHT] if tail_side 0: tail_x x w else: tail_x x results.append((area, (tail_x, y h // 2))) return resultstail_side取决于相机安装方向。如果钢筋在图像里从左往右走端部在右侧就取x w反过来取x。这里不要用整张图的最大值坐标因为一旦画面里出现背景杂物整图极值点会被带跑。按连通域逐个算更稳。5.2 超限量计算与判定阈值设计有了端部像素坐标超限量计算就是一行公式over (tail_x - ref_x) * mm_per_pxref_x是基准线在图像里的坐标。基准线可以是一个物理挡块、料框边缘或者画在设备上的一条永久刻度线。在标定阶段用标定板量出基准线像素位置写进配置文件。超限量大于0表示钢筋比基准线多出一截小于0表示短料。实际阈值设计要考虑测量本身的波动。比如测量误差±3毫米而你要求的报警线是超长40毫米那最终报警阈值要设在45毫米左右留出误差余量否则一根刚好卡在40毫米边上的料会反复触发报警。我用的是带死区的判定逻辑超长超过45毫米才报警但报警之后要等超长回落到35毫米以下才复位。这样一个料在生产线振动中轻微抖动也不会让报警灯一会儿亮一会儿灭。如果现场允许还可以连续拍三帧取三个超限量的中位数至少两帧超限才算数能滤掉偶发的分割抖动。5.3 多根钢筋同时出现的拆分处理如果场景是单根钢筋连续过检上面那段代码直接够用。但你要是想监控一捆钢筋端头有没有冒出的料就需要处理多个目标。多个端面在图像里如果彼此不接触连通域统计就能拆分。一旦两根钢筋靠得很近、掩膜连在一起单纯连通域会把它们当成一根。我试过两种办法一是把相机安装高度提高增大俯视角度让端面在透视关系下自然分离这个最省事二是用距离变换加分水岭把粘连区域切开。不过要提醒一点如果一堆钢筋端头紧密排列语义分割只能告诉你“哪些像素是钢筋”并不能天然区分“这是第几根”。真要做到逐根独立测量要么改变相机角度让它们在物理上分开要么升级到实例分割。对长度超限监控来说很多时候你不需要知道具体第几根你只需要知道“这捆料端部整体冒出去超出基准线了”那直接取整个掩膜的极值点就够了。6. 部署落地导出模型、接PLC、处理现场噪声6.1 模型导出与推理加速PaddleSeg训练完的模型是动态图参数部署前要导出成推理模型python tools/export.py --config configs/rebar_seg.yml \ --model_path output/rebar_seg/best_model/model.pdparams \ --save_dir export/rebar_seg导出后就是.pdmodel和.pdiparams可以直接用Paddle Inference加载。我在Python端的推理代码就几行import paddle.inference as paddle_infer config paddle_infer.Config( export/rebar_seg/model.pdmodel, export/rebar_seg/model.pdiparams ) config.enable_memory_optim() if use_gpu: config.enable_use_gpu(256, 0) predictor paddle_infer.create_predictor(config)如果现场工控机是CPU或低算力设备可以把模型转成ONNX再换成TensorRT或者OpenVINO跑。命令大致是paddle2onnx --model_dir export/rebar_seg \ --save_file export/rebar_seg/model.onnx \ --opset_version 12 --enable_onnx_checker转ONNX之后精度通常会掉一点点但推理速度能快不少。我做这一步前会在验证集上重新跑一遍端部极值点偏差确认没超标再上线。6.2 PLC联动的信号链路超限检测的目的不是给屏幕上看个数字而是要触发下一步的剔除或报警动作。我这边信号链路是这样设计的光电传感器检测到钢筋到达拍照位给相机触发信号。相机采集一张图像程序跑分割和超限判定。判定结果通过工业IO卡的干接点输出给PLC的DI点。PLC拿到信号后在钢筋到达下游剔除工位时启动气动推料机构把超长料推出辊道。这里要注意时序。产线速度比如3米/秒拍照点到剔除点之间必须留出足够的缓冲距离。推理本身一次只要几十毫秒问题不大真正要算的是PLC从收到信号到推料机构动作的延迟以及机械反应时间。这个缓冲距离没算够的话系统检测出来了但料已经跑过去了等于白做。如果现场需要把检测结果记录进MES系统我建议PLC负责实时动作上位机程序另外通过Modbus TCP或TCP JSON上报数据不要把MES通信跟实时判定混在同一条链路里否则网络一抖剔除动作也跟着抖。6.3 踩坑排查曝光、抖动和模型漂移上线后最容易出问题的不是模型而是现场环境变化。我举一个真实的排查过程。现象系统跑了几天一直稳定某天下午开始误报率突然从0.1%涨到8%。我打开日志里保存的图片一看所有钢筋端头都有一块高光分割掩膜在高光处断开连通域被拆成两半端部极值点落到了高光前面的铁屑上。追溯原因那天是阴天后突然转晴车间顶部的高位照明恰好把阳光反射到钢筋端面造成局部过曝。模型本身没问题但输入图像已经不是训练集的分布了。修复分两步第一步把相机增益调低一点同时调整低角度光源方向削弱镜面反射第二步在训练数据增强里加强了随机亮度扰动并专门收集了这种高反光场景的图像补进训练集。从那以后我再也没有只依赖单一光源而是每次大气候条件变化后都会去现场看一眼实时画面。模型漂移也是个长期问题。钢筋表面状态会随季节、供应商、轧制批次变化。我的做法是上线后每周自动保存被判定为超限的图片人工挑出分割效果差的样本攒够一两百张就增量训练一次。PaddleSeg支持从上次权重继续训练命令行加--resume就行不用每次从头来。7. 实际运行效果与后续扩展7.1 实测数据与验收结果说几个我这条线的实测数据大家参考时注意这只是单个产线的表现不代表所有现场都能复现。分割模型验证集mIoU在94.2%端部极值点平均绝对误差1.8毫米最大误差5.1毫米最大误差出现在直径25毫米规格的高振动工况下。连续运行三个月后抽检了1000根料实际超长的料全部被系统检出误报率在0.3%左右误报主要集中在大规格钢筋剧烈跳动、端头完全离开景深范围的瞬间。在线性方面PP-LiteSeg-T在RTX 3060工控机上单次推理约20毫秒加上图像采集和判定逻辑单根钢筋从拍照到输出IO信号大概35到40毫秒完全满足产线节拍。7.2 可以继续做的三件事这套系统跑稳之后我给它规划了三个改进方向。第一个是多规格自适应。不同直径的钢筋在图像里的像素宽度差异很大可以在相机触发时从PLC读来当前规格号动态切换不同的ROI区域和多套判定阈值减少背景杂物干扰。第二个是端头缺陷联动。既然已经有了像素级掩膜端头切斜、毛刺过大这些信息也顺带能算出来。可以把它们作为质量指标输出给下游而不是只盯长度一个维度。第三个是工艺闭环。把连续一段时间内全部钢筋的超限统计值反馈给飞剪的定尺补偿系统。如果超限均值持续为正说明定尺设定偏长自动调低设定值均值持续为负则反向调整。这套视觉系统从单纯的“监控报警”升级成“测量反馈”才算真正把数据用起来。最后分享一个我个人的体会这种现场视觉项目最花时间的往往不是模型训练而是把图像采集、标定、信号联调这些产线细节磨到稳定。模型只要数据给够了很快就能跑起来真正决定项目成败的是你有没有把相机、光源、基准线和PLC信号链路当成一个整体去设计。
返回列表