当前位置: 首页 > news >正文

基于机器视觉的工业产品型号识别与报警系统实现

在工业生产检测场景中快速、准确识别产品型号并对异常型号及时报警是保障产品质量和生产效率的关键环节。本文将分享一套基于 Python、OpenCV、PaddleOCR 和 PyQt5 实现的多摄像头产品型号识别与报警系统该系统可实时采集多路摄像头画面通过 OCR 识别产品型号对比标准型号后触发声光报警并保存异常画面。一、系统整体架构系统核心功能分为三大部分摄像头数据采集支持海康工业相机网口和 USB 摄像头实时获取多路画面OCR 型号识别基于 PaddleOCR 实现字符识别针对工业场景字符易混淆问题做专项优化异常检测与报警对比识别结果与基准型号异常时触发声光报警并保存取证画面。系统整体流程摄像头画面采集 → 帧间隔OCR识别 → 字符清洗与标准化 → 型号对比 → 异常则声光报警画面存档二、核心技术选型表格技术 / 库用途PyQt5可视化界面搭建摄像头画面展示按钮交互OpenCV图像预处理、摄像头数据读取、画面绘制PaddleOCR光学字符识别支持中英文、角度分类serial串口通信控制声光报警器threading后台线程管理避免界面卡顿numpy图像数据处理、字符区域面积计算三、核心代码实现1. 环境准备首先安装依赖包pip install opencv-python pyqt5 paddleocr numpy pyserial2. 系统初始化核心类定义import cv2 from collections import Counter import os from numpy import ndarray import sys import logging import numpy as np from paddleocr import PaddleOCR import re import serial import time import argparse import threading from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5.QtCore import * from PyQt5.QtGui import * from PyQt5.QtWidgets import QFileDialog, QMainWindow # 报警指令定义 LIGHT_BUZZ1 0110001A000101CE18 # 闪光声音1 LIGHT 0110001A0001028E19 # 仅闪光 BUZZ_CMD_CLOSE 0110001A0001000FD8 # 关闭报警 # 初始化OCR引擎 ocr PaddleOCR(use_angle_clsTrue,use_gpuTrue, langen) ocr2 PaddleOCR(use_angle_clsFalse, use_gpuTrue, langen) # 命令行参数解析 parser argparse.ArgumentParser() parser.add_argument(--SERIAL_PORT1, typestr, defaultCOM5, help第一个报警器的串口号) parser.add_argument(--SERIAL_PORT2, typestr, defaultCOM4, help第二/三个报警器的串口号) parser.add_argument(--confid_level, typefloat, default0.88, help识别的置信度) parser.add_argument(--cap_numb3, typeint, default1, help第三个摄像头编号) parser.add_argument(--frame_delay, typeint, default67, help获取画面帧数的延时) opt parser.parse_args() class PyQtMainEntry(QMainWindow, Ui_MainWindow): def __init__(self): super().__init__() self.setupUi(self) # 初始化串口连接报警器 self.ser1 serial.Serial(opt.SERIAL_PORT1, 9600, timeout2.5) self.ser2 serial.Serial(opt.SERIAL_PORT2, 9600, timeout2.5) # 初始化UI元素隐藏报警标签 self.label_4.setVisible(False) # 摄像头1异常标签 self.label_5.setVisible(False) # 摄像头2异常标签 self.label_6.setVisible(False) # 摄像头3异常标签 # 初始化数据存储容器 self.list_zong1 [] # 摄像头1识别结果列表 self.list_zong2 [] # 摄像头2识别结果列表 self.list_zong3 [] # 摄像头3识别结果列表 self.set_zong1 set() self.set_zong2 set() self.set_zong3 set() self.set_12hun set() # 摄像头12基准型号集合 # 初始化摄像头 # 海康工业相机1 self.camera1 HKCamera(CameraIp192.168.20.20) self.camera1.set_Value(param_typeenum_value, node_namePixelFormat, node_valueBayerGB8) self.camera1.set_Value(param_typeenum_value, node_nameGainAuto, node_valueContinuous) self.camera1.set_Value(param_typefloat_value, node_nameAcquisitionFrameRate, node_value15.0000) self.camera1.start_camera() # 海康工业相机2 self.camera2 HKCamera(CameraIp192.168.20.40) self.camera2.set_Value(param_typeenum_value, node_namePixelFormat, node_valueBayerGB8) self.camera2.set_Value(param_typeenum_value, node_nameGainAuto, node_valueContinuous) self.camera2.set_Value(param_typefloat_value, node_nameAcquisitionFrameRate, node_value15.0000) self.camera2.start_camera() # USB摄像头3 self.camera3 cv2.VideoCapture(opt.cap_numb3) # 启动后台线程定期释放USB摄像头资源防止内存泄漏 release_thread2 threading.Thread(targetself.release_capture3, args(self.camera3,)) release_thread2.daemon True release_thread2.start() # 初始化定时器用于画面刷新 self.is_camera_opened False self._timer QtCore.QTimer(self) self._timer.timeout.connect(self._queryFrame) self._timer.setInterval(opt.frame_delay) self.frame_counter 0 # 帧数计数器3. 关键工具函数1串口指令发送控制报警器def sendCmdToDevice(cmd, ser): 向报警器发送串口指令 cmdd bytes.fromhex(cmd) ser.write(cmdd) def hide_label_and_send_cmd(label,serNone): 隐藏报警标签并停止报警 label.setVisible(False) if ser: sendCmdToDevice(BUZZ_CMD_CLOSE, ser)2字符标准化解决易混淆字符问题def set_bing(set_a): 替换工业场景易混淆字符0→O、s→5、I→1等 resu set() for j in set_a: jj j.replace(0, O).replace(o, O).replace(s, 5).replace(S, 5)\ .replace(I, 1).replace(L, 1).replace(v,V).replace(B,8).replace(p,P) resu.add(jj) return resu def process_string(input_string): 筛选符合型号规则的字符字母数字/纯数字 aa[] parts input_string.split() # 正则1包含字母数字2-10位 pattern_alphanumeric re.compile(r^(?.*[a-zA-Z])(?.*\d)[a-zA-Z\d-]{2,10}$) # 正则24-7位纯数字 pattern_at_least_two_digits re.compile(r^\d{4,7}$) for part in parts: if pattern_alphanumeric.match(part) or pattern_at_least_two_digits.match(part): aa.append(part) return aa3字符区域面积计算筛选最大字符区域def are(i): 计算OCR识别字符的包围框面积 zs i[0][0] ys i[0][1] yx i[0][2] zx i[0][3] # 计算宽度取两组对边平均值 width_A np.sqrt(((zs[0] - ys[0]) ** 2) ((zs[1] - ys[1]) ** 2)) width_B np.sqrt(((zx[0] - yx[0]) ** 2) ((zx[1] - yx[1]) ** 2)) width (width_A width_B) / 2 # 计算高度取两组对边平均值 height_A np.sqrt(((zs[0] - zx[0]) ** 2) ((zs[1] - zx[1]) ** 2)) height_B np.sqrt(((ys[0] - yx[0]) ** 2) ((ys[1] - yx[1]) ** 2)) height (height_A height_B) / 2 area width * height return area4. 摄像头画面采集与 OCR 识别def _queryFrame(self): 定时器回调采集摄像头画面并触发OCR try: if not self.camera3.grab(): print(USB摄像头无画面) self.camera3.release() self.close() else: # 读取三路摄像头画面 self.frame1: ndarray self.camera1.get_image() self.frame2: ndarray self.camera2.get_image() ret3, self.frame3 self.camera3.read() if ret3: # 调整画面尺寸并显示到UI self.frame11 cv2.resize(self.frame1, (640, 480)) self.frame22 cv2.resize(self.frame2, (640, 480)) self.frame33 cv2.resize(self.frame3, (640, 480)) # 转换为Qt图像格式并显示 qimage cv2.cvtColor(self.frame11.copy(), cv2.COLOR_BGR2RGB) qimage QtGui.QImage(qimage.data, qimage.shape[1], qimage.shape[0], QtGui.QImage.Format_RGB888) self.label.setPixmap(QtGui.QPixmap.fromImage(qimage)) qimage2 cv2.cvtColor(self.frame22.copy(), cv2.COLOR_BGR2RGB) qimage2 QtGui.QImage(qimage2.data, qimage2.shape[1], qimage2.shape[0], QtGui.QImage.Format_RGB888) self.label_3.setPixmap(QtGui.QPixmap.fromImage(qimage2)) qimage3 cv2.cvtColor(self.frame33.copy(), cv2.COLOR_BGR2RGB) qimage3 QtGui.QImage(qimage3.data, qimage3.shape[1], qimage3.shape[0], QtGui.QImage.Format_RGB888) self.label_2.setPixmap(QtGui.QPixmap.fromImage(qimage3)) # 帧间隔触发OCR降低计算量 self.frame_counter 1 if self.frame_counter % 5 0: self._performOCR1() # 摄像头1 OCR if self.frame_counter % 3 0: self._performOCR2() # 摄像头2 OCR self._performOCR3() # 摄像头3 OCR except Exception as e: print(f画面采集异常{e}) # 装饰器指定调用次数后执行数据处理 def execute_after_n_calls(n, w2set): def decorator(func): def wrapper(self, *args, **kwargs): wrapper.count 1 result func(self, *args, **kwargs) if wrapper.count % n 0: w2set(self) return result wrapper.count 0 return wrapper return decorator execute_after_n_calls(3, lambda self: self.w2set1()) def _performOCR1(self): 摄像头1 OCR识别 result ocr2.ocr(self.frame1, clsFalse) if result and not None in result: try: for i in result[0]: mianji are(i) ma process_string(i[1][0]) # 过滤条件置信度0.92、有效型号、位置范围、面积1000 if i[1][1] 0.92 and ma and 320 i[0][0][0] 1060 and mianji 1000: self.list_zong1.extend(ma) except: pass def w2set1(self): 摄像头1识别结果处理异常判断报警 if self.list_zong1: try: # 筛选出现次数1的识别结果 for i in self.list_zong1: if self.list_zong1.count(i) 1: self.set_zong1.add(i) set_len1 set_bing(self.set_zong1) # 字符标准化 self.list1.extend(list(set_len1)) self.daan1 most_common_element(self.list1) # 取出现次数最多的作为基准 # 10秒刷新一次基准列表 if self.frame_counter % 16 0: self.list1.clear() # 显示识别结果 text ,.join(set_len1) self.lineEdit.setText(text) # 异常判断识别结果非空、非单一匹配基准 if (not self.daan1) or (not set_len1): pass elif len(set_len1) 1 and (list(set_len1)[0] self.daan1): pass else: # 异常处理保存画面、显示报警标签、触发声光报警 tu1 cv2.putText(self.frame1.copy(), text, (100, 200), cv2.FONT_HERSHEY_SIMPLEX, 2, (0, 0, 255), 5, cv2.LINE_AA) nam time.strftime(%Y_%m_%d_%H_%M, time.localtime()) path os.path.join(rD:\MVS\MVS\Development\Samples\Python\shiyan\baojing\镜头一, f{nam}-{self.daan1}.jpg) cv2.imencode(.jpg, tu1)[1].tofile(path) self.label_4.setVisible(True) # 显示报警标签 sendCmdToDevice(LIGHT, self.ser1) # 触发闪光报警 # 5秒后关闭报警 QtCore.QTimer.singleShot(5000, lambda: hide_label_and_send_cmd(self.label_4,self.ser1)) self.frame_counter 0 except Exception as e: print(f摄像头1处理异常{e}) finally: self.list_zong1.clear() self.set_zong1.clear()5. 系统运行入口if __name__ __main__: app QtWidgets.QApplication(sys.argv) window PyQtMainEntry() window.show() sys.exit(app.exec_())四、系统亮点多摄像头适配同时支持工业网口相机和 USB 摄像头满足不同场景需求字符鲁棒识别针对工业场景易混淆字符0/O、1/I/L、5/S 等做专项替换提升识别准确率性能优化通过帧间隔 OCR、字符面积筛选、出现次数统计降低计算量同时提升识别稳定性异常处理完善异常时自动保存取证画面、触发声光报警5 秒后自动复位无需人工干预线程安全后台线程管理摄像头资源避免 UI 卡顿和资源泄漏。五、扩展方向模型优化针对特定产品型号定制 PaddleOCR 训练数据集进一步提升识别准确率远程监控增加网络推送功能将异常画面和报警信息推送到手机 / 电脑端数据统计增加数据库存储功能统计异常型号出现频次、报警时间等辅助生产分析自适应调节根据环境光照自动调整相机曝光参数提升复杂环境下的识别稳定性。该系统已在实际工业检测场景中落地应用能够有效替代人工肉眼识别提升检测效率和准确率降低漏检、错检率。核心代码具备良好的可扩展性可根据不同工业场景的需求快速适配调整。
http://www.gsyq.cn/news/1335508.html

