前段时间,帮亲戚工厂做了一个很接地气的小项目:流水线零件残缺/异常自动检测报警程序。
说白了,需求并不复杂,但很典型:
- 产线上零件需要持续过站;
- 以前主要靠人工盯着看;
- 一旦出现混料、划伤、锈斑、残缺或异常件,就希望系统能及时报警;
- 最好还能顺手把结果统计下来,方便后面追溯。
一开始我并没有把它当成“多高大上”的 AI 项目去做,而是把它当成一个真正能在工厂现场跑起来的自动化工具:识别要稳、接线要简单、故障别轻易中断、出现 NG 之后要能直接给 PLC 发信号。
最后做出来的是一套轻量但完整的方案:模板分类防混料 + 缺陷检测 + PLC 报警输出 + 实时控制台面板 + 日志统计。
一、这个项目到底要解决什么问题
工厂现场最怕的不是“识别率论文指标不够漂亮”,而是下面这些很现实的问题:
人工目检容易漏检
工人长时间盯流水线,注意力会下降,轻微划伤、局部锈斑、错料件都可能漏过去。不同型号零件容易混料
只要上料或周转过程中出一点问题,就可能把 A 型和 B 型零件混在一起,后续装配会出更大问题。现场节拍固定,系统必须跟得上
不是离线跑图片,而是真正跟着产线节拍走,到了时间就得给出结果。检测结果不能只停留在屏幕上
产线真正需要的是:OK/NG 信号,必要时再带一个缺陷码,让 PLC 或执行机构去处理。
所以这个项目的目标一直很明确:
不是做一个“能识别图片的 demo”,而是做一个可以接近现场使用方式运行的、能自动拦截异常件的视觉检测程序。
二、为什么我没有一上来就上深度学习
很多人一看到“缺陷检测”,第一反应就是 YOLO、分割网络、训练数据集。
但这个项目的实际条件并不适合一开始就走重方案:
- 样本量有限;
- 项目周期短;
- 现场更看重可落地、可解释、可快速调参;
- 缺陷类型相对明确,主要就是划伤、锈斑、混料/未知类型这一类问题;
- 还需要兼顾 Windows / Linux、单相机 / 双相机、PLC 联动这些工程问题。
所以我最后选的是一套轻量规则 + 传统视觉方案:
- 用模板分类解决零件类型识别和混料拦截;
- 用颜色阈值 + 边缘/直线特征做锈斑和划伤检测;
- 用Modbus-TCP 把检测结果写给 PLC;
- 用脚本和配置文件解决生产启动问题。
这套方案最大的优点不是“最先进”,而是:
小工厂也能用,部署成本低,调试成本低,出了问题知道该改哪。
三、系统整体是怎么设计的
整个程序我拆成了几个非常实用的模块:
1 | valve_inspection/ |
从职责上看,可以概括成一条链路:
图像采集 → 类型识别 → 缺陷检测 → OK/NG 判定 → PLC 输出 → 结果记录与统计
这条链路跑通以后,整个系统就不再只是“识别软件”,而更像一个轻量工业视觉工位。
四、核心思路 1:先做模板分类,解决“混料拦截”
实际生产里,很多问题并不只是“表面有没有缺陷”,而是拿错料、上错料、混进去别的型号。
所以我没有直接上来就做缺陷检测,而是先做了一个模板分类器。
1. 模板库怎么建
每一种零件,先放几张标准良品图到 dataset/templates/ 里。
程序启动后可以先执行:
1 | python run_demo.py --build |
它会自动提取模板特征,并保存成 models/template_lib.pkl,后续运行时直接加载。
2. 分类器用了什么信息
这个分类器不是简单做一层像素比对,而是做了几种特征融合:
- 形状主轴对齐:先做主方向归一化,减少角度变化影响;
- Hu 矩:描述整体轮廓形状;
- ORB 特征 + 匹配:提高局部特征鲁棒性;
- HSV 直方图相似度:补充颜色/外观信息;
- 拒识阈值:相似度太低时直接判为
type_UNKNOWN。
这一步很关键,因为它把现场常见的“错料件”问题提前挡住了。
3. 为什么拒识比硬判更重要
在工厂里,“不确定”往往比“误判成正确”更安全。
所以我给分类器设计了拒识逻辑:
- 能够高置信度匹配模板 → 正常进入下一步;
- 置信度太低或完全不像 → 直接判定为未知类型;
- 如果开启混料拦截,就把这类件直接按 NG 处理。
这比“一定要猜一个最像的类别”实用得多。
五、核心思路 2:用规则法做缺陷检测
这个项目里的缺陷检测,主要针对两种比较典型的问题:
- 锈斑
- 划伤
因为零件材质、背景和拍摄环境相对可控,所以规则法其实很合适。
1. 先把零件区域分出来
为了避免背景干扰,我先做了一层钢件区域分割:
- 把图像转到 HSV;
- 利用绿色背景的颜色范围做反选;
- 再做开闭运算,去掉噪点、补齐区域。
这样后面检测锈斑和划伤时,就尽量只在零件表面上做判断。
2. 锈斑怎么检测
锈斑在颜色上通常偏棕、偏橙、偏红褐,所以我直接在 HSV 空间里定义了一个棕橙色区间:
- 提取可疑锈斑区域;
- 与钢件掩膜做与运算;
- 做形态学开闭处理;
- 计算面积;
- 面积超过阈值就记为
rust。
这种方法对现场快速落地非常友好,因为调阈值很直接。
3. 划伤怎么检测
划伤更像细长结构,所以我用的是:
- 灰度化;
- 高斯滤波;
- Canny 边缘提取;
- 霍夫直线检测;
- 把较长线段合成为划伤掩膜;
- 根据面积或覆盖范围做阈值判断。
如果最终区域超过阈值,就记为 scratch。
4. 为什么这套方案在现场够用
它不依赖大规模标注数据,也不要求显卡环境,优点非常明显:
- 可以快速上线;
- 可以针对现场光照直接调;
- 问题定位清晰;
- 改规则的成本很低。
当然,它也不是万能的。对于形态特别复杂、缺陷类型很多、背景变化很大的场景,后续还是可以逐步升级到深度学习方案。
六、判定逻辑:什么情况下算 NG
系统最终不是输出一堆中间结果,而是要给出一个明确的工位结论。
我这里的判定逻辑比较直接:
判 NG 的情况
- 检测到锈斑;
- 检测到划伤;
- 类型未知 / 拒识,且开启了混料拦截;
- 现场读取图像失败或关键步骤异常(可按生产策略定义)。
判 OK 的情况
- 类型识别正常;
- 没有发现设定范围内的缺陷;
- 结果可正常输出给 PLC。
也就是说:
先判断是不是正确的料,再判断这件料表面有没有问题。
这个顺序非常符合生产逻辑。
七、真正让它像“产线系统”的部分:PLC 联动
如果只是屏幕上显示 “OK / NG”,那它最多算半成品。
真正接近现场使用的是这一步:把检测结果通过 Modbus-TCP 写给 PLC。
我在程序里封装了一个 plc_io.py 模块,大致约定了几类输出:
coil_ok = 0:OK 线圈;coil_ng = 1:NG 线圈;reg_code = 100:缺陷码寄存器。
缺陷码示例
| 缺陷类型 | 码值 |
|---|---|
| scratch | 5 |
| rust | 6 |
| unknown | 15 |
这样 PLC 收到信号后,就可以继续联动:
- 报警灯;
- 蜂鸣器;
- 气缸剔除;
- 传送带停机;
- 后级分拣逻辑。
一个很实用的细节:自动模拟模式
现场开发时,不一定每次都有 PLC 真机可连。
所以我做了一个很实用的容错设计:
- 如果
pymodbus没装; - 或者 PLC 网络不通;
- 或者连接失败;
程序不会直接崩掉,而是自动切换成模拟模式,只在控制台打印信号。
这对调试阶段非常友好,因为算法开发和设备联调可以并行推进,不会互相卡死。
八、支持单相机、双相机和单相机复用
为了适配不同工位预算,我没有把方案写死成某一种硬件模式,而是做了三种运行方式:
1. 单面检测
如果现场只看零件一面,可以直接:
1 | python run_demo.py --live --up_only |
这种模式对成本最友好,一台相机就够。
2. 双相机检测
如果正反面都要看,可以上、下各一只相机:
1 | python run_demo.py --live --cam_up 0 --cam_down 1 |
3. 单相机复用
如果预算有限,但又想兼顾两面,可以通过节拍设计复用同一台相机:
1 | python run_demo.py --live --single_cam |
这种设计虽然简单,但对现场非常重要。因为很多时候,项目能不能落地,不只取决于算法,还取决于:
设备预算够不够,接线麻不麻烦,维护的人会不会用。
九、为了让工人也能看懂,我加了实时控制台面板
一个只会在后台悄悄运行的程序,对现场并不友好。
所以我在系统里做了一个实时控制台面板,用来显示:
- 当前节拍;
- PLC 状态;
- 累计检测数量;
- OK / NG 数量;
- 良率;
- 类型分布;
- 最近一次的检测结果;
- 最近一次 NG 的原因。
类似下面这样:
1 | ========== 阀板视觉检测·实时面板 ========== |
这种面板的意义不在于“炫”,而在于:
- 现场人员能快速知道系统有没有在正常跑;
- 维修或调试时,可以马上定位是 PLC 问题还是识别问题;
- 班组长也能直接看到良率变化。
十、统计和日志,决定了它是不是“可追溯”
如果检测完什么记录都不留,那后面复盘会非常麻烦。
所以系统运行时会自动生成几类结果:
session_stats.json:当前会话统计;session_stats.csv:逐件结果明细;live_records.jsonl:实时追加日志;- 检测结果图:把缺陷区域叠加到原图上。
这一步看起来不是算法核心,但实际很重要。因为一旦现场有人问:
- 今天一共拦了多少 NG?
- 哪一类缺陷最多?
- 某个时间段是不是识别异常?
- 这张图到底为什么判了 NG?
这些问题都得靠日志和结果图来回答。
十一、部署这件事,决定了项目能不能真正交出去
我在做这种小型现场项目时,一般不会搞特别重的部署体系,而是优先保证:
- 别人拿过去能启动;
- 工控机重启后能恢复;
- 出错后知道去哪看日志。
所以这个项目里,我专门补了三种启动入口:
Windows
1 | start_realtime.bat |
适合直接放在工控机上双击运行。
Python 跨平台启动器
1 | python start_realtime.py |
它会读取 start_config.json,自动拼装参数,支持日志重定向和异常退出自动重启。
Linux
1 | bash start_realtime.sh |
适合边缘设备或者 Linux 工业主机部署。
我很喜欢这种“把工程入口做实”的方式。因为对工厂来说,真正重要的不是代码是不是优雅,而是:
今天开机以后,它能不能自己稳稳跑起来。
十二、这个项目里我比较满意的几个点
1. 不只做识别,还考虑了完整链路
从采图、识别、判定、PLC 输出,到统计和启动脚本,这条链路是闭环的。
2. 工程容错做得比较实用
比如 PLC 连不上自动走模拟模式,这就很适合现场开发。
3. 运行模式足够灵活
单相机、双相机、单面、双面都能兼容,后续改造空间更大。
4. 规则法虽然朴素,但真能快速落地
对于样本不多、现场目标明确的项目,这类方法的性价比很高。
十三、它目前的局限也很明显
这篇文章也不能只写优点,不然就成宣传稿了。
这个系统现在更适合:
- 产品类型有限;
- 背景相对稳定;
- 缺陷类别较少;
- 现场光照和工位位置比较可控。
如果后面继续迭代,我觉得至少还有几个方向可以升级:
1. 从规则检测升级到深度学习检测
当缺陷类型更多、更复杂、更细微时,传统规则会越来越难维护。
2. 做更完整的相机标定和光照控制
工业视觉很多时候不是“算法不行”,而是成像条件没控制好。
3. 增加样本管理和误判回流机制
把误判图片自动收集起来,后面无论继续调规则还是训练模型,都更方便。
4. 增加 Web 看板
把实时结果、历史统计、缺陷图像做成一个网页,比纯控制台更适合多人查看。
5. 和产线执行机构做更深联动
比如剔除动作确认、复位信号、异常连锁停机等。
十四、这次项目给我最大的感受
这个项目虽然不算“大”,但特别能体现一个事实:
真正的工业小项目,难点往往不在某一个算法,而在于你能不能把“识别、控制、容错、部署、使用体验”一起串起来。
很多时候,能在电脑里跑通并不算完成;
只有当它能在工厂工位上稳定运行,并且现场人员愿意用,它才真的有价值。
对我来说,这次更像是一次很完整的“小型产线自动化实践”:
- 既有计算机视觉;
- 也有工程接线和 PLC 通信;
- 既要考虑识别逻辑;
- 也要考虑操作员和维护人员怎么使用。
这种项目做下来,会比单纯刷一个模型 demo 更能锻炼人。
最后
如果只从技术关键词上看,这个项目其实不复杂:OpenCV、模板匹配/特征匹配、规则检测、Modbus-TCP、Python 脚本化部署。
但如果从“真实可交付”来看,它已经具备了一个小型工业视觉系统该有的大部分骨架:
- 能识别;
- 能拦截;
- 能报警;
- 能统计;
- 能启动;
- 能排查问题。
后面如果我继续完善它,我大概率会沿着“更稳的成像条件 + 更强的缺陷识别模型 + 更完整的产线联动”这个方向走。
至少现阶段,它已经不是一个只会在本地文件夹里跑图片的 demo,而是一个真正朝现场应用迈出了一步的项目。