更新记录

2.4.0(2026-09-09)

图像增强 A 档扩展(imgproc,五端)

  • applyColorMap(id, colormap):伪彩映射(COLORMAP_AUTUMN/BONE/JET/WINTER/.../TURBO/DEEPGREEN 共 22 种, 参数用字符串名 'jet'/'turbo' 等;RGBA(4ch) 输入自动转灰度,输出 3ch 彩色句柄需 releaseImage)
  • cornerHarris(id, blockSize?, ksize?, k?):Harris 角点响应图(32F 响应归一化 0-255 转 8U 单通道 句柄返回,可 toBase64 展示;非灰度自动转灰,blockSize 可为偶数、ksize 自动奇数化,默认 blockSize=2、ksize=3、k=0.04)
  • goodFeaturesToTrack(id, maxCorners, qualityLevel?, minDistance?):Shi-Tomasi 角点检测, 返回 { corners: [{x,y}], count }(默认 qualityLevel=0.01、minDistance=10)
  • 均为 imgproc 模块现成能力,mp/H5 wasm 不新增模块依赖,App 三端薄桥直调原生

平台实现

  • mp-weixin:shim_full.cpp 新增 3 个 C ABI + opencv-facade.js/opencv-core.js 外观层 (wasm 2.37MB → 2.38MB,体积基本不变;白盒数值验证:40×40 亮块图检出 4 个角点坐标精确命中)
  • H5 / Android / iOS / 鸿蒙:与 mp 同签名(跨端数值一致),实现随各端薄桥
  • 类型:interface.uts 新增 ColorMapType / OcvCorner / OcvGoodFeaturesResult

二维码(QRCodeDetector)延后说明:原计划 2.4.0 纳入 QR 检测解码,但 OpenCV 4.8.0 旧版 QRCodeDetector(依赖第三方 QUIRC)解码存在上游通用缺陷——detect 正常但部分 二维码解码为空(opencv/opencv#23249 / #24318,维护者 asmorkalov 亲测复现, Android/桌面/wasm 一致,非插件移植问题)。官方已在 4.9.0+ 提供自研解码器 (PR #24299 "In-house QR codes decoding", 构建时关闭 QUIRC 即生效),故 QR 延后至随 OpenCV 升版(2.5.0)一并引入, 避免在 4.8.0 上交付带缺陷的解码能力。

修复(2.3.0 遗留:mp wasm 分发位置错误):2.3.0 将 wasm 放在插件 js_sdk/,但 uni 编译 小程序时只编译 js_sdk 内的 JS 模块,.wasm 二进制不会拷入产物(实测 dist 内无该文件), 运行时 WXWebAssembly.instantiate 与 fs 回退均报 not found。2.4.0 修正: wasm 唯一来源移至插件 uni_modules/axen-opencv-image/static/opencv_mp.wasm(随 uni 资产管线 打包进小程序包,插件自包含),loader 改为多候选路径探测(插件 static 源路径 → 合入根 /static/ → 旧 js_sdk 兜底),兼容不同 uni 版本的产物路径差异。

修复(2.2.0 遗留:findContoursHierarchy 原生三端层级错乱):OpenCV 的 hierarchy 为 1×N CV_32SC4(源码 create(1, total, CV_32SC4)),ptr<int> 线性化后每轮廓占 4 个 int; Android/iOS/鸿蒙桥接误用 conn = hierarchy.cols / n(=1),把 Vec4i 错读成滑动窗口, 导致 parent/child/next/prev 全错(mp/H5 的 JS 端 i*4 步长一直正确)。单轮廓图不暴露, 大图(15 轮廓嵌套)下 iOS 输出 顶层=5/深度=2 而 mp 正确输出 顶层=1/深度=1。修复: conn = (cols × channels) / n(对 CV_32SC4 与假想的 CV_32SC1-4N-cols 两种布局均稳健)。 mp 与 iOS 从错读值反推出的真实层级完全自洽,交叉验证成立。随修复同步重编预编译产物: iOS libOpenCVBridge.a(fat x86_64+arm64)、鸿蒙 libopencv_bridge.so(arm64-v8a + x86_64, strip 后 5.3M/8.6M)、Android opencv-4.8.0.aar(4 ABI,32.6M,含 A 档 3 个新 JNI 符号, nm 已验证)。

优化(mp:wasm brotli 压缩分发):微信小程序 WXWebAssembly.instantiate 自基础库 2.14.0 起原生支持 .wasm.br 后缀(brotli 自动解压,官方推荐方案)。本次将 mp wasm 从原始 .wasm (2.38MB)改为 brotli q11 压缩的 .wasm.br0.56MB,原始的 23.3%)作为唯一分发格式。 预览 4MB 限制下节省 1.83MB(wasm 从占预算 60% 降至 14%);正式上传 gzip 计费下亦从 0.72MB (gzip of raw)降至约 0.56MB(gzip of br)。loader 探针改为 .wasm.br 优先 → .wasm 兜底 (WXWebAssembly 通道),fs 回退仅探 .wasm(标准 WebAssembly 无法解压 brotli)。 Node 冒烟:.br 解压 → 字节注入 → 全函数(含 A 档)正常。

