OCR 碑文识别 LLM 系统 — 架构说明

SMT PCBA 产线「大板码扫码 → 入库 → 显微镜拍照 → LLM 识别 → 校验提交 → 结果上报」一体化桌面工具的分层架构、后台线程模型、端到端业务流程与外部接口说明

🔍 OCR 碑文识别 LLM 系统 — 架构说明

版本:LLM-V1.18 | 技术栈:Python 3 + PyQt5 + SQLite + Requests(多线程) 定位:SMT PCBA 产线「大板码/ReelID 扫码 → 入库 → 显微镜拍照 → LLM 识别 → 校验提交 → 结果上报」的一体化桌面工具。


1. 项目概述

本系统为 PCBA reel 卷盘扫描识别 工具,核心链路为:

  1. 通过串口/条码枪输入大板码(| 分隔的多字段编码);
  2. 从大板码中解析出 ReelID(第 7 个字段),末尾 MSL 自动替换为 MSD;
  3. 可选调用入库 API 将大板码入 WMS 仓库;
  4. 调用 Web API 查询该 ReelID 对应的行数;
  5. 通过显微镜截图 API 获取图片(或从本地文件夹匹配);
  6. 调用 LLM(Qwen3.6-27B) 识别图片中的文字;
  7. 识别结果提交到 Web API 校验;
  8. 校验通过/失败后,向 QMS 碑文结果接口 上报 OK/NG;
  9. 全过程记录日志与提交统计(支持导出 Excel)。

2. 目录结构

文件 职责
主入口.py PyQt5 GUI 主程序:窗口、事件、业务流程编排、统计对话框
LLM.py LLM 图片识别接口(base64 编码 → OpenAI 兼容接口 → JSON 解析)
LLM1.py LLM 识别增强变体(含文字方向 orientation 检测,实验性)
ThreadWorkers.py 后台工作线程:LLM / API / 提交 / 碑文上报 / 入库
WebApiClient.py HTTP API 客户端封装(GET/POST/PUT/DELETE + Session 复用)
getPicByUrl.py 显微镜图片抓取(HTTP → Base64 解码 → OpenCV → 保存本地)
SerialCom.py 串口通信(连接、持续读取、回调)
ConfigManager.py 配置读写(app_config.json,带默认值合并)
LogManager.py 日志管理(按天轮转、UTF-8、自动清理过期日志)
StatisticsDB.py SQLite 提交统计(stats.db,按 ReelID 聚合成功/失败计数)
app_config.json 运行时配置文件
主入口.spec PyInstaller 打包脚本(含 conda DLL 自动收集)

3. 总体架构

系统采用 分层架构:表现层(PyQt5)→ 业务编排层(主窗口)→ 服务层(API/LLM/串口/日志/统计)→ 数据层(JSON 配置 + SQLite + 本地图片)。


4. 核心模块详解

4.1 主入口 主入口.py(约 2600 行)

关键类:

类 职责
MainWindow(QMainWindow) 主窗口,承载全部 UI 与业务编排
ReelIDLineEdit(QLineEdit) 大板码输入框(200ms 防抖缓冲,屏蔽手动按键,支持条码枪扫描与 Ctrl+V)
SerialReaderThread(QThread) 串口读取线程(与 SerialCom 协作)
StatsDialog(QDialog) 提交统计对话框(表格 + 柱状图 + 导出 Excel)
OCRToastMessage / ToastMessage 黄色 Toast 提示
XianweijingCaptureTask(QRunnable) 显微镜截图异步任务

MainWindow 运行时状态:

  • 后台线程持有者:serial_thread、api_worker、llm_worker、submit_worker、beiweng_worker、warehouse_worker
  • 业务状态:current_reelid、current_row_nums、current_ocr_texts、input_fields(动态输入框)、picture_base64_map(ReelID→Base64 缓存)
  • 超时定时器:ocr_timeout_timer(单次触发,默认 60s)

关键方法(业务流):

方法 职责
on_reelid_detected / on_reelid_manual_input 大板码输入 → 解析 ReelID → 可选入库
_start_ocr_flow 记录 ReelID → 清空结果 → 调用 API 查询
query_api / on_api_result 查询行数 → 创建动态输入框 → 触发抓图/识别
start_ocr_processing / on_ocr_finished 启动 LLM 识别 → 填充结果 → 自动提交
submit_ocr_results / on_submit_result 提交校验 → 更新统计 → 触发碑文上报
report_beiweng_result 向 QMS 碑文接口上报 OK/NG
show_stats_dialog 打开统计对话框
clean_expired_images 按 pic_keep_days 清理过期图片

4.2 LLM 识别 LLM.py

  • 使用 OpenAI 兼容接口(http://10.32.36.25:11434/v1/chat/completions),模型 Qwen3.6-27B(运行时可配置)。
  • query_llm_for_image(image_path, instruction, config):图片 base64 编码 → 构造 multimodal 请求 → 解析响应。
  • extract_json_from_llm_response:三级降级解析(```json 代码块 → 整体 JSON → 正则提取 {...} → 正则分词兜底)。
  • analyze_batch_images:批量图片识别。

4.3 后台线程 ThreadWorkers.py

线程类 信号 职责
LLMWorkerThread llm_started/finished/error LLM 识别(延迟导入 LLM 模块),校验行数是否达标
ApiWorker api_result/api_error 查询 ReelID 行数
SubmitDataWorker submit_result/submit_error 提交 OCR 结果(携带 is_manual 标记)
BeiwengResultSubmitWorker submit_result/submit_error 上报碑文 OK/NG
WarehouseWorker warehouse_result/warehouse_error 大板码入库

所有网络请求均在后台线程执行,通过 pyqtSignal 回传主线程,避免阻塞 GUI。

4.4 其他模块

  • WebApiClient.py:requests.Session 复用,统一异常处理,支持上下文管理器。
  • getPicByUrl.py:fetch_and_save_image(url, save_path) 兼容 text/plain 与 JSON 两种响应,解码 Base64 为 OpenCV 图像并保存,返回 (BGR 图像, 原始 base64)。
  • SerialCom.py:SerialCommunication(底层连接)+ ContinuousSerialReader(持续读取 + 回调)。
  • ConfigManager.py:JSON 配置读写,加载时用默认值补齐缺失键。
  • LogManager.py:TimedRotatingFileHandler(midnight 轮转)+ UTF-8 + 自动清理 log_keep_days 天前的日志。
  • StatisticsDB.py:SQLite 表 submission_stats,字段 reelid(主键)/manual_success/manual_fail/auto_success/auto_fail,update_stats 使用 ON CONFLICT DO UPDATE 累加计数。

5. 端到端业务流程


6. 线程与异步模型

  • 串口读取:SerialReaderThread(后台 QThread)持续读取,回调 on_serial_data。
  • 网络请求:全部通过独立 QThread(*Worker)执行,信号槽回传结果,不阻塞 GUI 线程。
  • 显微镜截图:QThreadPool.globalInstance() 执行 XianweijingCaptureTask(QRunnable),通过 QMetaObject.invokeMethod(QueuedConnection)线程安全回传。
  • 超时保护:LLM 识别使用 ocr_timeout_timer(单次触发,ocr_timeout 默认 60s)。
  • 延迟导入:getPicByUrl(cv2/numpy ~1.5s)、LLM、PyQt5.QtChart 均按需导入,缩短启动时间。

7. 配置项(app_config.json)

键 默认值 说明
webapi_url http://10.58.2.106:8000 查询/提交 Web API 基础地址
api_path_getrownums .../getrownums 查询行数接口
api_path_add .../add 提交校验接口
shot_url http://127.0.0.1/shoot 显微镜截图接口
folder_path — 本地图片文件夹
port / baudrate COM1 / 115200 串口参数
auto_ocr / auto_submit true / true 自动识别 / 自动提交
enable_xianweijing_capture true 启用显微镜截图
enable_warehouse true 启用入库
warehouse_api_url / warehouse_location — / E9-2F 入库接口 / 货架位置
beiwen_result_url http://qms.luxshare-ict.com:8081/... 碑文结果上报接口
enable_beiweng_report true 启用碑文上报
llm_url / llm_token / llm_model Ollama 兼容接口 LLM 服务配置
ocr_timeout 60 LLM 识别超时(秒)
log_keep_days 7 日志保留天数
pic_keep_days 3 图片清理(0 = 不清理)

8. 外部依赖与接口

外部系统 接口 用途
WMS 仓库 POST /api/materialcenter/anonymous/v1/reel/addrid 大板码入库(code/rid/location)
物料中心 POST .../ReelStatusInscriptionAnonymous/getrownums 查询 ReelID 行数
物料中心 POST .../ReelStatusInscriptionAnonymous/add 提交碑文内容校验
显微镜/高拍仪 GET http://127.0.0.1/shoot 获取图片(返回 Base64)
QMS POST /API/IQCData/BeiWenResultPort 上报 OK/NG 结果
LLM 服务 POST .../v1/chat/completions(Ollama) 图片文字识别

9. 关键技术点

  1. 大板码解析:按 | 分割取第 7 字段作为 ReelID;末尾字段含 MSL 时替换为 MSD。
  2. 防抖输入:ReelIDLineEdit 200ms 防抖缓冲,兼容条码枪连扫与 Ctrl+V 粘贴。
  3. 图片文件夹回退:主目录不可写时自动在应用目录创建 output/ 并回写配置。
  4. Base64 缓存:picture_base64_map 缓存图片 Base64,碑文上报时优先使用,缺失时回退读取本地文件,上报后清除。
  5. 统计导出:StatsDialog 支持将统计信息导出为 Excel(openpyxl 写 .xlsx,不可用时回退 CSV)。
  6. 启动优化:Splash 进度 + 延迟导入 + 串口扫描延迟到首帧渲染后。
  7. 配置防误写:load_config 中使用 blockSignals 包裹 setChecked,防止 stateChanged 触发意外保存。

10. 已知说明

  • LLM1.py 为增强变体(含文字方向检测 orientation),当前主流程使用 LLM.py。
  • LLM.py 内置模型为 Qwen3.8-27B,实际运行时以配置 llm_model(Qwen3.6-27B)为准。
  • 备份/、build/、dist/ 为历史打包产物与备份,非运行时源码。
comments powered by Disqus
使用 Hugo 构建😊 主题 Stack 由 Jimmy 设计