更新记录

2.6.3(2026-09-24)

  • 注意(App-Android / uni-app x):UTS 编译到 Kotlin 后端时不生成可选参数的默认值,调用可选参数的 API 需显式传全, 例如 findContours(id, 'external', 'simple')、warpAffine(id, m, 0, 0)、distanceTransform(id, 0)、boxFilter(id, 9, 1); 省略会报 No value passed for parameter 'xxx'。传入的值与各端实现里 ?? 的默认值相同,故结果与省略时一致。 iOS / web / 小程序 / 鸿蒙后端不受此限制。

  • App 端(iOS / Android)路径兼容:loadImage 现在能直接接受 uni-app x 的虚拟路径与包内资源路径 —— unifile://...(如 uni.env.USER_DATA_PATH)、/static/...、static/...、_www/... 会先经 UTSiOS.convert2AbsFullPath / UTSAndroid.convert2AbsFullPath 转成真实文件路径; http(s)、data:、file:// 与普通绝对路径行为不变(原样透传)。 这样 App 端「内置示例图」这类包内静态资源也能直接加载,不必再依赖相册。

  • 说明:unifile:// 是运行时虚拟 scheme(实测 uni.env.USER_DATA_PATH = unifile://usr/), 原生 OpenCV 无法直接读取,故在插件侧统一转换。

  • 版本依赖:App 路径兼容在 Android 侧依赖 UTSAndroid.convert2AbsFullPath(uni-app x 3.90 起 / uni-app 的 UTS 插件内可用), iOS 侧依赖 UTSiOS.convert2AbsFullPath(uni-app x 4.11 起;本插件整体要求 HBuilderX ≥ 4.61,已覆盖)。 iOS 端转换先于 Android 侧落地(两次提交),对本版使用者无差别。

2.6.2(2026-09-23)