修复(鸿蒙:HoughCircles 运行间非确定):同一输入(同文件、同操作序列,霍夫直线两轮恒 2151 证明输入一致)下 HoughCircles 两轮输出 0/30 圆跳变;mp 端 wasm 为 USE_PTHREADS=0 单线程, 同输入恒定 30。OpenCV 4.8 的 HoughCircles 三个阶段均为 parallel_for_ 分条并行,鸿蒙端 setNumThreads(2) 下的分条行为在运行间不稳定。修复:鸿蒙 HoughCircles 固定单线程执行 (RAII guard,异常安全,结束恢复原线程数),对齐 mp 的确定性路径。耗时约 2.2s→4.4s(1440x2560), 仍低于 6s 主线程阻塞阈值;>2880px 走既有降采样兜底。

H5 A 档绑定opencv.js(embind 裁剪构建)此前无 applyColorMap/cornerHarris/goodFeaturesToTrack。 本次在 core_bindings.cpp 手写三个包装器(契约对齐 OcvCore/mp facade:goodFeaturesToTrack 无 mask 参数、corners 为 JS 数组 push {x,y}),经 embindgen 重新生成 bindings.cpp 并重编 opencv-h5-official 构建树,组装链(DATACOUNT 手术 + binaryen MVP 降级 + ES2019)产出新 js_sdk/opencv.js。node 冒烟 70/70 全绿(含 A 档三项)。

修复(H5 组装链复用残留旧 wasm):组装脚本 binaryenToMvp 从固定路径 /tmp/ocv-b0.wasm 读输入但从未写入,重装时复用 2.2.0 时代残留旧 wasm → 新 glue(含 A 档 embind 注册)配旧 wasm (无对应实现)→ 浏览器初始化 promise resolve undefined → H5 选图无响应。修复:DATACOUNT 手术后先落盘再进 binaryen;同修 --print 步骤缺失 EN 特性开关(trunc_sat 解析失败)。 新产物 4.37MB / 内嵌 wasm 3.14MB;浏览器环境模拟 + 组装产物全量冒烟 70/70 双验证。

2.3.0(2026-09-06)

微信小程序(mp-weixin)支持 —— 无 embind 架构

  • 背景:微信小程序逻辑层禁 eval/new Function(微信注入假桩),opencv.js 的 embind 绑定层(craftInvokerFunction 依赖 new Function)在逻辑层必然崩溃;逻辑层亦无标准 WebAssembly(仅 WXWebAssembly),且无 performance 全局。
  • 方案:纯 C ABI wasm + 纯 JS 外观层替代 embind,数值与 Android/iOS/H5 同源 (同一份 OpenCV 4.8.0 C++ 内核):
    • native/mp-weixin/shim_full.cpp:Mat 句柄 + 全部算法导出(无 embind、0 处 new Function)
    • js_sdk/opencv-facade.js:embind 兼容 cv 外观(Mat/MatVector/值对象/50+ 函数/常量/typed 数据视图)
    • 加载:WXWebAssembly.instantiate('/static/opencv_mp.wasm')(嵌套 imports), glue 用 web,worker 环境 ESM(免 module polyfill)、中和 import.meta.url、注入 performance 垫片
    • I/O:canvas2d 像素桥(getImageData/putImageData→toTempFilePath),包内路径归一化 + 直载兜底
  • 体积:小程序增量 ~2.4MB(wasm 2.3MB + glue/facade ~0.1MB),远低于预览/发布限制
  • 验证:微信开发者工具 3.16.2 模拟器与真机双绿,65 API 全量;数值与各端基线一致 (示例图 test.png:红色 9477 / 连通域 120000 / 直方图峰值 255 / OTSU 150;相册大图: 130196 / OTSU 155 / 霍夫圆 30 / 凸包 3682401 等)
  • 构建复现:native/mp-weixin/build-mp-nobind.sh(emcc 重链)+ scripts/package-mp-wasm.cjs(打包)
  • 已知小差异(不影响语义):canvas 解码的像素级偏差 → 示例图模板匹配分数 0.794(H5/Node 1.0, 命中位置一致 [55,75]);霍夫直线大图 2147(Android 2151,首条一致)

    更新日志

