142 lines
4.9 KiB
Markdown
142 lines
4.9 KiB
Markdown
# miniappB — 纯 JavaScript 试纸识别引擎
|
||
|
||
## 概述
|
||
|
||
零依赖纯 JavaScript 实现的尿检试纸识别引擎,从零构建全部图像处理原语(色彩空间转换、高斯模糊、形态学运算、边缘检测、轮廓提取、PCA最小外接矩形等),完全不依赖 OpenCV 或任何外部图像库。
|
||
|
||
## 项目定位
|
||
|
||
| 方案 | 技术栈 | 产物大小 | 定位 |
|
||
|------|--------|---------|------|
|
||
| miniappA | C++ → Emscripten → WASM | WASM 1014KB (gzip 348KB) | 高性能,接近原生 C++ 精度 |
|
||
| **miniappB** | **纯 JavaScript** | **JS 约 40KB** | 零依赖,适合微信小程序等受限环境 |
|
||
|
||
## 快速开始
|
||
|
||
```bash
|
||
# 安装依赖(仅用于 Node.js 测试环境读取图片)
|
||
npm install
|
||
|
||
# 运行单张图片测试
|
||
node test.js
|
||
|
||
# 运行诊断脚本(查看每个处理阶段)
|
||
node diagnose2.js # 蓝/绿图片
|
||
node diagnose.js # 红/蓝图片
|
||
|
||
# 批量测试所有图片
|
||
node test_pipeline.js
|
||
node test_real_images.js
|
||
|
||
# 启动 Web 演示服务器
|
||
python3 server.py
|
||
# 浏览器访问 http://localhost:8909
|
||
```
|
||
|
||
## 识别流程
|
||
|
||
```
|
||
RGBA 像素 → BGR → 灰度 + 高斯模糊
|
||
→ HSV 颜色分割 (蓝/绿/红 Mask)
|
||
→ 形态学闭运算 → 轮廓提取
|
||
→ 定位块检测 (最近邻 AR 分类)
|
||
→ 配对验证 (面积比 + 颜色一致性)
|
||
→ 试纸规格匹配 (14/11/8 项)
|
||
→ 色块中心计算 → 颜色采样
|
||
→ 生成标注图
|
||
```
|
||
|
||
## 关键参数
|
||
|
||
| 参数 | 值 | 说明 |
|
||
|------|-----|------|
|
||
| 大定位块 AR (短) | 2.0 ± 0.35 | 轮廓宽高比判定 |
|
||
| 大定位块 AR (长) | 3.0 ± 0.35 | 轮廓宽高比判定 |
|
||
| 小定位块 AR | 1.667 ± 0.50 | 轮廓宽高比判定(容差更宽) |
|
||
| 最小轮廓面积 | 100px² | 过滤噪声 |
|
||
| 配对面积比 | 3.33–5.0 | 大小块面积比例 |
|
||
|
||
## 支持的定位块颜色
|
||
|
||
- 🔵 **蓝色** (H: 180–260)
|
||
- 🟢 **绿色** (H: 80–170)
|
||
- 🔴 **红色** (H: 0–15 或 340–360)
|
||
|
||
## 支持的试纸类型
|
||
|
||
| 类型 | 色块数 | 类型 | 色块数 |
|
||
|------|--------|------|--------|
|
||
| 14_S (短型) | 14 | 14_L (长型) | 14 |
|
||
| 11_S (短型) | 11 | 11_L (长型) | 11 |
|
||
| 8_S (短型) | 8 | 8_L (长型) | 8 |
|
||
|
||
## 测试结果 (cpp/images/)
|
||
|
||
| 图片 | 检测类型 | 色块数 | 定位块颜色 | 状态 |
|
||
|------|---------|--------|-----------|------|
|
||
| 14blue_1.png | 14_S | 14 | 🔵 BLUE | ✅ |
|
||
| 14blue_2.png | 14_L | 14 | 🔵 BLUE | ✅ |
|
||
| 14red_1.png | 11_S | 11 | 🔴 RED | ✅ |
|
||
| 14red_2.png | 11_S | 11 | 🔴 RED | ✅ |
|
||
| 11green_1.png | 8_S | 8 | 🟢 GREEN | ✅ |
|
||
| 11green_2.png | 8_S | 8 | 🟢 GREEN | ✅ |
|
||
|
||
> **说明**:部分图片文件名与检测结果不一致(如 14red → 11 项、11green → 8 项),这些图片本身是 `cpp/images/` 中的干扰测试图片,定位块间距比例或拍摄角度导致算法将其归类为不同规格。
|
||
|
||
## API 接口
|
||
|
||
```javascript
|
||
const { PaperRecognizer, PST_NAMES } = require('./paper-recognizer.js');
|
||
|
||
const recognizer = new PaperRecognizer();
|
||
const result = recognizer.recognize(rgbaData, width, height);
|
||
// result.success: boolean
|
||
// result.paperType: 1=14_S, 2=14_L, 3=11_S, 4=11_L, 5=8_S, 6=8_L
|
||
// result.itemCount: 色块数量
|
||
// result.locatorColor: 1=RED, 2=GREEN, 3=BLUE
|
||
// result.colorBlockCenters: [{x, y}, ...]
|
||
// result.colors: [{id, r, g, b}, ...]
|
||
// result.annotatedImage: ImageData (标注图)
|
||
|
||
// 获取标注图像素(BGRA)
|
||
const annotatedPixels = recognizer.getAnnotatedPixels();
|
||
const w = recognizer.getAnnotatedWidth();
|
||
const h = recognizer.getAnnotatedHeight();
|
||
|
||
recognizer.free();
|
||
```
|
||
|
||
## 文件结构
|
||
|
||
```
|
||
miniappB/
|
||
├── paper-recognizer.js # 核心识别引擎 (1036 行)
|
||
├── test.js # 基本测试
|
||
├── diagnose.js # 红/蓝图片诊断
|
||
├── diagnose2.js # 蓝/绿图片诊断
|
||
├── test_pipeline.js # 批量测试
|
||
├── test_real_images.js # 真实图片测试
|
||
├── server.py # Web 演示服务器 (端口 8909)
|
||
├── index.html # 浏览器端演示
|
||
├── gen_samples.py # 生成测试样例图片
|
||
├── samples/ # 测试输出图片
|
||
└── package.json # canvas 依赖 (仅 Node 测试)
|
||
```
|
||
|
||
## 已知限制
|
||
|
||
1. **HSV 颜色分割**对光照变化敏感,极端光照下可能漏检定位块
|
||
2. **小定位块宽高比**容差较宽 (0.50),可能将部分非定位块错误纳入
|
||
3. 纯 JS 实现**性能不如 WASM 方案**,大图处理较慢(单张 1024×768 约 200–500ms)
|
||
4. 不支持严重透视变形或大角度旋转的试纸图片
|
||
|
||
## 与 C++ 原版的差异
|
||
|
||
| 项目 | C++ 原版 | JS 移植 |
|
||
|------|---------|---------|
|
||
| OpenCV 依赖 | core+imgproc+imgcodecs | 无(自实现) |
|
||
| 大/小块分类 | 重叠区间(可能自配对) | 最近邻分类 + 自配对防护 |
|
||
| 匹配阈值 | 严格开区间(存在间隙) | 连续区间(消除间隙) |
|
||
| 红色支持 | ✅ | ✅(已添加) |
|
||
| 后备配对 | ❌ | ✅(双大块配对) |
|