更新记录

0.1.0(2026-09-30)

首次发布预览版。

新增

  • 纯本地离线 OCR:PP-OCRv5 mobile 检测 + 识别,ONNX Runtime 推理,全程不联网、不上传。
  • 13 种识别模式:普通文本、身份证正/反面、车牌、银行卡、营业执照、自定义证件、社保卡、发票、车架号 VIN、行驶证、手机号、电动车牌。
  • 字段级国标校验与纠错:GB 11643(身份证)、GA 36(车牌)、GB 32100(统一社会信用代码)、ISO 3779(VIN)、Luhn(银行卡)。校验不通过时结果仍返回并给出原因;仅在纠正结果唯一可信时才自动纠正。
  • 真实证件适配:同行多框合并(证件标签字距大会被切成两个框)、按垂直重叠率分组、水印行丢弃、印章文字截断、地址跨行块提取、相册图方向搜索、车牌按牌面颜色做 ROI 定位。
  • API:ocrRecognize、ocrRecognizeAlbum、getBase64FromFilePath、ocrPrepare、ocrRelease。
  • 初始化失败原因可通过 ocrPrepare 回调的 error 与 logcat 标签 offline-ocr 获取。
  • 随包 THIRD-PARTY-NOTICES.md:内置开源组件(ONNX Runtime / MIT、PaddleOCR PP-OCRv5 模型与字符表 / Apache-2.0)的许可声明、我们所做改动说明与 SHA-256 校验值。

已知限制

  • 仅 Android(arm64-v8a,minSdk 21)。iOS / HarmonyOS 未包含在本版本。
  • v1 不含内置取景界面与透视矫正,图片需由调用方用 uni.chooseImage 取得后传 imagePath。
  • 推理库锁定 ONNX Runtime 1.19.2(其 aar 自带 manifest 声明 minSdk 21,可覆盖 Android 5~7 的旧手持机/PDA;1.22.0 起要求 minSdk 24)。详见 README「关于 ONNX Runtime 版本」。
  • 不内置发卡行(BIN)名称库。
  • 识别率实测样本量有限(每类 1 张真件 + 合成件),批量准确率请以自测为准。

平台兼容性

uni-app x(5.26)

Chrome Safari Android iOS 鸿蒙 微信小程序
× × 5.0 × × ×

其他

多语言 暗黑模式 宽屏模式 蒸汽模式
× × × √

离线 OCR 文本识别(身份证 / 车牌 / 银行卡 / 营业执照 / 社保卡 / 车架号 VIN)

三端同一引擎的纯本地证件 OCR 插件:不联网、不上传任何图片、无调用次数限制、无后端依赖。

与市面同类插件最关键的两点差异:

  1. 三端加载同一份 PP-OCRv5 模型、同一套前后处理与字段规则(规则写在 utssdk/ 根目录的共享 UTS 源码里,编译到 Kotlin / Swift / ArkTS),因此同一张图在 Android、iOS、鸿蒙上得到完全一致的结构化结果。分平台各调一套系统 OCR 的实现做不到这一点。
  2. 字段级国标校验。识别出的号码不是"读出来就交给你",而是逐个过校验位并把结论一起返回:
字段 标准 校验内容
身份证号 GB 11643-1999 省份码 + 出生日期合法性 + mod 11 校验位
车牌号 GA 36-2018 省份简称白名单 + 序号字符规则 + 新能源 D/F 位 + 使领/港澳入境
统一社会信用代码 GB 32100-2015 31 字符集(不含 I O S Z V)+ 加权模 31 校验位
车架号 VIN ISO 3779 / 3729 17 位字符集(不含 I O Q)+ mod 11 校验位
银行卡号 ISO/IEC 7812 13~19 位 + Luhn

校验不通过时结果照样返回,但会明确告诉你哪条规则没过、原因是什么、以及哪些字段被自动纠正过(见 result.verify)。

同时做易混字符纠正:车牌字符集本身不含 I/O,所以 I→1、O→0 可以无损还原;VIN 受反光锈蚀影响大的 18 组形近字符做单点替换,只有当校验位能唯一确定答案时才接受,多解或无解一律不猜、原样返回并标记未通过。


