Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MeterDetRead

基于深度学习的仪表读数自动识别系统

Python License Framework YOLO ONNX API

项目简介

MeterDetRead 是一个端到端的深度学习仪表读数识别系统。它结合了 YOLO26 目标检测定位仪表区域,以及 ResNet34-OCR 模型配合 CTC(连接时序分类)解码识别数值读数。系统覆盖完整的机器学习生命周期:数据标注、数据集生成、模型训练、ONNX 导出、命令行推理以及基于 Docker 的生产级部署。

应用截图

系统架构

                    ┌─────────────────────┐
                    │      输入图片         │
                    └──────────┬──────────┘
                               │
                               ▼
                    ┌─────────────────────┐
                    │   YOLO26 检测器      │
                    │   (仪表区域定位)     │
                    └──────────┬──────────┘
                               │
                    ┌──────────▼──────────┐
                    │   裁剪的仪表区域      │
                    └──────────┬──────────┘
                               │
                               ▼
                    ┌─────────────────────┐
                    │  ResNetOCR + CTC    │
                    │  (数字识别)         │
                    └──────────┬──────────┘
                               │
                               ▼
                    ┌─────────────────────┐
                    │      识别结果         │
                    │   如 "1234.56"       │
                    └─────────────────────┘

功能特性

  • 两阶段识别流程 — YOLO26 检测仪表区域,ResNet34-OCR 解析数值读数。模块化设计,职责清晰,各组件可独立替换。

  • 双引擎推理 — 支持 PyTorch 原生推理与 ONNX Runtime 高性能推理,两种后端共用统一的命令行接口,无需修改代码即可切换。

  • 完整机器学习管线 — 从数据标注到生产部署一站式覆盖:GUI 标注工具 → 数据集生成 → 模型训练 → ONNX 导出 → API 服务。所有步骤脚本化、可复现。

  • 图形化标注工具 — 基于 PyQt6 的桌面标注应用,支持矩形框绘制与编辑、标注/浏览双模式切换、数据完整性校验、一键导出训练格式。

  • 生产级 API 服务 — FastAPI + ONNX Runtime 推理后端,多阶段 Docker 镜像构建,健康检查端点,支持 JPEG / PNG / BMP / WEBP 多格式图片,可通过环境变量配置子路径部署。

  • 强化 OCR 架构 — ResNet34 骨干网络,集成 ECA 通道注意力机制、注意力池化、多层卷积 CTC 头、余弦预热学习率调度,以及亮度、对比度、旋转、噪声、模糊、Cutout 等数据增强策略。

  • 配置驱动设计 — 训练、推理、导出等所有阶段的参数统一通过 YAML 配置文件管理,确保各环节参数一致性。

环境配置

系统要求

  • Python ≥ 3.12
  • CUDA ≥ 11.8(可选,用于 GPU 加速训练)
  • uv 包管理器

安装

# 克隆仓库
git clone https://github.com/noimank/MeterDetRead.git
cd MeterDetRead

# 安装依赖
uv sync

# 激活虚拟环境
source .venv/bin/activate  # Linux / macOS
.venv\Scripts\activate     # Windows

预训练权重

训练检测模型前需下载 YOLO26 预训练权重:

mkdir -p data/yolo_weight
# 从 Ultralytics 下载 yolo26n.pt 并放入 data/yolo_weight/ 目录

快速开始

1. 数据标注