相关文章:

  • 如何快速找出占用Windows热键的幕后程序:热键侦探使用指南
  • OpenAI Agents SDK、MCP、A2A 都在升级,为什么最后拼的还是向量引擎?
  • 空间自相关分析避坑指南:莫兰指数计算中‘孤立岛屿’警告与权重矩阵标准化实操
  • 西安箱体梁楼梯技术解析:西安旋转玻璃楼梯/西安旋转钢结构楼梯订制厂家/西安消防楼梯/专业厂家实测对比与选型推荐 - 优质品牌商家
  • 边缘AI算力模组:物联网终端智能化的核心引擎与落地实践
  • DDR3缓存仿真平台搭建:从开源模型到UVM验证实践
  • 在i.MX6UL开发板上移植ncnn:嵌入式AI部署实战与性能优化
  • 【建议收藏】论文AI率怎么降?10大主流降AI工具优缺点实测
  • 告别ArcGIS!用Python+MRT批量处理MODIS 16A2蒸散发数据,从HDF到月均ET全流程
  • Python点云数据处理避坑指南:pypcd与pypcd4库在Ubuntu下的安装与实战对比
  • 光纤收发器和光纤环网交换机组网的区别
  • 保姆级教程:用VOFA+上位机配置HC08蓝牙模块主从机(STM32F103C8T6实战)
  • Eur Radiol 哈尔滨医科大学附属肿瘤医院王瑞涛团队:多模态深度学习探究肿瘤与内脏脂肪对结直肠癌隐匿性腹膜转移的影响
  • Python游戏开发实战:用Pygame从零复刻经典消消乐(附完整源码与素材包)
  • 笔试训练48天:小乐乐改数字
  • 普冉PY32F003单片机PWM呼吸灯实战:从8ms定时器中断到10KHz波形平滑调节
  • 用Arduino Nano和MPU6050做个‘防抖云台’:PID调参实战,告别手抖视频
  • 2026年兰州卫生纸批发商家排行及采购务实参考:兰州哪个地方卫生纸批发便宜/兰州哪有批发卫生纸的/兰州城关卫生纸批发/选择指南 - 优质品牌商家
  • 如何免费解锁百度网盘macOS版SVIP功能:终极完整指南
  • 在Ubuntu 22.04上编译OpenWrt 23.05.2,我踩过的坑和解决方案都在这了
  • 统信UOS/麒麟KYLINOS批量部署神器:用dpkg -i和yes命令搞定交互式deb包静默安装
  • TortoiseGit实战:用‘拣选’功能精准移植单个提交,告别全量合并的烦恼
  • STM32CubeMX实战:用一阶卡尔曼滤波给HC-SR04超声波测距数据‘降噪’(附完整代码)
  • 别再为龙芯装系统发愁了!保姆级教程:从下载UOS到用Deepin工具制作启动盘
  • 红日靶场实战复盘:我是如何利用phpMyAdmin日志写入拿到WebShell的
  • 保姆级教程:Halcon20.11在Windows系统下的完整安装与破解配置(附常见问题解决)
  • 学校开始查AI率了!知网AIGC检测到底是什么原理?
  • 实战:如何用OpenPCDet训练你自己的“树”检测模型(附完整数据集与配置文件)
  • 别再傻傻分不清!用打电话、对讲机、广播这些生活例子,5分钟搞懂串行通信里的单工、半双工和全双工
  • mg3640s,g2800,ts9000,ts9020,ts9080,ts3380,ts3440,ts9180如何清零详细教程报错5B00,P07,E08,1700,5b04废墨垫清零,亲测有用。