一、平台支持

平台 支持情况 说明
Android 支持 arm64-v8a;minSdk 21;需云打包(含三方 AAR)
iOS 未实现 平台支持表按实标注为 -,不谎报;需要 iOS 请勿购买本版
HarmonyOS NEXT 未实现 同上
H5 / 小程序 不支持 依赖原生推理

请以下方「版本信息」与 changelog 中的实测记录为准。未在你目标机型上验证过的项目,不要假定一定可用;本 README 不宣称未经实测的能力。

关于 ONNX Runtime 版本(影响你的 minSdk)

模型与推理库的 minSdk 是绑死的,实测各 AAR 自带 manifest 声明:1.22.0 要求 minSdk 24,1.19.2 / 1.17.0 要求 minSdk 21。

本插件锁定 1.19.2,为的是保住 Android 5~7 设备——证件 OCR 的主力客户里很大一块是停车场、物流、政务窗口用的手持终端/PDA,系统版本普遍偏旧。用到的 8 个 ORT API 已逐签名核对与新版一致,若你的工程本身 minSdk ≥ 24 想换新版,替换 utssdk/app-android/libs/ 下的 AAR 即可,代码无需改动。

三端差异(务必阅读)

  • Android 已在本机完成编译验证(UTS→Kotlin 编译通过、宿主 App 编译通过),真机识别结果见「实测数据」。
  • iOS / 鸿蒙:共享层(字段规则、校验、同行合并)与 Android 是同一份 UTS 源码,逻辑一致;native 取图与推理封装需各自平台的二进制依赖(iOS 需 onnxruntime.xcframework,鸿蒙需 @ohos/onnxruntime HAR)。推理库本身的获取路径不是障碍(Microsoft.ML.OnnxRuntime NuGet 包内即含 iOS xcframework 三切片),本版本未交付这两端的真实原因是没有可编译、可验证的环境(无 macOS/Xcode、无对应真机),因此不做无法验证的承诺。若你购买的版本尚未包含对应端实现,插件会在该端返回错误码 9020008,不会静默失败。

二、安装

环境要求

  • HBuilderX 4.24+(uni_modules 规范插件)
  • uni-app(Vue3)或 uni-app x 项目均可
  • 因为本插件带三方原生依赖,标准基座不能运行,必须使用自定义调试基座或正式云打包。 运行到手机时报「模型加载失败」,绝大多数情况就是还在用标准基座。

步骤

  1. 插件市场点「下载插件并导入 HBuilderX」,或把 uni_modules/zdd-ocr-recognize 整个目录拷进你的工程根目录下的 uni_modules/。
  2. manifest.json → App 权限配置:勾选 Camera、Gallery(相机和相册)。 从 HBuilderX 3.6.11 起云打包默认不再包含这两个模块,不勾选时 uni.chooseImage 会直接失败。
  3. 生成自定义调试基座(发行 → 原生App-云打包 → 勾选"打自定义调试基座"),然后运行到手机时选择自定义基座。
  4. 首次识别会自动从安装包内解压并加载模型(约 1~2 秒);建议在页面空闲时调 ocrPrepare 预热。

三、快速开始

import { ocrRecognize, ocrPrepare } from '@/uni_modules/zdd-ocr-recognize'

export default {
  methods: {
    // 1) 先用 uni.chooseImage 取图(三端同一套用法,权限由 uni-app 处理)
    pickAndRecognize() {
      uni.chooseImage({
        count: 1,
        sourceType: ['camera'], // 或 ['album']
        success: (e) => this.recognize(e.tempFilePaths[0])
      })
    },

    // 2) 把路径交给插件,recognizeType 决定证件类型
    recognize(path) {
      ocrRecognize({
        recognizeType: 1,        // 1 = 身份证正面
        imagePath: path,
        needVerify: true,
        success: (res) => {
          const d = res.result
          console.log('姓名', d.name, '号码', d.idNo)
          console.log('校验是否通过', d.verify.passed, d.verify.rules, d.verify.reasons)
        },
        fail: (err) => console.log('失败', err.code, err.message)
      })
    }
  }
}

