# 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 | 无(自实现) | | 大/小块分类 | 重叠区间(可能自配对) | 最近邻分类 + 自配对防护 | | 匹配阈值 | 严格开区间(存在间隙) | 连续区间(消除间隙) | | 红色支持 | ✅ | ✅(已添加) | | 后备配对 | ❌ | ✅(双大块配对) |