鸿蒙端交付改造:源码授权版零配置;插件包鸿蒙体积 22MB → 9MB

  • 源码授权版鸿蒙端:零配置。插件包不再散放裸 .so,改为随包提供只含原生库的载体 har (utssdk/app-harmony/libs/opencv-image-libs.har,9MB,内含 arm64-v8a + x86_64 两套 libopencv_bridge.so / libc++_shared.so),并在插件 utssdk/app-harmony/config.json 中声明该依赖 —— HBuilderX 生成鸿蒙工程时会自动把 har 拷入模块目录、按 config.json 生成模块 oh-package.json5, ohpm 再解包其中 libs/** 合并进应用。

    事项 之前(≤2.6.1) 现在(2.6.2)
    买家要做什么 手动把 utssdk/app-harmony/libs/<ABI>/*.so 同步到工程 harmony-configs/entry/libs/<ABI>/ 什么都不用做(仅需工程自带 EntryAbility)
    插件包鸿蒙部分 裸 .so 22MB 载体 har 9MB
    源码改动是否仍生效 生效 生效(源码流程编译源码,har 只提供原生库)
  • ⚠️ 普通授权版(加密包)的鸿蒙端不支持 —— 受 DCloud 官方限制:官方规则为 "发行平台为 web / 小程序 / 鸿蒙时,UTS 加密插件需云端编译,目前仅支持 uni-app x 项目,不支持 uni-app 项目"; HBuilderX 中该分支由 isX(UNI_APP_X === "true")守卫,uni-app(Vue2/Vue3) 工程不触发。 需要鸿蒙请选择源码授权版。

  • 升级提示:

    • 若你此前按旧文档把 .so 复制到了工程 harmony-configs/entry/libs/,可以删除(不再需要,也不影响构建)。
    • 鸿蒙端 API、数值与行为完全不变(OpenCV 4.9.0 内核未动;真机全序列与 2.6.1 基线一致)。
  • 引擎仍为 OpenCV 4.9.0,API 数量不变(77)。

2.6.1(2026-09-22)

新增:H5 / 微信小程序 纯 JS 入口(普通授权版五端可用性恢复)

DCloud 加密 UTS 插件的解密只发生在 App 云打包;uni-app(Vue2/Vue3) 工程的 H5 / 微信小程序 端在本地编译时无法解密加密 .uts(官方规则:加密插件 web/小程序/鸿蒙需云端编译且仅支持 uni-app x)。本版为两个平台提供随包明文 JS 入口,API 与 UTS 完全同名同参、返回值一致:

入口 平台 说明
js_sdk/index.js H5(浏览器) opencv-wasm 引擎 + web-helper I/O,77 API 同签名
js_sdk/mp-index.js 微信小程序 裁剪 wasm 引擎 + 画布桥;宿主需先 bindProcessingCanvas(canvas)(与 UTS 版要求一致)
  • 导入方式见 README「授权与交付」的条件编译示例;App 端仍走 UTS 入口(云打包),导入路径不变。
  • js_sdk 明文入口的 API 签名由 utssdk/web/index.uts 真源机械生成(生成脚本 + 签名护栏 + 双引擎运行时等价验证,同一输入两引擎输出逐字节一致),后续版本随 UTS 同步再生成。
  • 对既有源码授权版用户:无任何行为变化,无需迁移。
  • 引擎仍为 OpenCV 4.9.0,API 数量不变(77)。
查看更多

平台兼容性

uni-app(3.8.4)

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

uni-app x(4.0)

Chrome Safari Android iOS 鸿蒙 微信小程序 微信小程序插件版本
√ √ 5.0 12 12 2.14.0 2.3.0

其他

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

OpenCV 图像识别 - uni-app 跨端图像处理插件

基于 OpenCV 4.9.0 的 uni-app UTS 插件,句柄式图像处理管线。一套 API 覆盖 App-Android / App-iOS / 鸿蒙 / H5 / 微信小程序,同一输入各端结果一致;全部运算在设备本地完成,不上传任何数据。

支持 uni-app(Vue2 / Vue3)与 uni-app x 工程。

uni-app x 实测情况(同一插件包直接用于 x 工程,无需改动):

x 平台 状态 说明
web ✅ 已实测 wasm 引擎,version 显示 4.9.0 (opencv-wasm)
微信小程序 ✅ 已实测(DevTools + 真机) wasm 引擎,4.9.0 (opencv-wasm-mp);需在页面 onReady 里 bindProcessingCanvas(节点)
鸿蒙 ✅ 已实测 原生实现,4.9.0 (opencv-ohos);载体 har 交付,零配置
App-iOS ✅ 已实测(模拟器 x86_64 + 真机 arm64) 原生实现,4.9.0(Swift + 预编译 ObjC++ 桥接);需用 x 的自定义基座。实测:照片链路与示例图链路(轮廓 4967/23、模板 0.519@[582,2171] / 0.873@[55,75]、直线 2147(x86_64 模拟器)/ 2151(真机 arm64)、示例图直线 412、圆 30@(973,1470)r=198 等)逐项命中基线;「内置示例图」在 App 端可用
App-Android ✅ 已实测(x86_64 模拟器 + 真机 arm64) 原生实现,4.9.0(Kotlin + opencv-4.9.0.aar);需用 x 的自定义调试基座。实测:照片链路(轮廓 4967、模板 0.519@[582,2171]、直线 2151、圆 30@(973,1470)r=198、OTSU 155·78)与示例图链路(轮廓 23、模板 0.873@[55,75]、ORB 297·295、直线 412、凸包 119301)逐项命中基线;「内置示例图」在 App 端可用。注意:该端调用可选参数必须显式传全(见下方 x 注意事项 ⑤)

x 工程注意: ① 页面用 .uvue。算法实现按端分流:H5 / 微信小程序走 js_sdk/**(明文 JS),App 三端与鸿蒙走 utssdk/app-* 原生实现(js_sdk 并非「仅 uni-app 可用」,x 的 H5/mp 同样依赖它); ② x 的 App 端长内容需放进 <scroll-view>;③ 小程序端取画布节点要传 res[0].node; ④ App 端「内置示例图」:页面用 uni.getFileSystemManager() 把包内 static/sample/*.png 复制到 uni.env.USER_DATA_PATH(unifile://usr/),插件的 iOS / Android 侧用 UTSiOS.convert2AbsFullPath / UTSAndroid.convert2AbsFullPath 转真实路径后加载(该路径兼容自 2.6.3 起;UTSiOS.convert2AbsFullPath 要求 HBuilderX ≥ 4.11,本插件整体要求 ≥ 4.61,已覆盖); ⑤ App-Android(uni-app x / Kotlin 后端)必须显式传全可选参数:UTS 编译到 Kotlin 时不生成默认值, warpAffine(id, m)、findContours(id)、distanceTransform(id)、boxFilter(id) 这类省略可选参数的写法会报 No value passed for parameter 'xxx'。按各端实现里 ?? 的默认值显式传即可(如 findContours(id, 'external', 'simple')、warpAffine(id, m, 0, 0)),数值与省略时完全一致。 iOS/Swift、web、小程序、鸿蒙四个后端不受影响(可选参数正常)。 ⑥ 用插件市场加密包时,x 的 web 端会打印一条 warning: File '…/uni_modules/axen-opencv-image/utssdk/web/index.uts' is not a module —— 这是加密后该文件变 二进制、编译器按模块解析失败所致;H5 的实际代码走 js_sdk/**,功能与数值不受影响,可忽略。

✨ 特性

  • 🖼️ 基础处理:灰度、HSV 转换、二值化、高斯模糊、缩放、Canny 边缘
  • ✏️ 绘图标注:矩形 / 圆形 / 直线 / 中文与英文文字标注(putText)
  • 🔬 卷积滤波:自定义卷积核 filter2D / Sobel / Scharr / Laplacian 边缘检测(1.2.0)
  • 🎯 自动阈值:OTSU / 三角法自动计算最优阈值(返回阈值与新句柄,1.2.0)
  • 📐 霍夫变换:直线检测(HoughLinesP)/ 圆检测(HoughCircles),返回检出元素 JSON(1.2.0)
  • 🔷 轮廓与形状识别:面积、外接矩形、顶点数、形状分类(circle/rectangle/triangle/quad/other)
  • 📐 轮廓进阶:凸包、多边形逼近、最小外接圆、旋转矩形、轮廓层级树(1.3.0 / 2.2.0)
  • 🔀 几何变换:仿射 / 透视变换、图像金字塔上/下采样(1.3.0)
  • 🌈 颜色空间扩展:LAB / XYZ / YCrCb 转换、灰度转彩、通道拆分 / 合成(2.0.0)
  • ⚡ 增强与像素运算:CLAHE、加权融合、convertScaleAbs、位运算(与/或/异或/非)、boxFilter、距离变换(2.0.0)
  • 📊 直方图与连通域:直方图、反投影、相似度比较、连通域统计(2.1.0)
  • 🔍 模板匹配:TM_CCOEFF_NORMED + NMS,返回 Top N 位置与分数
  • 🧩 特征点匹配:ORB 提取 + BFMatcher(HAMMING) + 0.75 比率测试
  • 🎨 伪彩与角点:applyColorMap(22 种色表)、cornerHarris、Shi-Tomasi 角点(2.4.0)
  • 📱 二维码:生成 / 检测 / 解码 / 一步检测解码,五端可用(2.5.0)
  • 🔄 几何增强与句柄管理:任意角度旋转 rotate、ROI 裁剪 getRoi、图像尺寸 imageSize、多尺度模板匹配 matchTemplateMultiScale、批量释放 releaseAll(2.6.0)
  • 🏗️ 句柄模型:loadImage 返回句柄,链式处理不拷贝原图,用完必须 releaseImage
  • 🔒 本地计算:所有图像处理均在设备本地完成,不上传任何数据

引擎(Android / iOS / 鸿蒙为原生 OpenCV 4.9.0,H5 与微信小程序为 WebAssembly)随插件内置,导入即可用,无需自行编译或额外下载。

📦 安装

插件市场搜索「OpenCV 图像识别」,或直接把 uni_modules/axen-opencv-image 导入项目。安装后无需 npm install、无需 CocoaPods。

环境要求:HBuilderX ≥ 4.61;Android API ≥ 21;iOS ≥ 12;微信小程序基础库 ≥ 2.14.0;鸿蒙 HarmonyOS NEXT。

🧾 授权与交付

授权 适用 交付内容
普通授权版 自有商业项目(绑定 appid + 包名) 可直接编译、运行、发布;不授予源码,无法二次开发或修改内部实现
源码授权版 需要二次开发 / 定制 / 深入排障 在普通授权基础上额外提供插件源码
  • 普通授权版平台路由(DCloud 加密插件机制):加密插件的解密编译只发生在 App 云打包 (云端传统打包,不支持安心打包 / 离线打包)。App(Android/iOS)端照常从 UTS 插件入口导入; H5 / 微信小程序端因本地无法解密加密 .uts,请改从随包附带的明文 JS 入口导入 (API 与 UTS 完全同名同参、返回值一致,见下方条件编译写法)。 ⚠️ 鸿蒙端:仅源码授权版支持;普通授权版(加密包)不支持 —— 受 DCloud 官方限制。 官方规则明确:若发行平台为 web、小程序或鸿蒙,UTS 加密插件需提交云端编译,目前仅支持 uni-app x 项目, 不支持 uni-app 项目;HBuilderX 实现上该云编译分支由 isX(UNI_APP_X === "true")守卫, uni-app(vue2/vue3) 工程不会触发,因此加密包在鸿蒙端没有可用的编译路径(与插件实现无关)。 需要鸿蒙请选择源码授权版,详见「鸿蒙」章节。

普通授权版五端导入写法(条件编译):

// App(Android/iOS,云打包由 DCloud 云端解密,UTS 入口)
// #ifdef APP-PLUS || APP-HARMONY
import { initEngine, loadImage, cvtGray, findContours, releaseImage } from '@/uni_modules/axen-opencv-image'
// #endif

// H5(浏览器,明文 JS 入口)
// #ifdef H5
import { initEngine, loadImage, cvtGray, releaseImage } from '@/uni_modules/axen-opencv-image/js_sdk/index.js'
// #endif

// 微信小程序(明文 JS 入口;onReady 后需先 bindProcessingCanvas(canvas),与 UTS 版要求一致)
// #ifdef MP-WEIXIN
import { initEngine, loadImage, bindProcessingCanvas, cvtGray } from '@/uni_modules/axen-opencv-image/js_sdk/mp-index.js'
// #endif
  • 源码授权版:全端直接使用 UTS 入口,无需上述分流;JS 入口签名与 UTS 完全一致。
  • ⚠️ 鸿蒙平台标识是 APP-HARMONY(不是 APP-PLUS):条件编译漏写它会导致鸿蒙下所有分支 都不匹配、插件 API 全部 undefined(表现为能选图但页面无任何反应、控制台无插件日志)。
  • ✅ 鸿蒙端(源码授权版):零配置。插件包内 utssdk/app-harmony/libs/opencv-image-libs.har 是只含两个 ABI .so 的载体 har,插件用 utssdk/app-harmony/config.json 自动声明该依赖 —— HBuilderX 生成鸿蒙工程时会把它写进模块的 oh-package.json5,ohpm 再解包其中的 .so 合并进应用。 你只需要:① 工程提供 EntryAbility;② 条件编译写 APP-PLUS || APP-HARMONY,不用拷任何 har、不用改依赖。
    • 为什么载体 har 要单独起名:ohpm 规定"包不能依赖与自己同名的包"(00618004 Same As The PkgName), 而插件模块名就是 @uni_modules/axen-opencv-image,所以载体 har 的内部包名为 @axen/opencv-image-libs。
    • ⚠️ 普通授权版(加密包)的鸿蒙端不支持 —— 受 DCloud 官方限制(加密插件的鸿蒙端需云端编译,官方仅支持 uni-app x 项目);鸿蒙仅源码授权版可用。
  • ⚠️ App 端必须用「自定义调试基座」或云打包运行(普通授权版,已实测):本插件是第三方 UTS 插件, 标准基座不含它,且加密 .uts 无法在本地解密,因此用标准基座运行必然"点按钮没反应"、 控制台没有任何 [opencv-demo] 日志——这不是插件故障,是加密机制决定的。正确方式:
    • 调试:HBuilderX → 运行 → 制作自定义调试基座(基座由云端构建、会解密插件)→ 运行到手机
    • 发布:云打包(传统打包)出 APK/IPA
    • 两条路径已在 Android 真机实测通过(2026-09-20,全序列命中 Android 原生族基线)
  • ⚠️ 选图功能需勾选 App 模块(与插件无关的通用配置):若你的页面用 uni.chooseImage 选图, 必须在 manifest.json → App 模块配置 勾选 Camera(相机) 与 Gallery(相册): 自定义基座与云打包都按"已勾选模块"裁剪构建(标准基座才内置全部模块),未勾选时 iOS 端会提示 "打包时未添加 Gallery/Camera 模块"。改完模块必须重新制作自定义基座,旧基座不会自动生效。 iOS 模拟器无摄像头硬件,调试时建议 sourceType: ['album'](或直接用工程自带的示例图片按钮)。 iOS 还需在 manifest 填写 NSCameraUsageDescription / NSPhotoLibraryUsageDescription 隐私描述。
  • 两种授权均绑定唯一的 appid 与包名;更换其中任一项需重新购买授权。
  • 试用:可在自定义调试基座中评估全部功能;试用版本不能用于正式发布。
  • 版本变更记录见插件包内 changelog.md。
  • 企业定制、私有化部署或超出上述范围的使用,请通过插件市场联系方式沟通。

⚠️ App 云打包的项目体积门槛(60MB 免费额度,必读)

DCloud 云打包按【项目体积】计费(不是 APK/IPA 体积),免费额度 60MB。本插件的原生 OpenCV 产物较大 (iOS fat 静态库 48MB / Android aar 20MB / 鸿蒙载体 har 9MB / 明文 H5 引擎 5MB), 各端产物全留 ≈ 84MB,必然超限。而云打包一次只打一个平台 —— 其余平台的产物纯属白占额度。

打包前按目标平台裁一刀即可(Android 单端 ≈27MB;iOS 单端需先裁切片,见下方提示):

cd uni_modules/axen-opencv-image/utssdk

# 只打 Android:移出 iOS 与鸿蒙产物(可先备份到工程外)
mv app-ios app-harmony ../            # 打包完成后移回

# 只打 iOS:移出 Android 与鸿蒙产物
# mv app-android app-harmony ../

# 只打鸿蒙:无需裁(走本地构建,不涉及云打包额度)
  • iOS 额外提示:内置 fat 库 = arm64(真机)+ x86_64(Intel Mac 模拟器),未裁前 48MB → iOS 单端 ≈53MB,贴着 60MB 上限;若只做真机发布,裁掉 x86_64 切片可降到 约 22MB (该副本不能再跑 x86_64 模拟器;Apple Silicon 上的 arm64 模拟器本就不含此切片):
    cd uni_modules/axen-opencv-image/utssdk/app-ios/Libs/OpenCVBridge
    lipo -thin arm64 -output libOpenCVBridge.a libOpenCVBridge.a
  • 上述裁剪只影响体积:被移出的平台产物不参与目标平台的编译,功能与数值完全不变。
  • 若不想裁剪、且项目体积确实需要超过 60MB,只能在 DCloud 侧充值"App 大小超限"额度。

🚀 快速开始

import {
  initEngine, loadImage, releaseImage,
  cvtGray, threshold, cvtHsv, gaussianBlur, resize, canny,
  detectColorRange, findContours, matchTemplate, orbMatch,
  drawRect, drawCircle, drawLine, putText,
  filter2D, sobel, scharr, laplacian,
  thresholdOtsu, thresholdTriangle, houghLinesP, houghCircles,
  convexHull, approxPolyDP, minEnclosingCircle, minAreaRect,
  getAffineTransform, warpAffine, getPerspectiveTransform, warpPerspective, pyrUp, pyrDown,
  cvtLab, cvtXyz, cvtYCrCb, grayToBgr, splitChannels, mergeChannels,
  clahe, addWeighted, convertScaleAbs, bitwiseAnd, bitwiseOr, bitwiseXor, bitwiseNot,
  boxFilter, distanceTransform,
  qrEncode, qrDetect, qrDecode, qrDetectAndDecode,
  toBase64
} from '@/uni_modules/axen-opencv-image'

// 1. 初始化(首帧前调用一次;H5/小程序端会等待 wasm 编译完成)
await initEngine()

// 2. 加载图片,得到句柄
const img = await loadImage('/storage/emulated/0/xxx.png')   // App: 本地文件绝对路径
// App 端会自动兼容 `unifile://...`(如 uni.env.USER_DATA_PATH)与包内资源路径(`/static/...`、`static/...`、`_www/...`)
// const img = await loadImage('https://xxx/1.png')          // H5: URL / blob / data URL
// const img = await loadImage(wxTempPath)                   // 微信小程序: wx.chooseImage 临时路径,或 '/static/sample/xxx.png' 包内路径

// 3. 基础处理:灰度 -> 二值化
const gray = cvtGray(img)
const binary = threshold(gray, 127, 255)

// 4. 颜色检测(输入 HSV 图,范围为 OpenCV 约定 H:0-180, S:0-255, V:0-255)
const hsv = cvtHsv(img)
const red = detectColorRange(hsv, 0, 100, 100, 10, 255, 255)

// 5. 轮廓/形状识别(输入二值图)
const contours = JSON.parse(findContours(binary))   // [{ area, x, y, width, height, shape, points }]

// 6. 模板匹配(templateId 为模板图句柄,需先 loadImage 模板图)
const templateId = await loadImage('/path/to/template.png')
const matches = JSON.parse(matchTemplate(img, templateId, 3))   // [{ x, y, width, height, score }]

// 7. 特征点匹配(imgB 为另一张图的句柄)
const imgB = await loadImage('/path/to/another.png')
const orb = orbMatch(img, imgB)   // { keypoints1, keypoints2, matches, goodMatches }

// 8. 绘制结果并导出 base64 展示
drawRect(img, matches[0].x, matches[0].y, matches[0].width, matches[0].height, '#00ff00', 3)
const b64 = await toBase64(img)

// 9. 释放句柄(所有中间结果都要释放)
releaseImage(img); releaseImage(gray); releaseImage(binary); releaseImage(hsv); releaseImage(templateId); releaseImage(imgB)

⚠️ 句柄模型:每个处理函数返回新句柄,原句柄不受影响;用完必须 releaseImage 释放,否则内存持续增长(H5 / 小程序端是 WASM 线性内存,泄漏最终会导致可分配内存耗尽)。批量处理循环里请逐个释放。

📖 API 文档

函数 返回 说明
initEngine() Promise<OcvInitResult> 初始化,返回 OpenCV 版本
loadImage(source) Promise<number> 加载图片返回句柄;失败返回 -1
releaseImage(id) void 释放句柄
resize(id, w, h) number 缩放(w/h 须为正数,否则返回 -1)
cvtGray(id) / cvtHsv(id) number 通道转换
threshold(id, thresh, maxval) number 二值化(THRESH_BINARY);非灰度输入自动转灰度
gaussianBlur(id, ksize) number 高斯模糊(ksize 自动取奇数)
canny(id, low, high) number Canny 边缘;非灰度输入自动转灰度
detectColorRange(id, hMin, sMin, vMin, hMax, sMax, vMax) OcvColorRangeResult HSV 范围检测(H:0-180, S/V:0-255)
findContours(id, retrMode?, approxMode?) string 轮廓与形状(JSON 字符串,JSON.parse 后为 OcvContour[]);retrMode: external/list/ccomp/tree(默认 external)、approxMode: simple/none(默认 simple);1.3.0 起每项含 perimeter(周长)。注意:完整点集体积过大(数千轮廓会使 JSON 达数十 MB),请使用 convexHull / approxPolyDP 获取点集
matchTemplate(id, templateId, topN) string 模板匹配 TopN(JSON 字符串,OcvMatch[])
orbMatch(id1, id2) OcvFeatureMatchResult ORB 特征匹配
drawRect(id, x, y, w, h, color, thickness) number 在原句柄上画框(颜色 #rrggbb)
drawCircle(id, cx, cy, radius, color, thickness) number 在原句柄上画圆(thickness>0 空心,≤0 实心)
drawLine(id, x1, y1, x2, y2, color, thickness) number 在原句柄上画直线
putText(id, text, x, y, scale, color, thickness) number 文字标注(FONT_HERSHEY_SIMPLEX,支持中文/英文,scale>0)
toBase64(id) Promise<string> PNG base64(无 data: 前缀)
morphErode(id, kernelSize) / morphDilate(id, shapeSize) number 腐蚀 / 膨胀
morphologyEx(id, morphType, ksize) number 形态学:open / close / gradient / tophat / blackhat
adaptiveThreshold(id, method, blockSize, c) number 自适应二值化(mean / gaussian)
medianBlur(id, ksize) number 中值滤波
bilateralFilter(id, d, sigmaColor, sigmaSpace) number 双边滤波(保边平滑;RGBA 输入自动转 RGB 处理)
equalizeHist(id) number 直方图均衡化
flipRotate(id, mode) number flipH / flipV / rotate90 / rotate180 / rotate270
filter2D(id, kernel, delta) number 自定义卷积(kernel 为 3×3 数组,9 个数按行优先;多通道自动逐通道处理)
sobel(id, dx, dy, ksize) number Sobel 边缘(dx/dy 分别为 x/y 方向阶数,如 sobel(id, 1, 0, 3);非灰度输入自动转灰度)
scharr(id, dx, dy) number Scharr 边缘(比 Sobel 更精确,固定 3×3)
laplacian(id, ksize) number Laplacian 边缘(ksize 自动取奇数)
thresholdOtsu(id, maxval) OcvAutoThresholdResult OTSU 自动阈值,返回 { id: 新二值图句柄, thresh: 最优阈值 }
thresholdTriangle(id, maxval) OcvAutoThresholdResult 三角法自动阈值,返回 { id, thresh }
houghLinesP(id, rho, thetaDeg, threshold, minLineLength, maxLineGap) string 霍夫直线检测(JSON OcvHoughLine[],JSON.parse 后为 [{ x1, y1, x2, y2 }];非灰度自动转灰;参数 ≤0 时取默认 1/1°/80/30/10)
houghCircles(id, dp, minDist, param1, param2, minRadius, maxRadius) string 霍夫圆检测(JSON OcvHoughCircle[],[{ x, y, radius }];参数 ≤0 时取默认 1/高/8/100/30/0/0)。鸿蒙端对最长边 >2880 的超大图自动降采样检测并坐标还原(minDist/min/maxRadius 按比例换算保持原图像素语义)
convexHull(id, contourIndex) string 凸包(JSON OcvConvexHullResult,{ points: 扁平点集, area: 凸包面积 });轮廓越界返回 {"points":[],"area":0}(1.3.0)
approxPolyDP(id, contourIndex, epsilonRatio?) string 多边形逼近(JSON OcvApproxPolyResult,{ points: 扁平点集 });epsilon = epsilonRatio × 周长,默认 0.02;轮廓越界返回 {"points":[]}(1.3.0)
minEnclosingCircle(id, contourIndex) string 最小外接圆(JSON OcvMinEnclosingCircleResult,{ x, y, radius });轮廓越界返回全 0(1.3.0)
minAreaRect(id, contourIndex) string 旋转矩形(JSON OcvMinAreaRectResult,{ x, y, width, height, angle },angle 为 -90~0);轮廓越界返回全 0(1.3.0)
getAffineTransform(srcTri, dstTri) string 仿射矩阵(JSON 数组 6 数);点数 ≠6 返回 "[]"(1.3.0)
warpAffine(id, matrix, outW?, outH?) number 仿射变换新句柄(INTER_LINEAR + BORDER_CONSTANT);矩阵 ≠6 个数或尺寸非法返回 -1;outW/outH 默认原图尺寸(1.3.0)
getPerspectiveTransform(srcQuad, dstQuad) string 透视矩阵(JSON 数组 9 数);点数 ≠8 返回 "[]"(1.3.0)
warpPerspective(id, matrix, outW?, outH?) number 透视变换新句柄;矩阵 ≠9 个数或尺寸非法返回 -1;outW/outH 默认原图尺寸(1.3.0)
pyrUp(id) / pyrDown(id) number 图像金字塔上采样 2× / 下采样 ½(1.3.0)
cvtLab(id) / cvtXyz(id) / cvtYCrCb(id) number 颜色空间转换(BGR→LAB/XYZ/YCrCb,输出 3ch 数值通道图;非 3/4ch 输入返回 -1)(2.0.0)
grayToBgr(id) number 灰度(1ch)扩为 3 通道(显示为灰度外观,可叠加彩色标注;非 1ch 输入返回 -1)(2.0.0)
splitChannels(id) OcvSplitChannelsResult 按内存物理序拆前 3 通道为三个单通道句柄 { c1, c2, c3 }(4ch→R,G,B;3ch→序内三通道;1ch 返回全 -1;对 LAB/HSV 等转换产物拆分即得 L,a,b / H,S,V)(2.0.0)
mergeChannels(c1, c2, c3) number 三个单通道句柄按序合成 3 通道新句柄(与 splitChannels 同序;任一无效/非单通道/尺寸不一致返回 -1)(2.0.0)
clahe(id, clipLimit?, tileSize?) number CLAHE 自适应直方图均衡(非灰度自动转灰;默认 clipLimit=2.0、tileSize=8)(2.0.0)
addWeighted(id1, alpha, id2, beta, gamma?) number 加权融合 dst=α·a+β·b+γ(两图尺寸/通道不一致返回 -1;默认 γ=0)(2.0.0)
convertScaleAbs(id, alpha?, beta?) number dst=│α·src+β│ 转 8U(默认 α=1 β=0)(2.0.0)
bitwiseAnd(id1, id2) / bitwiseOr(id1, id2) / bitwiseXor(id1, id2) number 双图位运算(尺寸/通道不一致返回 -1)(2.0.0)
bitwiseNot(id) number 单图按位取反(2.0.0)
boxFilter(id, ksize?, normalize?) number 均值模糊(ksize 自动取奇数,默认 3;normalize 传 1/0,默认 1=归一化)(2.0.0)
distanceTransform(id, thresholdValue?) number 距离变换(DIST_L2+mask3,归一化 0-255 转 8U 返回,非灰度自动转灰;thresholdValue>0 时先截断再归一化,默认用实际最大距离)(2.0.0)
calcHist(id, bins?) OcvHistResult 灰度直方图 { id, bins }:1×N 8U 归一化句柄(可 toBase64)+ 各 bin 计数数组(归一化 0-255);非灰度自动转灰;bins 默认 256(2.1.0)
calcBackProject(id, histId) OcvBackProjectResult 直方图反投影 { id }(单通道灰度级模型,目标图灰度→模型直方图强度,8U 返回;hist 尺寸<2 返回 id=-1)(2.1.0)
compareHist(h1, h2, method?) OcvCompareResult 直方图相似度 { value }:correlation(默认)/ chisqr / intersection / bhattacharyya;长度不符返回 value=-1(2.1.0)
connectedComponentsWithStats(id) OcvConnectedComponentsResult 连通域统计 { count, labelId, components }:components 按面积降序(跳过背景),labelId 为 labels 归一化 8U 可视化句柄;非灰度自动转灰(2.1.0)
connectedComponents(id) OcvConnectedComponentsResult 连通域数(内部同 WithStats,统一返回完整结构)(2.1.0)
findContoursHierarchy(id, retrMode?, approxMode?) OcvHierarchyResult 轮廓层级树:{ contours, hierarchy, maxDepth }(hierarchy 含 parent/child/next/prev/depth,-1 无;retrMode 默认 tree,也支持 external/list/ccomp;区分容器轮廓与孔洞、按深度分层)(2.2.0)
applyColorMap(id, colormap) number 伪彩映射(colormap: autumn/bone/jet/winter/rainbow/ocean/summer/spring/cool/hsv/pink/hot/parula/magma/inferno/plasma/viridis/cividis/twilight/twilight_shifted/turbo/deepgreen,共 22 种);非灰度自动转灰,输出 3 通道彩色句柄需 releaseImage(2.4.0)
cornerHarris(id, blockSize?, ksize?, k?) number Harris 角点响应图(归一化 0-255 转 8U 单通道,可 toBase64 展示;默认 blockSize=2、ksize=3、k=0.04,非灰度自动转灰,需 releaseImage)(2.4.0)
goodFeaturesToTrack(id, maxCorners, qualityLevel?, minDistance?) OcvGoodFeaturesResult Shi-Tomasi 角点检测:返回 { corners: [{x,y}], count }(默认 qualityLevel=0.01、minDistance=10)(2.4.0)
qrEncode(text) number 生成二维码:文本 → 8UC1 二值 Mat 句柄(需 releaseImage;全端支持)(2.5.0)
qrDetect(id) OcvQrDetectResult 检测二维码:{ ok, points: [{x,y}×4] } 四角点(2.5.0)
qrDecode(id) OcvQrDecodeResult 解码二维码:{ ok, text }(需二维码模块 ≥10px;尺寸过小时建议先 resize 放大)(2.5.0)
qrDetectAndDecode(id) OcvQrDecodeResult 一步检测+解码:{ ok, points, text }(2.5.0)
imageSize(id) OcvImageSizeResult 图像尺寸 { width, height };句柄无效 width=-1(2.6.0)
getRoi(id, x, y, w, h) number ROI 裁剪:平移仿射实现,像素精确;越界/非法尺寸返回 -1,需 releaseImage(2.6.0)
rotate(id, angleDeg, scale?) number 旋转:angleDeg 正值=逆时针(度),与 flipRotate 方向一致;90 倍数且 scale=1 像素精确并互换尺寸,其它角度同尺寸仿射(角落黑边);scale 缩放内容(2.6.0)
matchTemplateMultiScale(id, templateId, topN?, scales?) string 多尺度模板匹配:模板按各尺度缩放后与原尺寸源图匹配,跨尺度 NMS 去重;JSON [{ x, y, width, height, score, scale }](score 降序;scale>1 表示实例比模板大;默认 scales [0.6,0.8,1.0,1.5],每尺度一次全图匹配,大图建议先降采样)(2.6.0)
releaseAll() number 释放池内全部句柄,返回释放数量(2.6.0;App 三端随 2.6.0 基座产物提供)

返回类型定义见 utssdk/interface.uts。

返回值为 JSON 字符串的接口(findContours / matchTemplate / matchTemplateMultiScale / houghLinesP / houghCircles / convexHull / approxPolyDP / minEnclosingCircle / minAreaRect / getAffineTransform / getPerspectiveTransform)各端统一返回字符串,请 JSON.parse 后使用;其余接口返回对象或数字句柄。

🌐 平台支持

平台 引擎 包体影响 支持度 前提
App-Android 原生 OpenCV 4.9.0 内置 aar 约 20MB(打包时按 ABI 拆分) 全部能力 API ≥ 21;需自定义调试基座
App-iOS 原生 OpenCV 4.9.0 内置静态库约 50MB(链接时按引用裁剪) 全部能力 iOS ≥ 12;无需 CocoaPods
鸿蒙 原生 OpenCV 4.9.0 载体 har(仅含双 ABI 的 .so,由插件 config.json 自动声明)约 9MB 全部能力 · 仅源码授权版(普通授权版受 DCloud 官方限制不支持) HarmonyOS NEXT;零配置,仅需 EntryAbility(见下)
H5 (web) opencv-wasm 4.9.0 发行包增加约 5MB 全部能力 现代浏览器 + HBuilderX 内置浏览器
微信小程序 裁剪 WASM 增量约 0.75MB 全部能力 基础库 ≥ 2.14.0
抖音 / 支付宝等其它小程序 未支持 - - 需按各平台 wasm 通道适配

各端结果一致:同一张图在五端的阈值、轮廓数、霍夫检出、模板分数等指标逐项相同。仅 wasm 端与原生端在少数浮点敏感指标上存在末位差异(如霍夫直线 2147 vs 2151、模板分数 0.492 vs 0.519),源于向量化内核的浮点归约顺序,不影响阈值判定与业务结论。

uni-app x · iOS 实测(照片 1440x2560):轮廓 4967、层级树 15·顶1·深1、ORB 500·500、 直线 2147、圆 30 @(973,1470) r=198(约 0.5s)、连通域 1(a=3686377)、QR [449,28] 解码成功、 凸包/逼近/外接圆(r=1468)/旋转矩形(2559x1439 90°)、OTSU 155.0、三角法 78.0 —— 与 wasm 族基线逐项一致 (该端为原生 OpenCV,因此直线取 2147 而非 arm64 族的 2151、模板分数取 0.519 而非 wasm 的 0.492)。

内置示例图(400x300)同端实测:轮廓 23、模板 0.873@[55,75]、ORB 297·295、连通域 120000、 OTSU 150.0、三角法 253.0、直线 412、圆 0、凸包 119301、外接圆 r=249、旋转矩形 299x399。 App 端「内置示例图」可用(页面物化到 uni.env.USER_DATA_PATH + 插件侧路径转换,见下方 x 注意事项 ④)。

⚠️ 各端使用注意

微信小程序

  • 必须绑定画布:页面 onReady 后调用 bindProcessingCanvas(canvas)(<canvas type="2d">),读图/写图走该画布;未绑定时 loadImage 会失败。
  • 基础库 ≥ 2.14.0 时由 WXWebAssembly 原生解压加载 wasm;更早的基础库走字节回退加载,速度较慢。
  • 引擎随插件自包含(uni_modules/axen-opencv-image/static/),宿主无需额外放置 wasm 文件。
  • 请用发行模式打包:运行模式含 sourcemap 会显著增大包体,容易超过预览/上传限制。
  • 首次初始化耗时约几百毫秒(wasm 编译),建议在首页启动时 initEngine() 一次,复用后续调用。

Android

  • 需自定义调试基座:HBuilderX → 运行 → 运行到手机或模拟器 → 制作自定义调试基座。
  • 图片格式支持 JPEG / PNG / WEBP / TIFF / EXR / JPEG2000;读取相册或拍照由宿主调用 uni.chooseImage(插件不新增权限)。
  • 宿主注意(相册 / 相机):App 端 uni.chooseImage 依赖原生 Camera&Gallery 模块 (HBuilderX 3.6.11+ 为可选模块)。两点都要满足:① manifest.json 的「App 模块配置」勾选 Camera&Gallery (模块标识 Camera);② 调试基座/安装包里确实链接了该模块——缺任一项,运行时会提示 「打包时未添加 Camera 模块」。H5 与小程序端不需要该配置(H5 走浏览器文件选择器)。
  • 64 位产物已按 16KB 页对齐,满足 Google Play 上架要求。

iOS

  • 引擎已内置,无需 CocoaPods、无需额外配置;内置桥接库含 arm64(真机)与 x86_64(模拟器) 两种切片,支持 iOS 12 及以上。
  • 已在 iPhone 真机与模拟器完成全量功能验证(2.6.0 真机基座 71 次霍夫圆连打零漂移零崩溃);若你的环境需要其它切片组合(例如 Apple 芯片 Mac 上的 arm64 模拟器),可通过插件市场联系方式获取支持。

鸿蒙

源码授权版:零配置。 插件包内只有一个载体 har(只含 .so),由插件 config.json 自动声明依赖:

utssdk/app-harmony/
├── config.json                          {"dependencies":{"@axen/opencv-image-libs":"./libs/opencv-image-libs.har"}}
└── libs/opencv-image-libs.har      9.02MB,内含 arm64-v8a / x86_64 两套
                                          libopencv_bridge.so + libc++_shared.so

HBuilderX 生成鸿蒙工程时会:

  1. 把该 har 连同插件文件一起拷进模块目录(sync('**/*.{ets,js,har,tgz}'));
  2. 依据 config.json 生成模块的 oh-package.json5(parsePackageDeps 按 utssdk/app-harmony/ 解析相对路径);
  3. ohpm install 把 har 内的 libs/** 解包到 oh_modules 并合并进应用。

所以你不需要在工程里放任何 har、也不需要改依赖,只要让应用使用自己的 EntryAbility (参考演示工程 harmony-configs/entry/src/main/ets/entryability/),并把条件编译写成 APP-PLUS || APP-HARMONY。

⚠️ 普通授权版(加密包)不支持鸿蒙 —— 受 DCloud 官方限制:官方规则为 "发行平台为 web / 小程序 / 鸿蒙时,UTS 加密插件需云端编译,目前仅支持 uni-app x 项目,不支持 uni-app 项目"; HBuilderX 中该云编译分支由 isX(UNI_APP_X === "true")守卫,uni-app(vue2/vue3) 工程不触发, 因此加密包在鸿蒙端无可用编译路径。两种表现: ① 若工程在 APP-HARMONY 下 import 了本插件 → 鸿蒙构建在 ohpm 阶段失败 (.../utssdk/app-harmony/module.har does not exist); ② 若按建议做条件编译(鸿蒙端不 import,仅在 APP-PLUS/APP-HARMONY 之外引入 UTS 入口)→ 构建与运行正常,插件能力不可用,页面可自行给出提示 (演示工程即此做法,实测:构建成功、启动后提示"鸿蒙端不支持…仅源码授权版可用")。 鸿蒙请使用源码授权版(本文档上一节即为其零配置接入方式)。

❓ 常见问题

Q:图片加载返回 -1? 路径写法随平台不同:App 用本地文件绝对路径(如 /storage/emulated/0/xxx.png),H5 用 URL / blob / data URL,微信小程序用 wx.chooseImage 临时路径或包内 /static/... 路径;小程序端还需先 bindProcessingCanvas。

Q:内存一直涨 / 后面开始报错? 句柄未释放。每个函数都返回新句柄,包括 cvtGray、threshold、mask 这类中间结果,用完即 releaseImage;循环里尤其注意。

Q:模板匹配分数偏低? 分数受输入像素与算法实现影响,判阈值请按业务实测标定;同图在不同引擎(原生 / wasm)可能有约 0.03 的末位差异,命中位置一致。

Q:findContours 返回的 JSON 很大? 轮廓点集默认带全部点。数千条轮廓时请改用 convexHull / approxPolyDP 取精简点集,或用 findContoursHierarchy 只看层级与统计。

Q:小程序预览/上传提示超限? 切到发行模式重新编译;运行模式含 sourcemap,包体会明显变大。

Q:二维码解码失败? 被解图里二维码模块需 ≥ 10 像素;模块过小时先用 resize 放大再解码。qrDetect 可先确认能否检出四角点。

Q:H5 首屏变慢? 首次 initEngine() 需要编译约 5MB 的 wasm,属一次性成本;可放在启动页提前初始化并复用。

🗓️ 路线图

当前 77 个 API(15 基础 + 8 个 1.1.0 + 11 个 1.2.0 + 10 个 1.3.0 + 15 个 2.0.0 + 5 个 2.1.0 + 1 个 2.2.0 + 3 个 2.4.0 + 4 个 2.5.0 + 5 个 2.6.0),覆盖经典图像处理与特征匹配的常用子集。后续规划:

性能建议(大图霍夫直线)

houghLinesP 在 OpenCV 里没有并行实现,耗时由角度分辨率与阈值主导。1440×2560 这类大图上:

  • 把 thetaDeg 从 1 提到 2:约 7 倍提速,检出线条数基本不变(实测 2033 → 2110);
  • 把 threshold 从 80 提到 120:约 3 倍提速,线条数不变;
  • 先自行 resize 到长边 1440 再检测、并把坐标乘以 1/scale 还原:10 倍以上,但线条数会按比例减少。

houghCircles 已按在线核数并行(Android 实测 1440×2560 上 6000ms → 2200ms)。

下个版本(2.7.0)计划

  • 性能:32 位 ARM(armeabi-v7a)引擎优化与多线程放开 —— 低端 32 位真机上的耗时显著下降
  • 二维码增强:qrDetectMulti / qrDetectAndDecodeMulti(一图多码)
  • 几何与拼接:findHomography(含 RANSAC)配合特征匹配做透视校正 / 拼接
  • 特征点增强:SIFT / AKAZE 特征 + FLANN 匹配
  • 便捷能力:imencode / imdecode(处理完直接上传 / 落盘)
  • 体验:大图自动降采样开关(opt-in)

2.6.0 已交付:多尺度模板匹配 matchTemplateMultiScale、任意角度旋转 rotate、ROI 裁剪 getRoi、图像尺寸 imageSize、批量释放 releaseAll(共 5 个新 API,总数 77)。

中期

  • 人脸检测(Haar 级联或 YuNet ONNX)
  • DNN 推理模块(ONNX:分类 / 检测 / 分割,模型由宿主下发)

远期

  • 光流(稀疏 / 稠密)与背景建模(MOG2 / KNN)
  • 视频流处理管线(各端相机帧回调接入)
  • GPU 加速(OpenCL / Metal / 鸿蒙 NAPI 侧加速)

需求优先级欢迎通过插件市场联系方式反馈,将按热度排期。

🔐 隐私与安全

本插件所有图像处理均在设备本地完成,不主动采集 IDFA、定位、相机、麦克风、相册、通讯录信息,也不上传任何数据。处理图片由宿主业务方选择传入;读取相册/拍照需宿主自行调用 uni.chooseImage 申请用户授权,插件不新增权限。

📄 许可证

插件引擎基于 OpenCV(Apache License 2.0,含原始 OpenCV 与 opencv.js 组件),许可见 THIRD_PARTY_LICENSES.md;插件本体授权以插件市场页面/购买协议为准。

隐私、权限声明

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

插件不新增权限;读取图片由宿主应用通过 uni.chooseImage 授权完成。

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

本插件所有图像处理均在本地设备完成,不上传任何数据。

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

无