uni-app x(uvue)写法需要显式类型:

import { ocrRecognize, OCROptions } from '@/uni_modules/zdd-ocr-recognize'

const opt = {
  recognizeType: 4,          // 银行卡
  imagePath: '/storage/emulated/0/Download/card.jpg'
} as OCROptions

ocrRecognize(opt)

四、API

4.1 ocrRecognize(options)

参数 类型 默认 说明
imagePath string 必填 图片本地路径。接受 chooseImage 返回的临时路径、file://、content://、_doc/
recognizeType number 0 识别模式,见下表
needVerify boolean true 是否执行国标校验并回填纠正结果
needCropImage boolean true 是否额外保存并返回裁剪后的证件图路径
customizeTags string "" 仅 recognizeType=6:自定义字段名 JSON 数组串,最多 15 项
recognizeType 之外的取景类参数 — — scanHintText、showPhotoAlbum、scanColor、bgColor、showBeep、showVibrate、isSupportZoom、showLightController、forceVertical、imgLocation、pickTextFromImg、textAreaType、pickTextAreaType、multiVerify、skipMatchParams、cameraDevice、customerToken 等,为 v2 内置取景界面预留,当前版本传入不报错也不生效

回调:success(res: OCRResult) / fail(err) / complete(res)。

4.2 ocrRecognizeAlbum({ imagePaths, recognizeType, breakOnError, complete })

批量识别相册图片。串行执行(避免多张图同时占内存),res.items 与入参顺序一致,单张失败不影响其余。

4.3 getBase64FromFilePath({ imagePath, success, fail })

图片转 base64(不含 data: 前缀,res.mime 为 jpeg)。内部会先降采样到 1280 长边,避免大图 base64 撑爆内存。

4.4 ocrPrepare(complete)

预热模型。回调参数为 { ready: boolean, error: string }。 error 一定要打印出来——加载失败的真实原因(缺依赖、资源未进包等)全在这里,只看 ready 会无从排查。

4.5 ocrRelease()

释放模型内存。App 长时间不再识别时调用;下次识别会自动重新加载。


五、识别模式与返回字段

res.result 为扁平结构,只填充当前模式相关字段,其余为 null。所有模式都会填 imagePath。

recognizeType 模式 返回字段
0 普通文本 text、lines[{text,box,confidence}]
1 身份证正面 name sex nation birthday(yyyy-MM-dd) address idNo
2 身份证反面 validPeriod(yyyy-MM-dd 至 yyyy-MM-dd) issueOrg
3 车牌 licensePlate licensePlateType licensePlateTypeName
4 银行卡 cardId bankInfo validDate cardScheme
5 营业执照 businessName socialCreditCode businessType businessAddress legalPeople registerMoney createDate validDate businessScope businessLicenseNumber
6 自定义证件 fields(Map,键为 customizeTags 里的字段名)
7 社保卡 name socialSecurityNumber bankCardNo bankCardType cardNo
8 发票 invoiceCode invoiceNumber invoiceDate invoiceAmount invoiceTotal buyerName sellerName
9 车架号 VIN vin
10 行驶证 owner licensePlate vin vehicleType bandType engineNo registerDate issueDate address
11 手机号 phoneNumbers(数组,已去重)
12 电动车/自行车牌 licensePlate

licensePlateType 取值:0 未知、1 常规蓝牌、2 新能源、3 黄牌、4 白牌(军警)、5 使领馆、6 港澳入境、7 电动车牌。 该枚举为本插件自定义,不与任何其他插件的数值互通,迁移需按名称重映射。

result.verify

{
  passed: true,                 // 主字段是否通过国标校验
  rules: ["idCardChecksum"],    // 命中的规则
  reasons: [],                  // 未通过的原因(人类可读)
  correctedFields: ["idNo"]     // 被自动纠正过的字段名
}

passed=false 不代表结果一定错,只代表它无法自证。建议业务侧的处理策略:passed=true 直接入库;passed=false 展示原文让用户确认。


六、实测数据

真机(华为 HMA-AL00 / Android 10 / arm64,2026-09-30)

通过页面自动回归跑完整链路(ocrPrepare → 读图 → det → rec → 同行合并 → 字段抽取 → 国标校验),结果从 logcat 机器可读输出采集:

类型 耗时 校验规则 关键结果
身份证正面 912ms idCardChecksum 通过 姓名/号码/出生日期/民族/性别正确,住址跨 3 行正确合并
车牌 263ms plateGA36 通过 粤R888G8(装饰圆点已剥离),类型"常规车牌"
银行卡 1075ms luhn 通过 6231020501000087054、UnionPay、威海市商业银行
营业执照 3048ms usccChecksum 通过 名称、91310112MAD5T2164X、法定代表人(红章文字已剥离)、2023-11-28 至 2027-12-11
车架号 VIN 1304ms vinChecksum 通过 LS5A2DKE2MA263439

冷启动首次识别含模型加载约多花 350ms(实测 1320ms vs 预热后 969ms),所以建议在页面空闲时先调 ocrPrepare。

取图方式会影响识别结果(重要)

同一张身份证照片,uni.chooseImage 默认返回的是压缩重编码后的临时文件,而压缩会引入模型误读。实测同一张图:

输入 未加保护时的姓名取值
原始文件 龚友强
JPEG 质量 0.8 重编码 姓名b → 姓名被解析成 b龚友强

JPEG 压缩在标签区产生的伪字符会被检测框吸附到标签上,于是"取标签之后的内容"就把噪声一起取了进来。

插件侧已做防护:姓名字段按 CJK 白名单清洗(只保留汉字与少数民族姓名的间隔号),压缩引入的拉丁字母会被剥掉,清洗后为空则退回原值。

调用侧建议:能取原图就取原图 —— uni.chooseImage({ sizeType: ['original'] })。

样本量诚实说明:以上每类各只有 1 张实拍样本。它证明的是"链路对这些真实版式能跑通且字段正确",不等于批量识别率。真实识别率需要每类 ≥50 张不同机型、光线、角度的样本统计,购买后请按你的实际场景自测。

已记录的能力边界

  • 形近汉字仍会错:营业执照"2幢323室"两端都读成"2输323室";同一路名 PC 读"幸福路"、真机读"李福路",说明低对比度小字已在模型判定边界上。
  • 银行卡有效期没有校验位,因此要求它必须未过期才输出(实测真机会把无关数字读成 12/12 并当成有效期)。

七、能力边界(会踩到,请看完)

  1. v1 不含内置取景界面。图片必须由调用方用 uni.chooseImage 等方式取得后传 imagePath。实时预览、边框检测、自动抓拍在 v2。
  2. 倾斜/弯曲不矫正。v1 只做轴对齐裁剪,不做透视变换。拍歪的卡证请重拍,或自行做矫正后传入。
  3. 形近汉字会错。实测把营业执照"2幢323室"读成"2输323室"。汉字形近误识是当前模型的固有边界,无校验位的字段(姓名、地址、经营范围)无法自动发现。
  4. 背景水印会产生假文本框。证件满版水印(如营业执照的 SCJDGL)置信度可达 0.88,插件按规则丢弃"无中文的纯大写拉丁短行",但不能保证全部滤净。
  5. 照片方向。手机照片可能物理旋转而 EXIF 未标记,插件会做方向搜索兜底,但会增加耗时;取景时保持横平竖直最稳。
  6. 发卡行名称不内置。准确的 BIN→银行 映射需要持牌数据源,插件不内置猜测表。bankInfo 返回的是卡面上识别到的银行名称文字,cardScheme 是按公开号段规则判定的卡组织。
  7. 各地电动车牌规则不统一。编码长度与规则各城市不同,模式 12 只保证"不输出非法串",不保证种类判定正确。
  8. 军警白牌不做颜色定位(与背景对比度太低),会退回通用文本检测,成功率下降。
  9. 文件扩展名不可信。遇到过实际是 WebP 却命名为 .jpg 的相册图;插件按内容解码,但请确保来源格式在平台解码能力范围内。
  10. 包体积:模型约 21MB + 推理库约 28MB,会明显增加安装包体积。只投 arm64 可再减小。