2.2.0(2026-09-05)

轮廓层级树(imgproc)

  • findContoursHierarchy(id, retrMode?, approxMode?):RETR_TREE 层级轮廓分析,返回 { contours, hierarchy, maxDepth }——contours 与 findContours 同字段(含 index), hierarchy 每条为 { index, parent, child, next, prev, depth }(次序按 OpenCV 惯例 next/prev/child/parent,-1 表示无;depth 顶层=0 顺序递推),maxDepth 为树最大深度
  • retrMode 默认 tree(也支持 external/list/ccomp),approxMode 默认 simple
  • 失败/空图返回 {"contours":[],"hierarchy":[],"maxDepth":0}
  • 典型用途:区分容器轮廓与孔洞(父→子=外边界→内边界)、按 depth 分层涂色、抠出内部组件

平台实现

  • Android:android-bridge.cpp 新增 findContoursHierarchy JNI(薄桥重编 4 ABI,aar 12.45M)
  • iOS:OpenCVBridge.mm/.h 新增方法(自编库重编)
  • 鸿蒙:napi_bridge.cpp 新增 NAPI + OpenCVBridge.ets/index.d.ts/index.uts
  • H5:opencv-core.js 新增方法 + web/index.uts 导出
  • 类型:interface.uts 新增 OcvHierarchyEntry/OcvHierarchyResult + opencv-core.d.ts
  • 契约:各端 hierarchy 读取一致(1×N CV_32SC1 每元素 4 值),数值四端对齐

H5 体积与兼容(并入 2.2.0)

  • opencv.js 9.99M → 3.96M(-60%):模块级裁剪(core/imgproc/features2d)+ 函数级白名单
    • 链接级 --gc-sections 三层精简,65 API 全量保留
  • 兼容 QtWebEngine 5.12 / Chromium 69(HBuilderX 内置浏览器):wasm 降级至纯 MVP —— DATACOUNT section 移除、trunc_sat→trunc(WAT 文本层替换)、sign-ext/bulk/SIMD 降级、 blocktype 标准 s33 编码、-s WASM_BIGINT=0(解决导出函数含 i64 在 V8 6.9 的 signature contains illegal type
  • 数值与全量版逐位一致(130196 / 4946 / OTSU 155 / 霍夫 2147·30 / ORB 500(大图)与 150(小图)/ compareHist=1 / 3686377 等),65 API 全绿;scripts/assemble-h5-opencv.cjs 可复现组装链, docs/H5-TRIM.md 记录完整排障
查看更多

平台兼容性

uni-app(3.8.3)

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

uni-app x(4.0)

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

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

基于 OpenCV 4.8.0(H5 为 opencv-wasm 4.8.0)的 uni-app UTS 插件,句柄式图像处理管线。同一套 API 覆盖 H5 / App-Android / App-iOS / 鸿蒙 / 微信小程序,全端结果一致。

✨ 特性

  • 🖼️ 基础处理:灰度、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)
  • 🔀 几何变换:仿射 / 透视变换、图像金字塔上/下采样(1.3.0)
  • 🌈 颜色空间扩展:LAB / XYZ / YCrCb 转换、灰度转彩、通道拆分 / 合成(2.0.0)
  • 增强与像素运算:CLAHE 自适应均衡、加权融合、convertScaleAbs、位运算(与/或/异或/非)、boxFilter 均值模糊、距离变换(2.0.0)
  • 🔍 模板匹配:TM_CCOEFF_NORMED + NMS,返回 Top N 位置与分数
  • 🧩 特征点匹配:ORB 提取 + BFMatcher(HAMMING) + 0.75 比率测试
  • 📱 原生引擎:Android / iOS / 鸿蒙基于 OpenCV 4.8.0 原生实现,H5 走 opencv.js WASM,微信小程序走无 embind 裁剪 wasm(2.3.0)
  • 🏗️ 句柄模型:loadImage 返回句柄,链式处理不拷贝原图,用完必须 releaseImage
  • 🔒 本地计算:所有图像处理均在设备本地完成,不上传任何数据

📦 安装

插件市场搜索「OpenCV 图像识别」或直接导入 uni_modules/axen-opencv-image

本插件已在 Android 模拟器(API 37)/ iOS 模拟器(iPhone)/ 鸿蒙模拟器(arm64)/ 微信开发者工具 3.16.2(模拟器 + 真机) 完成接入验证与全功能自测;如有复杂接入场景,可通过插件市场作者联系方式咨询。

🚀 快速开始

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,
  toBase64
} from '@/uni_modules/axen-opencv-image'

// 1. 初始化(App 端加载 OpenCV 原生库;H5 端等待 wasm 异步编译完成)
await initEngine()

// 2. 加载图片,得到句柄
const img = await loadImage('/storage/emulated/0/xxx.png')   // App: 本地文件绝对路径
// const img = await loadImage('https://xxx/1.png')          // H5: URL / blob / data URL
// const img = await loadImage(wxTempPath)                 // 微信小程序: wx.chooseImage 临时路径,或 '/static/sample/xxx.png' 包内路径(canvas 像素桥)

// 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)

返回类型定义见 utssdk/interface.uts;App 端 findContours / matchTemplate 返回 JSON 字符串(原生数组桥接字段丢失问题,跨端统一字符串传递 + JSON.parse)。

🌐 平台支持

平台 引擎 支持度
H5 (web) opencv.js(opencv-wasm,wasm 内联 base64 + 异步编译改造) 全部能力(发行包将增加约 9.7MB)
App-Android OpenCV 4.8.0(自写 C++ 薄桥 libopencv_bridge.so,替代 Java wrapper;aar 12.4M,内置 4 ABI) 全部能力
App-iOS OpenCV 4.8.0(自编裁剪静态库 46.3M + 预编译 ObjC++ 桥接库,见 docs/IOS.md) 全部能力(需先编译桥接库)
鸿蒙 OpenCV 4.8.0(OHOS 交叉编译,NAPI 桥 libopencv_bridge.so,全部处理原生实现) 全部能力
微信小程序 OpenCV 4.8.0 无 embind 裁剪 wasm(shim_full.cpp 纯 C ABI + JS 外观层,WXWebAssembly.instantiate 加载;小程序增量 ~2.4MB) 全部能力
抖音/支付宝等其它小程序 未支持(引擎实现与微信一致,需按各平台 wasm 通道适配) -

📱 微信小程序(mp-weixin)说明

  • 架构:微信逻辑层禁 eval/new Function、无标准 WebAssembly、无 performance,故不采用 embind; 改由 native/mp-weixin/shim_full.cpp(纯 C ABI,同一份 OpenCV 4.8 内核)+ js_sdk/opencv-facade.js (embind 兼容外观层)提供同名 cv API,数值与其它端一致。
  • 加载:wasm 以 brotli 压缩格式随插件打包在 static/opencv_mp.wasm.bruni_modules/axen-opencv-image/static/,原始 2.38MB → 0.56MB,微信 WXWebAssembly.instantiate 基础库 ≥2.14.0 原生解压),loader 按候选路径探测(.wasm.br 优先 → .wasm 兜底) 经 WXWebAssembly.instantiate 实例化;I/O 走 <canvas type="2d"> 像素桥 (页面 onReady 后先 bindProcessingCanvas(canvas))。
  • 分布(随插件自包含,2.4.0 修正):wasm 唯一来源为插件 uni_modules/axen-opencv-image/static/opencv_mp.wasm.br,随 uni_modules 资产管线打包进小程序包, 第三方导入插件即可用,无需宿主额外放文件。 注意:不要把 wasm 放进插件 js_sdk/——uni 只编译 js_sdk 里的 JS 模块, .wasm 二进制不会被拷入产物(实测 dist 内无该文件,运行时 not found; 2.3.0 曾误放 js_sdk,2.4.0 修正为 static + loader 多候选路径探测)。
  • 体积:小程序增量约 0.7MB(wasm.br 0.56MB + loader/facade ~0.1MB), 预览 4MB 限制下 wasm 仅占 14%(原始 .wasm 占 60%);请在发行模式下使用 (运行模式含 sourcemap,预览上传会超限)。
  • 构建复现native/mp-weixin/build-mp-nobind.sh(emcc 4.0.7 重链)→ scripts/package-mp-wasm.cjs(打包 glue/facade/loader + wasm 拷贝)。

    以上为维护者仓库内的构建脚本(位于 native/scripts/不随插件分发); 插件使用者无需重建,直接导入插件即可。

  • 已知小差异:canvas 解码的像素级偏差会使模板匹配分数略低(示例图 0.794 vs H5 1.0, 命中位置一致);不影响判定阈值与其它数值。

🗓️ 路线图(待支持能力)

当前 68 个 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 新增)覆盖了经典图像处理与特征匹配的常用子集。以下按规划优先级列出待支持能力,全部基于 OpenCV 4.8.0 原生实现(各端引擎已就位,扩展只需新增原生函数 + API 薄层):

近期规划(原生 API 现成,扩展成本低)

  • 轮廓进阶:层级树(凸包 / 逼近 / 最小外接圆 / 旋转矩形已支持,1.3.0;findContoursHierarchy 已支持,2.2.0)
  • 颜色空间扩展:LAB / XYZ / YCrCb / 灰度反变换(已支持,2.0.0)
  • 几何变换:仿射 / 透视变换 / 金字塔(已支持,1.3.0)
  • 直方图:反向投影(均衡化 / CLAHE 已支持,2.0.0;calcHist / calcBackProject / compareHist 已支持,2.1.0)
  • 连通域分析(距离变换已支持,2.0.0;connectedComponents(WithStats) 已支持,2.1.0)
  • 图像增强:CLAHE / addWeighted / convertScaleAbs / bitwise 位运算 / boxFilter(已支持,2.0.0);applyColorMap 伪彩映射 / cornerHarris / goodFeaturesToTrack 角点检测已支持,2.4.0
  • 模板匹配:matchTemplate 已支持;calcBackProject 常配合 splitChannels 取 HSV 单通道做颜色反投影(2.1.0)

中期规划(需引入模型/级联资源,注意包体)

  • 人脸检测(Haar 级联或 YuNet ONNX)
  • SIFT / AKAZE 特征 + FLANN 匹配 + 单应矩阵(findHomography)+ 透视校正与拼接
  • 二维码 / 条码检测(QRCodeDetector):已排期 2.5.0 随 OpenCV 升版引入 —— OpenCV 4.8.0 旧版 QRCodeDetector(依赖第三方 QUIRC)解码存在上游通用缺陷(detect 正常但部分码解码为空,#23249 / #24318,原生/桌面/wasm 一致);官方 4.9.0+ 提供不依赖 QUIRC 的自研解码器(PR #24299),故随升版(2.5.0)引入
  • DNN 推理模块(ONNX:分类 / 检测 / 分割,模型由宿主下发)

远期规划

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

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

⚠️ 鸿蒙 HarmonyOS 说明

  • 鸿蒙实现位于 utssdk/app-harmony/index.uts(UTS 入口)+ OpenCVBridge.ets(混编 ArkTS,通过 NAPI import opencvNative from 'libopencv_bridge.so' 调用原生)+ 内置原生库。
  • 全原生实现:基础处理(灰度/HSV/二值化/模糊/缩放/颜色检测/绘制)与高级能力(Canny/轮廓/模板/ORB)均走 NAPI 原生 OpenCV(Uint8Array 通道),与 Android/iOS 算法结果一致;仅图片解码(@ohos.multimedia.image)与 PNG 编码(ImagePacker)走系统 API。
  • .so 打包方式:HAR 不支持携带 .so,需同步将 libopencv_bridge.so / libc++_shared.so 放入项目 harmony-configs/entry/libs/<abi>/(HBuilderX 会覆盖到生成的鸿蒙工程,打包进对应 libs/<abi>/)。插件目录 utssdk/app-harmony/libs/ 内已附带两个 ABI 的库,直接拷贝即可。
  • 双 ABIarm64-v8a 用于真机/模拟器,x86_64 用于 x86 模拟器;HarmonyOS NEXT 仅 64 位,无需 32 位 ABI。
  • 原生库重建(仅插件维护者):源码与脚本在仓库 native/harmony/

    cd native/harmony
    ./build-so.sh            # arm64-v8a(默认)
    ./build-so.sh x86_64     # x86_64

    前置:OpenCV 4.8 源码 /tmp/opencv-4.8.0/,交叉编译静态库于 /tmp/opencv-ohos-build(arm64)与 /tmp/opencv-ohos-x64-build(x86_64),OpenCV cmake 参数:

    cmake -DCMAKE_TOOLCHAIN_FILE=$OHOS_SDK/native/build/cmake/ohos.toolchain.cmake \
        -DOHOS_ARCH=<arm64-v8a|x86_64> -DBUILD_SHARED_LIBS=OFF \
        -DBUILD_LIST=core,imgproc,flann,features2d,calib3d /tmp/opencv-4.8.0

    链接使用 -lace_napi(libace_napi.z.so,NAPI 运行时符号);产物同步到插件 utssdk/app-harmony/libs/<abi>/ 与项目 harmony-configs/entry/libs/<abi>/

  • 鸿蒙运行需 uni-app x 工程(HBuilderX 4.61+),并处理运行时 EntryAbility(不依赖 HBuilderX 调试会话),参考仓库 harmony-configs/entry/src/main/ets/entryability/EntryAbility.ets

⚠️ iOS 说明

  • iOS 原生实现位于 utssdk/app-ios/,依赖 Libs/OpenCVBridge/libOpenCVBridge.a(自编裁剪 OpenCV 4.8.0 静态库,7 模块 + 全 codec,46.3M)+ ios-bridge/ 头文件。
  • 内置桥接库为自编裁剪版(arm64 + x86_64 双 slice,46.3M,OpenCV 已静态合并):可直接用于 iOS 模拟器联调;真机打包前需用 native/ios/build-trim-bridge.sh 重新编译并替换,否则真机链接失败(官方 framework 含大量无用 bitcode,新流程已去除)。
  • 首次编译前需执行 native/ios/build-trim-bridge.sh(自编裁剪 framework + 合并桥接,详见 docs/IOS.md)。OpenCV 4.8.0 已静态合并进桥接库,无需 pod。
  • 桥接采用 NSNumber + NS_SWIFT_NAME 无标签签名;findContours/matchTemplate 返回 JSON 字符串(iOS 类型化对象数组桥接字段丢失问题)。

⚠️ Android 说明

  • 薄桥架构:65 个 API 由自写 C++ 薄桥 libopencv_bridge.sonative/android/android-bridge.cpp,JNI)直接实现,像素常驻 native 池(BGR 8UC3,cv::imread 加载,与历史基线一致);OpenCVNative.kt 为 external 薄层(公开签名不变)。已放弃官方 Java wrapper(不再依赖 org.opencv.* 与 classes.jar)
  • aar 内置 4 ABI(arm64-v8a / armeabi-v7a / x86 / x86_64),build-bridge.sh 可一键重编;64 位 so 已按 16KB 页对齐(满足 Google Play 要求)
  • 真机运行需自定义调试基座(HBuilderX: 运行 → 运行到手机或模拟器 → 制作自定义调试基座);自写 JNI 库改档后需重打基座
  • 格式支持:JPEG/PNG/WEBP/TIFF/EXR/JPEG2000(imread 全 codec,与 iOS 一致);读取相册/拍照由宿主 uni.chooseImage 授权

🔐 隐私与安全

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

📄 许可证

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

隐私、权限声明

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

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

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

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

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