832a3db830
新文件: "Docker\346\212\200\346\234\257.md" 新文件: "GIT\346\212\200\346\234\257.md" 新文件: "Linux\346\212\200\346\234\257.md" 新文件: "Python\346\212\200\346\234\257.md" 新文件: hermes-agent.md 新文件: "\345\244\207\344\273\275\344\270\216\346\201\242\345\244\215.md" 新文件: "\347\224\265\345\255\220\347\247\244\345\233\276\347\211\207\350\257\206\345\210\253\347\263\273\347\273\237\350\256\276\350\256\241.md"
272 lines
12 KiB
Markdown
272 lines
12 KiB
Markdown
# 电子秤图片识别系统设计文档
|
||
|
||
> 版本:v1.0
|
||
> 最后更新:2026-05-20
|
||
> 状态:草案(待迭代)
|
||
|
||
## 1. 项目背景
|
||
|
||
### 1.1 业务场景
|
||
用户拍摄电子秤显示器图片,需自动提取**读数(数字 + 单位)**用于数据录入或核对。
|
||
图片来源包括家用体重秤、台秤、智能手机 App 截图等。
|
||
|
||
### 1.2 现状
|
||
- 现有脚本 `preprocess.py` 仅完成 ROI 裁剪 + 对比度增强,无识别能力
|
||
- 122 张样本通过人工 + 多模态模型识别,准确率约 80%,主要误差来源见 §2
|
||
|
||
### 1.3 目标
|
||
- **短期**:将自动识别准确率提升至 **≥85%**,剩余由人工核对
|
||
- **中期**:达到 **≥95%**,仅极端模糊/异常显示需要人工
|
||
- **长期**:支持任意品牌秤的型号自动识别 + 单位歧义消除
|
||
|
||
|
||
## 2. 问题分析(基于 122 张样本)
|
||
|
||
### 2.1 误差来源分布
|
||
|
||
| 误差类型 | 占比 | 典型样例 | 严重性 |
|
||
|---|---|---|---|
|
||
| 拍摄方向倒置 | ~25% | 倒着读"119.35"识别为反向 | 🔴 高 |
|
||
| ROI 裁切过紧 | ~12% | 只剩"6"丢失其余数字 | 🔴 高 |
|
||
| 7段数码管字符混淆 | ~16% | `7↔L`、`2↔5`、`6↔9` | 🟡 中 |
|
||
| 显示器反光/模糊 | ~8% | 粉色秤小屏幕 | 🟡 中 |
|
||
| 单位歧义(kg/斤) | ~5% | 小米秤同显示两种模式 | 🟢 低 |
|
||
| 显示异常(启动/出错) | ~2% | 段笔画不完整 | 🟢 低 |
|
||
|
||
### 2.2 设备类型分布
|
||
|
||
| 设备类型 | 占比 | 显示特征 | 难点 |
|
||
|---|---|---|---|
|
||
| 蓝背光 LCD 体重秤 | ~40% | 黑字蓝底 | 反光、自适应阈值难 |
|
||
| LED 数码管秤(橙/白) | ~20% | 高对比度发光数字 | 易倒置拍摄 |
|
||
| 香山台秤(多屏) | ~10% | 黑底白字三段 LCD | 多窗口干扰 |
|
||
| App 截图 | ~25% | 高清,多字段 | 需要定位"主体重"字段 |
|
||
| 其他(粉色、HUAWEI、LEFU 等) | ~5% | 各异 | 长尾问题 |
|
||
|
||
|
||
## 3. 技术方案
|
||
|
||
### 3.1 整体 Pipeline
|
||
|
||
```
|
||
┌─────────┐ ┌──────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐
|
||
│ 原始图片 │ → │ EXIF校正 │ → │ ROI检测 │ → │ 方向校正│ → │ 增强 │ → │ OCR识别 │
|
||
└─────────┘ └──────────┘ └────────┘ └────────┘ └────────┘ └────────┘
|
||
↓
|
||
┌──────────────────┐
|
||
│ 数值+单位解析 │
|
||
│ 合理性校验 │
|
||
└──────────────────┘
|
||
↓
|
||
┌──────────────────┐
|
||
│ 输出:值/单位/置信│
|
||
└──────────────────┘
|
||
```
|
||
|
||
### 3.2 各阶段技术选型
|
||
|
||
#### Step 1 — EXIF 方向校正
|
||
**目的**:手机拍摄的 JPG 自带 Orientation 元数据,可零成本转正。
|
||
**方案**:`PIL.ExifTags` 读取 Orientation 标签,按 3/6/8 三种 case 旋转。
|
||
**预期收益**:解决约 30% 的方向问题,几乎无成本。
|
||
|
||
#### Step 2 — ROI 检测(屏幕区域定位)
|
||
**目的**:从全图裁出显示器矩形,降低 OCR 干扰。
|
||
**方案**:4 策略加权打分:
|
||
- **策略 A**:LED 高亮 + 低饱和(白/黄数码管)— boost ×1.3
|
||
- **策略 B**:蓝色背光 LCD(HSV: H∈[85,140])
|
||
- **策略 C**:白色/浅色 LCD(V>180, S<60)
|
||
- **策略 D**:Canny 边缘 + 横向膨胀(用于黑底白字台秤)— boost ×0.8
|
||
|
||
**打分维度**:面积比、宽高比、对比度、亮度。
|
||
**风险**:当前 margin 15% 偏紧,新版调至 20%;仍需观察。
|
||
|
||
#### Step 3 — 方向校正(4 向暴力 + 评分)
|
||
**目的**:解决倒置/侧拍。
|
||
**评分项**:
|
||
1. **形状先验**:显示器一般 `w>h`(横向) → +1
|
||
2. **7段重力特征**:水平投影下 1/3 行 ≥ 上 1/3 行 → +1(数字朝上的典型分布)
|
||
3. **Tesseract OSD**:若返回 `rotate=0` → +2(强证据)
|
||
|
||
**选择**:取 0°/90°/180°/270° 中评分最高的方向。
|
||
**优势**:即使 OSD 失败,仍有 7段特征兜底。
|
||
|
||
#### Step 4 — 图像增强
|
||
**目的**:让 OCR 识别 7 段数码管。
|
||
**关键步骤**:
|
||
1. CLAHE(自适应直方图均衡化)
|
||
2. 极性自动判断:若图像均值<127 视为暗背景,反转
|
||
3. 自适应阈值(Gaussian, blockSize=25)
|
||
4. **关键**:2×2 核膨胀 1 次 — 连接 7 段间隙,否则 Tesseract 会把一个数字切成多字符
|
||
|
||
#### Step 5 — OCR 识别(多后端)
|
||
| 后端 | 优势 | 劣势 | 推荐场景 |
|
||
|---|---|---|---|
|
||
| **Tesseract** | 易部署、有 LCD 字模 | 7段需调参 | 默认 |
|
||
| **SSOCR** | 专为 7段设计 | 仅命令行、需手编译 | 干净 LED 显示 |
|
||
| **PaddleOCR** | 中文+数字皆强 | 体积大 | App 截图 |
|
||
| **自训 CNN** | 准确率天花板高 | 需训练数据 | 长期投入 |
|
||
|
||
**当前默认**:Tesseract,PSM=7(单行),whitelist 限制为数字 + 单位字符。
|
||
|
||
#### Step 6 — 数值合理性校验
|
||
**正则提取**:`(\d{1,3}\.?\d{0,2})\s*(kg|KG|公斤|千克|斤|两|lb)?`
|
||
**合理范围**:
|
||
- kg / 公斤 / 千克:10–200
|
||
- 斤 / 两:20–400
|
||
- lb:20–440
|
||
|
||
**作用**:拦截 OCR 典型错误(如把 `1` 错认 `7` 得到 170kg 时直接 reject)。
|
||
|
||
|
||
## 4. 文件结构
|
||
|
||
```
|
||
新建文件夹 1/
|
||
├── 未识别/ # 待处理原图
|
||
├── 预处理/ # 旧版输出(v1)
|
||
├── 预处理v2/ # 新版输出
|
||
│ ├── *.png # 各图的二值化预处理结果
|
||
│ └── _results.csv # 识别汇总(文件名/旋转/OCR/置信度/解析值)
|
||
├── preprocess_v2.py # 新版(预处理 + 识别 + 校验)
|
||
└── 设计文档.md # 本文档
|
||
```
|
||
|
||
|
||
## 5. 评估指标
|
||
|
||
### 5.1 准确率指标
|
||
- **Top-1 准确率**:单次识别完全正确(数字 + 单位都对)的比例
|
||
- **数字准确率**:仅数字正确(容忍单位错误)
|
||
- **±5% 容忍准确率**:识别值与真值相对误差 ≤5%(避免小数位识别错带来的负面感受)
|
||
|
||
### 5.2 召回率 / 拒识率
|
||
- **拒识率**:合理性校验后输出"无效"的比例(高拒识率好过错误识别)
|
||
- **置信度阈值**:建议 Tesseract conf > 60 才接受,否则降级人工
|
||
|
||
### 5.3 性能
|
||
- 单图处理时间 < 1s(CPU 单线程)
|
||
- 122 张全量处理 < 2 分钟
|
||
|
||
|
||
## 6. 已知局限与待解决
|
||
|
||
| # | 问题 | 当前对策 | 长期改进 |
|
||
|---|---|---|---|
|
||
| L1 | 粉色秤显示器尺寸过小(占图 <1%) | margin 放宽 | 改用超分辨率(ESRGAN)预处理 |
|
||
| L2 | 启动画面/异常显示误识 | 合理性校验拦截 | 加一个"是否合法读数"的分类器 |
|
||
| L3 | 香山台秤三屏,只需重量栏 | ROI 取最大 LCD | 训练专用检测器,按字段标签裁切 |
|
||
| L4 | 小米秤 kg/斤 模式无法从显示判断 | 默认按区间猜单位 | 加品牌+型号识别(CNN 或 logo 匹配) |
|
||
| L5 | OCR 把"6/9"反向识别 | 4向暴力旋转 | 训练朝向检测器 |
|
||
| L6 | App 截图字段繁多 | 暂用通用 OCR + 选最大数字 | 训练 App 截图专用 layout 模型 |
|
||
|
||
|
||
## 7. 改进路线图
|
||
|
||
### v2.0(当前)— 通用 Pipeline
|
||
- ✅ EXIF 方向校正
|
||
- ✅ 4 策略 ROI 检测
|
||
- ✅ 4 向暴力旋转 + 评分
|
||
- ✅ Tesseract / SSOCR / PaddleOCR 三选一
|
||
- ✅ 数值合理性校验
|
||
- ✅ CSV 汇总输出
|
||
|
||
### v2.1 — 兜底机制
|
||
- [ ] 低置信度自动转人工:置信度 <60 时输出标记
|
||
- [ ] 多 OCR 后端投票(Tesseract + PaddleOCR 投票)
|
||
- [ ] 单位上下文推断:根据数字范围反推(如 50–100 多半是 kg,120+ 多半是斤)
|
||
|
||
### v2.2 — 专项优化
|
||
- [ ] **App 截图分支**:检测到 App UI 元素时走专用路径(直接定位"目标数字"色块)
|
||
- [ ] **秤品牌识别**:用图中 logo(mi、SENSSUN、HUAWEI、LEFU、HCS 等)辅助选择 OCR 参数
|
||
- [ ] **超分辨率增强**:粉色秤等小显示器先 4× 超分再识别
|
||
|
||
### v3.0 — 深度学习
|
||
- [ ] 用现有 122 张 + 持续累积构建训练集(目标 ≥1000 张)
|
||
- [ ] Fine-tune 7 段专用 CNN(参考 [Seven-Segment-OCR](https://github.com/SachaIZADI/Seven-Segment-OCR))
|
||
- [ ] 端到端 YOLO 检测+识别一体模型(参考 Goodfellow 多位数字识别论文)
|
||
|
||
### v4.0 — 工程化
|
||
- [ ] 提供 HTTP API(FastAPI)
|
||
- [ ] 提供 Web UI 标注 + 校验工具
|
||
- [ ] 主动学习:被人工修正过的样本自动加入训练集
|
||
|
||
|
||
## 8. 测试与验证
|
||
|
||
### 8.1 当前测试集
|
||
- 122 张样本图(位于 `未识别/`,已按"识别结果.jpg"命名作为 ground truth)
|
||
- 真值来源:人工 + 多模态模型双校
|
||
- **注意**:约 10 张倒置图的真值仍可能有误差,需后续校对
|
||
|
||
### 8.2 验证流程
|
||
```bash
|
||
# 1. 跑识别
|
||
python preprocess_v2.py --backend tesseract
|
||
|
||
# 2. 对照真值(文件名即真值)
|
||
python evaluate.py # 待实现:从文件名提取真值,与 _results.csv 比对
|
||
```
|
||
|
||
### 8.3 验收标准(v2.0)
|
||
- Top-1 准确率 ≥ 70%
|
||
- 数字准确率 ≥ 80%
|
||
- ±5% 容忍准确率 ≥ 85%
|
||
- 拒识率 ≤ 20%(剩余转人工)
|
||
|
||
|
||
## 9. 依赖
|
||
|
||
### 必装
|
||
```bash
|
||
pip install opencv-python pillow pytesseract imutils numpy
|
||
```
|
||
|
||
### 系统依赖(Linux)
|
||
```bash
|
||
sudo apt install tesseract-ocr tesseract-ocr-chi-sim
|
||
# 可选:下载 LCD 专用字模
|
||
wget https://github.com/Shreeshrii/tessdata_ssd/raw/master/ssd.traineddata
|
||
sudo mv ssd.traineddata /usr/share/tesseract-ocr/4.00/tessdata/
|
||
```
|
||
|
||
### 可选(更强后端)
|
||
```bash
|
||
pip install paddlepaddle paddleocr # PaddleOCR
|
||
sudo apt install ssocr # 7段专用 OCR(Debian/Ubuntu 自带)
|
||
```
|
||
|
||
|
||
## 10. 参考资料
|
||
|
||
### 论文
|
||
- Goodfellow et al., [Multi-digit Number Recognition from Street View Imagery using Deep CNNs](https://arxiv.org/abs/1312.6082)
|
||
|
||
### 开源项目
|
||
- [SSOCR](https://www.unix-ag.uni-kl.de/~auerswal/ssocr/) — 专用 7段 OCR(C)
|
||
- [tessdata_ssd](https://github.com/Shreeshrii/tessdata_ssd) — Tesseract 7段字模
|
||
- [LCD-OCR](https://github.com/DevashishPrasad/LCD-OCR) — Tesseract + OpenCV 流水线
|
||
- [Seven-Segment-OCR](https://github.com/SachaIZADI/Seven-Segment-OCR) — CNN/MNIST 风格
|
||
- [seven-segment-ocr](https://github.com/renjithsasidharan/seven-segment-ocr) — TensorFlow Lite
|
||
|
||
### 工程文章
|
||
- [PyImageSearch — Correcting Text Orientation with Tesseract](https://pyimagesearch.com/2022/01/31/correcting-text-orientation-with-tesseract-and-python/)
|
||
- [Medium — Correct image orientation using Pytesseract + Imutils](https://medium.com/@birenmer/correct-image-orientation-using-python-pytesseract-and-imutils-5a524d386857)
|
||
|
||
|
||
## 11. 维护与协作
|
||
|
||
### 11.1 文档维护
|
||
- 每次方案变更需在 §7 路线图打勾,并写明版本号
|
||
- 新增已知问题加入 §6 已知局限表
|
||
- 重大架构调整需更新 §3 Pipeline 图
|
||
|
||
### 11.2 代码维护
|
||
- `preprocess.py` 保留作为 v1 基准(不再改动)
|
||
- 新增功能在 `preprocess_v2.py` 上演进,重大版本切到 `preprocess_v3.py`
|
||
- 实验性功能放 `experiments/` 子目录
|
||
|
||
### 11.3 数据维护
|
||
- 新增的真值样本放 `未识别/` 目录,文件名即真值
|
||
- 误识别的样本单独标记,作为难例集合(后续训练用)
|