# 将原始仪表图片放入 data/raw/ 目录
cp /path/to/meter/images/*.jpg data/raw/

# 启动标注工具
python annotator_gui_app.py

在图形界面中框选仪表区域并输入对应的读数值,标注数据会自动保存到 data/annotated/ 目录。

2. 生成训练数据集

python split_dataset.py --train-ratio 0.8 --val-ratio 0.1 --test-ratio 0.1

生成 YOLO 格式的检测标签以及用于 OCR 训练的裁剪区域图片。

3. 模型训练

# 训练检测模型
python train_det.py --epochs 300 --batch 16

# 训练识别模型
python train_resnet_ocr.py

4. 推理测试

# PyTorch 推理(默认)
python infer.py --source path/to/images

# ONNX 推理(需先导出,速度更快)
python infer.py --source path/to/images --use-onnx

5. API 部署

# 导出 ONNX 模型
python export_onnx.py

# 构建并运行 Docker 容器
docker build -t meter-reader:latest .
docker run -d --name meter-reader -p 8000:8000 meter-reader:latest

# 测试接口
curl -X POST "http://localhost:8000/api/detect_and_read" -F "file=@meter.jpg"

详细使用

数据准备

步骤 脚本 输入 输出
标注 annotator_gui_app.py data/raw/ data/annotated/(JSON 格式)
数据集切分 split_dataset.py data/annotated/ data/datasets/(YOLO + OCR 格式)

标注文件格式 (data/annotated/*.json)

{
  "image": "meter_001.jpg",
  "width": 1920,
  "height": 1080,
  "annotations": [
    { "bbox": [100, 200, 300, 400], "value": "123.45" }
  ]
}
  • bbox:边界框坐标 [x1, y1, x2, y2](绝对像素坐标)
  • value:仪表的真实读数值

标注工具

内置的 PyQt6 标注工具支持两种工作模式:

模式 快捷键 说明
标注模式 Ctrl+1 data/raw/ 中的新图片进行标注,保存后自动移至 data/annotated/
浏览模式 Ctrl+2 浏览和编辑 data/annotated/ 中已有的标注

常用快捷键Ctrl+S 保存, / 切换图片,鼠标拖拽绘制标注框,点击选中后可编辑移动。

模型训练

检测模型 (train_det.py)

训练 YOLO26 单类别(仪表)目标检测模型,所有参数通过 configs/det/yolo.yaml 配置管理。

python train_det.py --config configs/det/yolo.yaml --epochs 300 --batch 16 --lr 0.01
参数 默认值 说明
--config configs/det/yolo.yaml 配置文件路径
--epochs 配置文件中的值 训练轮数
--batch 配置文件中的值 批次大小
--lr 配置文件中的值 学习率

识别模型 (train_resnet_ocr.py)

训练 ResNet34-OCR 模型,采用 CTC Loss 进行端到端序列识别。支持断点续训、混合精度训练、余弦预热学习率调度及可配置的数据增强策略。

python train_resnet_ocr.py --config configs/rec/resnet_ocr.yaml

推理 (infer.py)

统一推理命令行工具,同时支持 PyTorch 和 ONNX 两种后端:

# 基础用法
python infer.py --source data/raw

# 完整参数
python infer.py \
    --det-model data/outputs/det/exp/weights/best.pt \
    --rec-model data/outputs/rec_resnet/best_model.pt \
    --source data/test/images \
    --output data/results \
    --crops-dir data/crops \
    --use-onnx
参数 默认值 说明
--source data/datasets/test/images 输入图片路径(目录或单文件)
--det-model data/outputs/det/exp/weights/best.pt 检测模型路径
--rec-model data/outputs/rec_resnet/best_model.pt 识别模型路径
--use-onnx false 启用 ONNX Runtime 推理
--crops-dir null 保存裁剪仪表区域到指定目录
--output data/outputs/infer 结果输出目录

ONNX 导出 (export_onnx.py)

# 导出全部模型
python export_onnx.py

# 选择性导出
python export_onnx.py --det-only
python export_onnx.py --rec-only --output onnx_models

导出产物:yolo26_det.onnxresnet_ocr.onnx

REST API

服务提供以下接口:

方法 路径 说明
GET /health 健康检查,返回服务及模型加载状态
POST /api/detect 检测图片中的仪表边界框
POST /api/read 读取已裁剪仪表图片中的数值
POST /api/detect_and_read 一体化接口:检测并读取仪表数值

Python 调用示例

import requests

url = "http://localhost:8000/api/detect_and_read"
with open("meter.jpg", "rb") as f:
    response = requests.post(url, files={"file": f})

result = response.json()
# {
#   "results": [
#     {"bbox": [100, 200, 300, 400], "confidence": 0.95, "reading": "123.45"}
#   ],
#   "count": 1,
#   "inference_time_ms": {"total": 45.2, "detection": 20.1, "reading": 25.1}
# }

cURL 示例

curl -X POST "http://localhost:8000/api/detect_and_read" -F "file=@meter.jpg"

完整的接口文档、错误码说明及多语言示例(JavaScript、Python、cURL)详见 API 文档

Docker 部署

快速体验(使用预构建镜像)

# 拉取并运行已发布的镜像
docker run -d --name meter-reader -p 8000:8000 noimankdocker/meter-reader:latest

# 打开浏览器访问 http://localhost:8000 即可使用 Web 演示界面
# 或通过 API 测试
curl -X POST "http://localhost:8000/api/detect_and_read" -F "file=@meter.jpg"

从源码构建

# 构建镜像
docker build -t meter-reader:latest .

# 运行容器
docker run -d --name meter-reader -p 8000:8000 meter-reader:latest

# 子路径部署(适用于反向代理场景)
docker run -d --name meter-reader \
    -p 8000:8000 \
    -e BASE_URL_PREFIX=meter-reader \
    meter-reader:latest

镜像采用多阶段构建优化体积。容器内置健康检查(30 秒间隔),确保服务可用性。

项目结构

MeterDetRead/
├── src/meterdetread/            # 核心 Python 包
│   ├── annotator/               # PyQt6 标注工具
│   │   ├── ui/                  # 主窗口与 UI 组件
│   │   ├── widgets/             # 画布、图片列表、标注面板
│   │   ├── managers/            # 标注状态管理与导出逻辑
│   │   └── validators/          # 数据完整性校验
│   ├── models/                  # 模型实现
│   │   ├── resnet_ocr.py        # ResNet34-OCR(含 ECA 注意力)
│   │   ├── attention_modules.py # 注意力池化等模块
│   │   └── loss.py              # CTC Loss 与数据集类
│   └── config.py                # 统一配置管理
├── configs/                     # YAML 配置文件
│   ├── det/yolo.yaml            # 检测模型配置
│   └── rec/resnet_ocr.yaml      # 识别模型配置
├── serve/                       # 推理 API 服务
│   ├── api.py                   # FastAPI 应用
│   └── static/index.html        # Web 演示界面
├── train_det.py                 # 检测模型训练脚本
├── train_resnet_ocr.py          # 识别模型训练脚本
├── infer.py                     # 统一推理命令行工具
├── export_onnx.py               # ONNX 模型导出脚本
├── annotator_gui_app.py         # 标注工具入口
├── split_dataset.py             # 数据集生成脚本
├── Dockerfile                   # 多阶段 Docker 构建文件
└── pyproject.toml               # 项目元数据与依赖声明

配置说明

检测模型 (configs/det/yolo.yaml)

Model:
  name: yolo26n
  weights: data/yolo_weight/yolo26n.pt

Dataset:
  config: data/datasets/data.yaml
  nc: 1
  names: ['meter']

Inference:
  imgsz: 640
  conf_threshold: 0.25
  iou_threshold: 0.45

Training:
  epochs: 1000
  batch: 16
  optimizer: SGD
  lr0: 0.01
  amp: true

Export:
  opset: 18
  simplify: true
  dynamic: false
  half: false

识别模型 (configs/rec/resnet_ocr.yaml)

Global:
  character: "0123456789."
  img_h: 128
  img_w: 256

Architecture:
  name: ResNetOCR
  backbone:
    name: ResNet34
    pretrained: true
    use_eca: true
  encoder:
    seq_len: 32
    use_attention_pooling: true
  head:
    name: CTCHead
    hidden_dim: 128
    dropout: 0.3

Training:
  batch_size: 16
  num_workers: 0
  amp: false

DataAugmentation:
  enabled: true
  brightness_prob: 0.5
  contrast_prob: 0.5
  rotation_prob: 0.3
  noise_prob: 0.3
  blur_prob: 0.2
  cutout_prob: 0.1

常见问题

Q: 训练时出现 CUDA 显存不足? 减小配置文件中的 batch_size,或启用 AMP 混合精度训练(amp: true)。

Q: Windows 下多进程数据加载报错? 将识别模型配置中的 num_workers 设为 0(默认已设置为 0)。

Q: ONNX 推理结果与 PyTorch 不一致? 检查配置文件中的 imgszimg_himg_w 是否与训练时完全一致。

Q: 检测不到仪表? 尝试降低 configs/det/yolo.yaml 中的 conf_threshold(如从 0.25 降至 0.15),或者扩充训练数据覆盖更多场景。

参与贡献

欢迎社区贡献。请遵循以下流程:

  1. Fork 本仓库
  2. 创建功能分支 (git checkout -b feature/your-feature)
  3. 实现你的改动
  4. 运行代码检查 (ruff check . && black .)
  5. 使用 Conventional Commits 规范提交 (git commit -m 'feat: add your feature')
  6. 推送分支并创建 Pull Request

许可证

本项目基于 MIT 许可证开源。详见 LICENSE 文件。

致谢


作者: noimank  |  邮箱: noimank@163.com

About

基于 YOLO26 + ResNet34-OCR 的端到端仪表读数识别系统,支持数据标注、模型训练、ONNX 导出与 Docker 部署,覆盖完整机器学习管线。

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages