更新记录

1.0.0(2026-09-13)

首个版本发布。

  • VIN(车架号)识别:17 位车架号识别 + 规则纠正 + ISO 3779 校验位校验; 支持相机实时取景、系统相册选图、图片路径 / URI 三种入口。
  • 车牌(PLATE)识别:车牌号识别 + 车牌类型判定 + 结构合规与字符集校验; 同样支持相机取景、相册选图、按路径识别。
  • 三端支持:Android、iOS、HarmonyOS,对外方法名与参数完全一致,业务侧无需写条件编译。
  • 全离线运行:无需网络、无需填写任何 Key——Android 走 ML Kit + HyperLPR3, iOS 走 Vision + HyperLPR3,HarmonyOS 走系统 OCR + 车牌规则。
  • 取景浮层样式可配:取景框高度、提示文案、文案字号与颜色、边框颜色均由业务侧透传。
  • 详细用法、参数说明、错误码与注意事项见 readme.md

说明:鸿蒙端的相机实时取景依赖项目根目录下的 harmony-configs 原生页面文件,无法随插件自动安装; 若在鸿蒙端运行失败,请在购买后联系作者获取配置文件与调试协助。


平台兼容性

uni-app(5.24)

Vue2 Vue2插件版本 Vue3 Vue3插件版本 Chrome Safari app-vue app-nvue Android Android插件版本 iOS iOS插件版本 鸿蒙 鸿蒙插件版本
1.0.0 1.0.0 - - - - 5.1 1.0.0 12 1.0.0 19 1.0.0
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 小红书小程序 快应用-华为 快应用-联盟
- - - - - - - - - - - -

uni-app x(5.24)

Chrome Safari Android Android插件版本 iOS iOS插件版本 鸿蒙 鸿蒙插件版本 微信小程序
- - 5.1 1.0.0 12 1.0.0 19 1.0.0 -

xwq-ocr —— UTS 原生 OCR 插件(VIN 车架号 / 车牌识别)

xwq-ocr 是一个 uni-app / uni-app x 的 UTS 原生插件,提供离线的车架号(VIN)与车牌识别能力:

  • VIN(车架号)识别:17 位车架号识别 + 规则纠正 + ISO 3779 校验位校验
  • 车牌(PLATE)识别:车牌号识别 + 车牌类型 + 结构合规 / 字符集校验
  • 相机实时取景识别:全屏取景浮层,连续抓帧,命中即回调
  • 相册选图识别:从系统相册选图后识别
  • 按路径 / URI 识别:业务侧自己拿到图片路径也能直接识别

两条链路完全独立:车牌走专业车牌检测模型(Android/iOS 为 HyperLPR3,鸿蒙为系统 OCR + 车牌规则), VIN 走通用文字识别 + 车架号规则(Android 为 ML Kit,iOS 为 Vision,鸿蒙为 CoreVisionKit)。 不要指望用同一个接口既识车牌又识 VIN,必须按 recognizeType 分开调用。


一、平台支持

能力 Android iOS HarmonyOS
VIN 识别(按路径 / URI) ✅ ML Kit ✅ Vision ✅ CoreVisionKit
车牌识别(按路径 / URI) ✅ HyperLPR3 ✅ HyperLPR3 ✅ 系统 OCR + 车牌规则
相机实时取景 ✅ CameraX ✅ AVCaptureSession ⚠️ 见「鸿蒙端特别说明」
相册选图识别 ✅ 系统图库 ✅ UIImagePickerController ✅ PhotoViewPicker
需要模型文件 否(HyperLPR3 自带) 是(6 个 .mnn
是否联网 全离线 全离线 全离线

必须在 自定义基座 / 云打包 后生效(UTS 插件无法在标准基座里跑)。


二、安装与配置

1. 安装

把插件目录放到项目的 uni_modules/xwq-ocr(插件市场安装或手动拷贝均可), 然后在页面里按需引入:

import {
  openCardCamera, closeCamera,
  recognizeVinFromImagePath, recognizeVinFromUri, recognizeVin, releaseVinOcrService,
  recognizePlateFromImagePath, recognizePlateFromUri, recognizePlate, releasePlateOcrService,
  pickVinFromAlbum, pickPlateFromAlbum
} from '@/uni_modules/xwq-ocr'

2. 权限

平台 需要配置 位置
Android android.permission.CAMERA 插件已自带 utssdk/app-android/AndroidManifest.xml,云打包自动合并
iOS NSCameraUsageDescriptionNSPhotoLibraryUsageDescription 插件已自带 utssdk/app-ios/Info.plist,云打包自动合并
HarmonyOS ohos.permission.CAMERA 插件已自带 utssdk/app-harmony/module.json5

业务侧仍需在系统权限被拒绝时给出引导:Android/iOS 首次调用相机识别会弹系统权限框; 用户拒绝后本插件会通过 error 回调 type: 'CAMERA',请自行提示用户去设置里开启。


三、页面调用用例

1. 车架号(VIN)识别

<template>
  <view class="page">
    <button type="primary" @click="scanVin">📷 扫描车架号(VIN)</button>
    <button @click="albumVin">🖼 从相册选择</button>
    <button @click="pathVin">📁 选图详细识别</button>
    <text class="result">{{ vin }}</text>
  </view>
</template>

<script setup>
  import { ref } from 'vue'
  import {
    openCardCamera, recognizeVinFromImagePath, pickVinFromAlbum
  } from '@/uni_modules/xwq-ocr'

  const vin = ref('')

  // ① 相机实时取景:注意 recognizeType 必须是 'VIN'
  const scanVin = () => {
    vin.value = ''
    openCardCamera({
      recognizeType: 'VIN',      // ★ 识别类型:VIN / PLATE
      // ---- 取景浮层样式(VIN 页生效;不传就用默认值)----
      scanBoxHeight: 50,                       // 取景框高度(vp),内部收敛 20~300,默认 50
      markeTitle: '请将车架号对准取景框',        // 取景框下方提示文案,留空用默认
      scanBoxTitleSize: 16,                    // 提示文案字号(fp),内部收敛 10~32,默认 16
      scanBoxTitleColor: '#FFFFFF',            // 提示文案颜色 #RRGGBB / #AARRGGBB
      scanBoxBorderColor: '#00FF66',           // 取景框边框色 #RRGGBB / #AARRGGBB
      // ---- 回调 ----
      success: (val) => {
        // val.type === 'VIN'
        vin.value = val.option.vin
        console.log('校验位是否通过:', val.option.vinCheckDigitValid)
        console.log('命中来源:', val.option.vinSource)     // line / lineClean / wordJoin / window / wholeText
        console.log('OCR 原始文本:', val.option.vinRawText)
      },
      error: (err) => {
        console.log('识别失败:', err.type, err.msg)          // PARAM / IMAGE / OCR / VIN / CAMERA
        uni.showToast({ title: err.msg || '识别失败', icon: 'none' })
      },
      cancel: () => {
        console.log('用户取消取景')
      }
    })
  }

  // ② 相册识别:鸿蒙端与 iOS 端走插件原生相册;缺省时业务侧也可自行用 uni.chooseImage + 按路径识别
  const albumVin = () => {
    pickVinFromAlbum((val) => {
      vin.value = val.option.vin
    }, (err) => {
      uni.showToast({ title: err.msg || '识别失败', icon: 'none' })
    })
  }

  // ③ 业务侧自己选图后按路径识别(任意平台都可用,推荐通用写法)
  const pathVin = () => {
    uni.chooseImage({
      count: 1,
      success: (res) => {
        recognizeVinFromImagePath(res.tempFilePaths[0], (r) => {
          // 这里拿到的是完整详情对象,不是 option
          vin.value = r.vin
          console.log(r.source, r.checkDigitValid, r.charsetValid, r.rawText, r.matchedRaw)
        }, (err) => {
          console.log('识别失败:', err.type, err.msg)
        })
      }
    })
  }
</script>

2. 车牌(PLATE)识别

<script setup>
  import { ref } from 'vue'
  import { openCardCamera, recognizePlateFromImagePath, pickPlateFromAlbum } from '@/uni_modules/xwq-ocr'

  const plate = ref('')

  const scanPlate = () => {
    plate.value = ''
    openCardCamera({
      recognizeType: 'PLATE',    // ★ 车牌必须用 PLATE
      // 车牌页只用得到底部工具栏那句话;scanBoxHeight / scanBoxBorderColor 不生效(与 Android 行为一致)
      markeTitle: '正在识别中,请稍后...',
      scanBoxTitleSize: 16,
      scanBoxTitleColor: '#FFFFFF',
      success: (val) => {
        // val.type === 'PLATE'
        plate.value = val.option.plate
        console.log('车牌类型:', val.option.plateType)            // 蓝牌 / 黄牌单层 / 绿牌新能源 …
        console.log('结构是否合规:', val.option.plateCheckedValid)
        console.log('命中来源:', val.option.plateSource)          // 目前固定为 line
      },
      error: (err) => {
        uni.showToast({ title: err.msg || '识别失败', icon: 'none' })
      }
    })
  }
</script>

3. Vue2 / 选项式 API

import { openCardCamera } from '@/uni_modules/xwq-ocr'

export default {
  methods: {
    scan() {
      openCardCamera({
        recognizeType: 'PLATE',
        success: (val) => { this.plate = val.option.plate },
        error: (err) => { uni.showToast({ title: err.msg, icon: 'none' }) }
      })
    }
  },
  onUnload() {
    // 离开页面时务必关闭取景,避免浮层残留占用相机
    closeCamera()
  }
}

四、API 说明

API 作用 关键参数 回调返回
openCardCamera(params) 打开相机实时取景识别(按 recognizeType 分流) InitParamsType success({type, option}) / error({type,msg}) / cancel()
closeCamera() 关闭取景浮层(不触发任何回调
pickVinFromAlbum(success, error) 打开系统相册选图识别 VIN 两个回调 success({type:'VIN', option})
pickPlateFromAlbum(success, error) 打开系统相册选图识别车牌 两个回调 success({type:'PLATE', option})
recognizeVinFromImagePath(path, success, fail) 按图片路径识别 VIN(返回完整详情) string VinRecognizeResult / VinRecognizeError
recognizeVinFromUri(uri, success, fail) 按 URI 识别 VIN stringfile:// / 本地路径) 同上
recognizeVin(path, success, error) 按路径识别 VIN(回调形态同 openCardCamera string {type:'VIN', option} / {type, msg}
releaseVinOcrService() 释放 VIN 识别资源(长时间不用可调)
recognizePlateFromImagePath(path, success, fail) 按图片路径识别车牌(返回完整详情) string PlateRecognizeResult / PlateRecognizeError
recognizePlateFromUri(uri, success, fail) 按 URI 识别车牌 string 同上
recognizePlate(path, success, error) 按路径识别车牌(回调形态同 openCardCamera string {type:'PLATE', option} / {type, msg}
releasePlateOcrService() 释放车牌识别资源

三个平台的对外方法名与参数完全一致,业务侧不需要写条件编译


五、参数说明

5.1 openCardCamera 入参(InitParamsType

参数 类型 默认 说明
recognizeType 'VIN' \| 'PLATE' 必传。VIN 与车牌必须分开调用
scanBoxHeight number \| null VIN 50 / 车牌 80 取景框高度(vp),原生侧收敛到 20~300。仅 VIN 页生效
markeTitle string \| null 见下 提示文案,优先级高于 scanBoxTitle
scanBoxTitle string \| null 提示文案(备用字段,markeTitle 为空时取它)
scanBoxTitleSize number \| null 16 提示文案字号(fp),收敛到 10~32
scanBoxTitleColor string \| null #FFFFFF 提示文案颜色,#RRGGBB / #AARRGGBB,非法值自动回退
scanBoxBorderColor string \| null #00FF66 取景框边框色,仅 VIN 页生效
cameraType 'BACK' \| 'FRONT' \| null BACK 摄像头方向;目标方向没有摄像头时回退到系统默认摄像头
success (val) => void 识别成功回调
error (val) => void 识别失败回调
cancel (() => void) \| null 用户取消取景回调(不传则不回调)

默认提示文案:

  • VIN 页:请将车架号对准取景框
  • 车牌页:正在识别中,请稍后...

说明:上表就是 openCardCamera 的全部入参(InitParamsType 只有这些字段,多传会直接编译不过)。

5.2 成功回调 option 字段

VIN(successval.option):

字段 类型 说明
vin string 识别并纠正后的 17 位车架号
vinSource string 命中来源,见下表
vinCheckDigitValid boolean ISO 3779 校验位是否通过(false 建议提示用户确认或重拍)
vinCharsetValid boolean 是否全部落在 VIN 合法字符集内(不含 I/O/Q
vinRawText string OCR 整图原始文本(排查识别质量用)
vinMatchedRaw string 命中的那条候选原始文本

车牌(successval.option):

字段 类型 说明
plate string 车牌号(普通 7 位 / 新能源 8 位)
plateType string 车牌类型。Android / iOS 取 HyperLPR3 的号牌类型:蓝牌 / 黄牌单层 / 黄牌双层 / 白牌单层 / 绿牌新能源 / 黑牌港澳 / 香港单层 / 香港双层 / 澳门单层 / 澳门双层;鸿蒙端为 蓝牌 / 黄牌 / 新能源 / 港澳 / 警用 / 使领馆
plateSource string 命中来源,目前固定为 line
plateCheckedValid boolean 车牌结构是否合规(省简称 + 发牌字母 + 尾段结构,含新能源 D/F 位与尾字牌)
plateCharsetValid boolean 是否全部落在车牌合法字符集内(字母不含 I/O
plateRawText string OCR / 模型原始文本
plateMatchedRaw string 命中的原始文本

vinSource / plateSource 取值含义: line 单行命中、lineClean 单行清洗后命中、wordJoin 分词拼接命中、 window 滑动窗口命中、wholeText 整图兜底命中。 实际会出现哪些值随平台不同(车牌走专用模型时固定 line)。

5.3 recognizeVinFromImagePath / recognizePlateFromImagePath 的返回

这两个接口返回的是完整详情对象(不是 option):字段与上表同名但去掉前缀,例如 r.vin / r.source / r.checkDigitValid / r.charsetValid / r.rawText / r.matchedRaw, 车牌则是 r.plate / r.plateType / r.plateCheckedValid / r.charsetValid / r.rawText / r.matchedRaw

5.4 支持的图片来源

来源 是否支持
uni 相对路径(_doc/xxx_www/xxxstatic/xxx
沙盒绝对路径(/var/.../storage/...
file:// URI
Android content:// URI(系统图库返回)
网络图片 URL(http(s):// ❌ 请先下载到本地再传路径

六、错误码

error / fail 回调的 type 取值:

type 含义 常见 msg
PARAM 参数无效 图片地址无效
IMAGE 图片读取失败 图片文件不存在 / 图片解析失败
OCR 识别引擎级失败 文字识别失败 / 车牌识别引擎初始化失败 / 系统版本过低(iOS 需 13.0+)
VIN 没识别到有效车架号 未识别到有效的 17 位车架号(正常抖动,取景时会继续抓帧
PLATE 没识别到有效车牌 未识别到有效的车牌号(正常抖动,取景时会继续抓帧
CAMERA 相机相关失败 未获得相机权限 / 未找到可用摄像头 / 相机初始化失败 / 当前页面上下文不存在
ALBUM 相册相关失败 当前设备不支持访问相册 / 读取图片失败 / 图片读取失败

取景时「某一帧没识别到」不会回调 error(属正常现象),只有引擎级错误才会中断取景并回调。


七、鸿蒙端特别说明(重要)

鸿蒙端的相机实时取景(openCardCamera)可能无法直接运行,属于已知风险。

原因:鸿蒙侧的取景页是 ArkTS 原生页面,插件代码通过 windowStage.createSubWindow + setUIContent('pages/VinScannerPage') 拉起它们, 而 VinScannerPage.ets / PlateScannerPage.ets / VinRecognizer.ets / PlateRecognizer.ets 以及路由注册文件 main_pages.json 必须放在「你的项目根目录」下的 harmony-configs/entry/src/main/ets/pages/harmony-configs/entry/src/main/resources/base/profile/main_pages.json, 它们不属于 uni_modules 插件目录,无法随插件一起自动安装。 缺失这些文件时,鸿蒙端调用 openCardCamera 会打开取景子窗失败。

如果你在鸿蒙端运行失败,请在购买后联系作者,作者会把对应的 harmony-configs 文件发给你,并协助你完成配置与真机调试。 联系方式见插件市场页面的「插件作者」信息(也可以在插件市场页面留言)。

鸿蒙端其余能力(recognizeVinFromImagePath / recognizeVinFromUri / recognizeVin / recognizePlateFromImagePath / recognizePlateFromUri / recognizePlate / pickVinFromAlbum / pickPlateFromAlbum)不依赖上述页面文件,可以正常使用。 如果你的项目在鸿蒙端只想用「相册 + 按路径识别」而不要实时取景,可以只在 #ifndef APP-HARMONY 之外调用 openCardCamera,或改用 uni.chooseImage + recognizeXxxFromImagePath 的组合。


八、注意事项

  1. 必须自定义基座 / 云打包:UTS 原生插件无法在 HBuilderX 标准基座中运行,调试请打自定义调试基座。
  2. 离开页面务必关闭取景openCardCamera 是原生全屏浮层,页面 onUnload(Vue2)/ onUnmounted(Vue3) 时请调用 closeCamera(),否则浮层会残留并一直占用相机。 注意:调用 openCardCamera 拉起原生浮层时,当前页面不会触发 onHide,所以不要在 onHide 里关闭取景。
  3. 同一时刻只允许一个取景会话:重复调用 openCardCamera 会先关掉上一个浮层; 若此时页面上已有其它原生弹窗(例如系统相册),会回调 error当前已有页面正在展示,请稍后重试
  4. VIN 与车牌必须分开调用recognizeType 传错会得到识别失败。 车牌用的是专业车牌检测模型,它识别不了车架号;反之通用 OCR 也不适合直接认车牌。
  5. 识别结果是「尽力而为」,请务必结合 vinCheckDigitValid / plateCheckedValid 做二次判断, 校验位不通过的 VIN 建议提示用户确认或重拍;生产环境不要直接拿结果写库。
  6. releaseVinOcrService() / releasePlateOcrService() 用于长时间不用时释放资源; 注意车牌引擎(HyperLPR3)释放后无法重建,业务侧不要频繁调用,一般不需要调用。
  7. 首次调用会有明显延迟:车牌识别首次需要初始化模型(Android 拷贝模型、iOS 加载 6 个 .mnn), 建议在业务空闲时先调用一次「相册识别」预热,避免用户第一次点相机时等待过久。
  8. 相机取景为整屏浮层,Android/iOS 下会自动申请相机权限; 如果需要自定义权限引导文案,请在调用前自行判断并提示。
  9. 不要自己实现拍照后识别openCardCamera 已经是「连续抓帧 + 实时识别」, 命中才回调,比自己拍照再识别体验更好。
  10. 识别质量与环境强相关:光照、反光、角度、字号都会影响结果。 VIN 建议在车架号钢印/贴纸前保持 20~30cm 距离并让钢印充满取景框; 车牌建议正对车牌、避免强反光。
  11. Android 抓帧分辨率已锁定 16:9(1280x720 / 1920x1080 优先), 过低或非 16:9 的抓帧会让车牌检测失效,如自行改动请谨慎。
  12. 接口兼容性:升级插件时请保留 success / error / cancel 三个回调的写法, 这三次回调在三个平台上语义一致。

九、常见问题(FAQ)

Q:相机打开后一片黑 / 一直识别不到? A:先确认是自定义基座;再确认权限已授予;VIN 需让车架号落在取景框内, 车牌需正对车牌。识别不到时控制器不会报错,只会一直抓帧,可让用户调整距离重试。

Q:option 里的 vinSource / plateSource 为什么平台间不一样? A:不同平台的识别底座不同(Android ML Kit / iOS Vision / 鸿蒙 CoreVisionKit / 车牌专用模型), 命中来源自然不同,业务侧只把它们当调试信息用即可,不要依赖具体取值做业务判断。

Q:可以把识别结果直接展示给用户吗? A:可以,但建议同时展示校验位 / 结构合规状态,并在不合规时给用户二次确认的机会。

Q:鸿蒙端取景打不开? A:见第七章「鸿蒙端特别说明」,购买后联系作者获取 harmony-configs 文件。

隐私、权限声明

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

相机、相册

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

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

暂无用户评论。