4.9 KiB
4.9 KiB
miniappB — 纯 JavaScript 试纸识别引擎
概述
零依赖纯 JavaScript 实现的尿检试纸识别引擎,从零构建全部图像处理原语(色彩空间转换、高斯模糊、形态学运算、边缘检测、轮廓提取、PCA最小外接矩形等),完全不依赖 OpenCV 或任何外部图像库。
项目定位
| 方案 | 技术栈 | 产物大小 | 定位 |
|---|---|---|---|
| miniappA | C++ → Emscripten → WASM | WASM 1014KB (gzip 348KB) | 高性能,接近原生 C++ 精度 |
| miniappB | 纯 JavaScript | JS 约 40KB | 零依赖,适合微信小程序等受限环境 |
快速开始
# 安装依赖(仅用于 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 接口
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 测试)
已知限制
- HSV 颜色分割对光照变化敏感,极端光照下可能漏检定位块
- 小定位块宽高比容差较宽 (0.50),可能将部分非定位块错误纳入
- 纯 JS 实现性能不如 WASM 方案,大图处理较慢(单张 1024×768 约 200–500ms)
- 不支持严重透视变形或大角度旋转的试纸图片
与 C++ 原版的差异
| 项目 | C++ 原版 | JS 移植 |
|---|---|---|
| OpenCV 依赖 | core+imgproc+imgcodecs | 无(自实现) |
| 大/小块分类 | 重叠区间(可能自配对) | 最近邻分类 + 自配对防护 |
| 匹配阈值 | 严格开区间(存在间隙) | 连续区间(消除间隙) |
| 红色支持 | ✅ | ✅(已添加) |
| 后备配对 | ❌ | ✅(双大块配对) |