八、隐私与合规

  • 全部识别在设备本地完成,不联网、不采集、不上传任何图片或识别结果,插件不申请网络权限。
  • 但你的 App 用本插件处理身份证等个人敏感信息时,仍需按《个人信息保护法》履行告知同意、在隐私政策中列明摄像头/相册权限与用途,并满足各应用市场的审核要求。插件本身不提供合规承诺。
  • 若上架国内应用市场,还需在 manifest 中配置隐私政策相关项,否则云打包会给出提示。
  • 内置开源组件:ONNX Runtime(MIT)+ PaddleOCR / PP-OCRv5 模型与字符表(Apache-2.0)。两者的许可均允许商用与再分发;完整声明、我们所做改动及文件校验值见插件包内 THIRD-PARTY-NOTICES.md,请勿删除该文件。
  • 识别能力来自 PP-OCRv5 通用文字模型,不是 PaddlePaddle 官方对本插件准确率的背书;所有字段校验规则(GB 11643、GA 36、GB 32100、ISO 3779、Luhn)由本插件自行实现。

九、错误码

码 含义 常见原因
9020001 用户取消 取图取消
9020002 / 9020003 相机 / 相册权限被拒 系统权限未授予
9020004 图片读取失败 路径失效、文件被移动
9020005 图片解码失败 格式不支持或文件损坏
9020006 模型资源缺失 插件 assets 未完整打进包
9020007 引擎初始化失败 在用标准基座运行;或缺三方库
9020008 当前平台不支持该模式 该端尚未实现
9020009 推理失败 内存不足、图片过大
9020010 未检测到有效文本区域 距离太远、光线差、角度歪
9020011 字段校验未通过 结果仍返回,见 verify.reasons
9020012 参数非法 未传 imagePath 等

ocrPrepare 的 error 字段会带上底层异常原文,排查时优先看它和 logcat 的 offline-ocr 标签。


十、FAQ

Q:为什么报"模型加载失败"? A:九成是在用标准基座。本插件含三方原生依赖,必须打自定义调试基座。请先调 ocrPrepare 并把 error 打印出来确认。

Q:uni.chooseImage 报 chooseImage:fail 路径不存在,但插件没报错? A:这是取图阶段的权限问题,插件根本没被调用。部分国产 ROM(华为 EMUI 等)不会自动授予相机/存储运行时权限,即使清单里已声明、即使用 adb install -g 安装。到系统设置里手动授予后重试。排查时先看引擎状态:如果还是 idle,说明失败发生在插件之前。

Q:姓名/号码前面多出一个字母或符号? A:uni.chooseImage 默认返回压缩重编码的临时文件,JPEG 压缩会在卡面标签区产生被模型误读的伪字符。已实测并加了 CJK 清洗保护。建议调用时传 sizeType: ['original']。

Q:能不能不传 imagePath,让插件自己开相机? A:v1 不行,用 uni.chooseImage 即可,三端一致且权限已由 uni-app 处理。内置取景在 v2。

Q:识别一张要多久? A:与机型和文字量相关。建议先 ocrPrepare 预热,避免把首次加载的 1~2 秒算进第一次识别。

Q:能同时支持 32 位设备吗? A:当前只保证 arm64-v8a。需要 armeabi-v7a 请先联系确认。

Q:识别结果能直接入库吗? A:verify.passed === true 的字段可以直接入库;为 false 的必须人工确认,因为号码类字段一旦校验位不对就是错的。

隐私、权限声明

1. 本插件需要申请的系统权限列表:

android.permission.CAMERA(仅当业务侧自行调起相机时由宿主声明);插件本身只读入业务传入的图片文件路径

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

插件不采集、不上传任何数据,全部识别在设备本地完成,无需网络

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

无

暂无用户评论。