Files
nanocode/web-opencv/miniapp
Ubuntu 32b43f85bd a
2026-07-03 16:58:28 +08:00
..
a
2026-07-03 16:58:28 +08:00
a
2026-07-03 16:58:28 +08:00

paper-recognizer — 微信小程序尿检试纸识别

纯 JavaScript 实现,零依赖,约 40KB。复制即用。

文件说明

miniapp/
├── paper-recognizer.js    # 核心识别引擎(唯一必需文件)
└── README.md

快速集成

1. 复制文件

将 paper-recognizer.js 放入小程序项目的 utils/ 目录。

2. 页面引入

// pages/recognize/recognize.js
const { PaperRecognizer } = require('../../utils/paper-recognizer.js');
const recognizer = new PaperRecognizer();

3. 拍照识别

Page({
  data: { result: null },

  // 拍照
  onTakePhoto() {
    wx.chooseImage({
      count: 1,
      sourceType: ['camera'],
      success: (res) => this.doRecognize(res.tempFilePaths[0])
    });
  },

  // 识别
  doRecognize(filePath) {
    wx.getImageInfo({
      src: filePath,
      success: (info) => {
        // 建议长边超过 1500px 时先缩放,保证性能
        const maxLen = 1500;
        let w = info.width, h = info.height;
        if (Math.max(w, h) > maxLen) {
          const scale = maxLen / Math.max(w, h);
          w = Math.round(w * scale);
          h = Math.round(h * scale);
        }

        // 离屏 Canvas 获取像素
        const ctx = wx.createCanvasContext('offscreenCanvas', this);
        ctx.drawImage(filePath, 0, 0, w, h);
        ctx.draw(false, () => {
          wx.canvasGetImageData({
            canvasId: 'offscreenCanvas',
            x: 0, y: 0, width: w, height: h,
            success: (res) => {
              const rgba = new Uint8Array(res.data);
              const result = this.recognizer.recognize(rgba, w, h);

              if (result.success) {
                console.log('试纸类型:', result.paperType);
                console.log('色块数量:', result.itemCount);
                console.log('定位块颜色:', result.locatorColor);
                console.log('颜色数据:', result.colors);
              } else {
                console.error('识别失败:', result.errorCode, result.errorMessage);
              }
            }
          });
        });
      }
    });
  }
});

3. 相册选图识别

wx.chooseImage({
  count: 1,
  sourceType: ['album'],
  success: (res) => this.doRecognize(res.tempFilePaths[0])
});

识别结果字段

字段 类型 说明
success boolean 是否成功
errorCode number 错误码(成功为 0)
errorMessage string 错误描述
paperType string 试纸类型,如 "14_S", "11_L"
itemCount number 色块数量
locatorColor string 定位块颜色 "Red"/"Green"/"Blue"
smallLocatorOnLeft boolean 小定位块是否在左侧
blurLevel string 清晰度 "None"/"Slight"/"Severe"
blurScore number 清晰度分数(越高越清晰,>300 为 None)
colors array 色块颜色数组 [{id, r, g, b}, ...]

错误码

码 含义
0 成功
-1 未找到定位块
-2 定位块配对失败
-3 定位块颜色不一致
-4 未找到匹配的试纸配置
-5 未知试纸类型

性能参考

图片分辨率 预估耗时 建议
< 800×100 < 20ms 直接处理
~1100×400 ~150ms 直接处理
~2500×1100 ~600ms 建议缩放到 1500px
> 3000px > 1s 必须缩放

注意事项

  1. Canvas 必须存在于 WXML 中 — 即使隐藏也要声明:
<canvas canvas-id="offscreenCanvas"
  style="position:fixed;top:-9999px;left:-9999px;width:750px;height:750px;">
</canvas>
  1. 拍照时保持试纸平整 — 严重透视变形或大角度旋转可能导致识别失败。

  2. 光照均匀 — 算法使用 HSV 颜色分割,极端光照(强反光、暗光)下定位块可能漏检。

  3. 仅支持 14/11/8 项试纸 — 支持短型(S)和长型(L)两种规格。

试纸类型清单

paperType itemCount 说明
14_S 14 14 项短型
14_L 14 14 项长型
11_S 11 11 项短型
11_L 11 11 项长型
8_S 8 8 项短型
8_L 8 8 项长型