OpenCV 图像识别 - 更新日志

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

2.6.0(2026-09-19)

新增:5 个几何 / 体验 API —— 五端可用(API 总数 72 → 77)

API 说明
imageSize(id) 图像尺寸,返回 { width, height };句柄无效 width=-1
getRoi(id, x, y, w, h) ROI 裁剪(平移仿射实现,像素精确);越界 / 非法尺寸返回 -1,结果需 releaseImage
rotate(id, angleDeg, scale?) 任意角度旋转:angleDeg 正值=逆时针(度),与 flipRotate 方向一致;scale 缩放内容
matchTemplateMultiScale(id, templateId, topN?, scales?) 多尺度模板匹配:模板按各尺度缩放后与原尺寸源图匹配,跨尺度 NMS 去重
releaseAll() 释放池内全部句柄,返回释放数量

行为契约

  • rotate:90 的倍数且 scale=1 时走像素精确路径(flipRotate)并互换宽高;其它角度为同尺寸仿射(四角黑边),宽高不变。
  • matchTemplateMultiScale:返回 JSON [{ x, y, width, height, score, scale }](score 降序;scale>1 表示实例比模板大;box 为模板尺寸在源图坐标系);默认 scales=[0.6,0.8,1.0,1.5]、topN=3;每尺度一次全图匹配,大图建议先 resize 降采样。
  • releaseAll 释放后原句柄全部失效,句柄计数器不清零(与 loadImage 后的序号连续行为一致)。
  • getRoi / rotate 返回新句柄,同样需要 releaseImage;不修改源图(非破坏式)。

跨端差异

  • releaseAll:H5 / 微信小程序为 OcvCore 实现,导入即可用;App 三端(Android / iOS / 鸿蒙)为原生实现,需随 2.6.0 基座产物运行——自编基座的项目需重新打基座,否则调用报未找到。
  • rotate 非 90 倍数角度的插值结果与原生各端亚像素插值一致;跨端数值与模板匹配家族基线一致(详见验收)。

五端验收(2026-09-18,真机 + 模拟器全量复核)

  • 照片基线(1440×2560)五端逐项复核通过:红色 130196 / 轮廓 4967(鸿蒙族 4955)/ 模板 0.519(原生族)· 0.492(wasm 族)· 0.863(鸿蒙族)/ 霍夫直线 2151(真机 arm64)· 2147(模拟器与 wasm 族)/ 霍夫圆 30@(973,1470) r=198 全端一致。
  • 压力:Android 真机连打 40+31 次、x86_64 模拟器 31+32 次、鸿蒙真机 32+30 次、H5 浏览器 15 次、mp 真机 5+19 次、iOS 真机 71 次 + 模拟器 47 次(1016–1334ms 真机 / 505–620ms 模拟器)——全部零漂移零崩溃。
  • 工具链分族提醒:模板分数 / 霍夫直线在原生 arm64、x86_64 模拟器、wasm、鸿蒙四族间存在既定基线差异(见 README「跨端差异」),回归时按族对照,不跨族比较。

升级注意

  • App 三端(Android / iOS / 鸿蒙)升级后需重新以 2.6.0 基座运行(自编基座需重新打包基座);H5 / 微信小程序无额外动作。
  • 引擎仍为 OpenCV 4.9.0,既有 API 行为与数值无变化。

2.5.0(2026-09-10)

新增:二维码(QR)4 个 API —— 五端可用

API 说明
qrEncode(text) 文本生成二维码,返回 8UC1 二值图句柄(需 releaseImage)
qrDetect(id) 检测二维码,返回 { ok, points: [{x,y}×4] } 四角点
qrDecode(id) 解码二维码,返回 { ok, text }
qrDetectAndDecode(id) 一步检测 + 解码,返回 { ok, points, text }
  • 解码要求被解图内二维码模块 ≥ 10 像素(模块过小时先用 resize 放大再解码)。
  • 类型定义:OcvQrPoint / OcvQrDetectResult / OcvQrDecodeResult。

引擎升级:OpenCV 4.8 → 4.9.0

  • 模块范围:core / imgproc / features2d / flann / calib3d / objdetect(图片解码按平台选用系统 codec)。
  • 既有 API 行为与数值不变:合成图基线(OTSU 141 / 三角法 12 / 霍夫直线 131 / 霍夫圆 1 / Shi-Tomasi 13)与 4.8 完全一致,68 项 API 无回归。
  • 二维码解码能力随 4.9 落地:4.8 时代的解码器存在上游缺陷(检测正常但部分二维码解码为空),因此 2.4.0 未交付解码能力,改为随内核升版一并提供。

五端验收基线(同一张 1440x2560 照片)

指标 mp H5 Android iOS 鸿蒙
内核 4.9.0 4.9.0 4.9.0 4.9.0 4.9.0
红色像素 130196 130196 130196 130196 130196
OTSU / 三角 155 / 78 155 / 78 155 / 78 155 / 78 155 / 78
霍夫直线 2147 2147 2151 2147 2151
模板最佳分 0.492@[583,2171] 0.492@[583,2171] 0.519@[582,2171] 0.519 0.519
霍夫圆 30 30 30 30 30
轮廓 / 层级树 4967 / 顶1深1 4967 / 顶1深1 4967 / 顶1深1 4967 / 顶1深1 4955 / 顶1深1
QR 四按钮 全通 全通 全通 全通 全通
QR 角点 [[28,30],[449,28],…] 同 mp [[28,30],[450,29],…] 同 mp 同 Android
  • 数值分两族:wasm 端(H5 / 小程序) 与 原生端(App / 鸿蒙),两者只在浮点敏感指标上差最后一档(霍夫直线 2147 vs 2151、模板分 0.492 vs 0.519、示例图模板分 0.813 vs 0.873)。成因是向量化内核与标量内核的浮点归约顺序不同,不影响阈值判定与业务结论。
  • 示例图 400x300 基线(mp 与 H5 逐项同值):红色 9477、轮廓 23、模板 0.813@[55,75]、霍夫直线 412、霍夫圆 0、凸包 119301、ORB 297/295、OTSU 150·253。

修复

  • H5:在 HBuilderX 内置浏览器(QtWebEngine 5.12 / Chromium 69)初始化失败(报 wasm function signature contains illegal type),现代浏览器正常。已修复,并复核内置浏览器与外部浏览器数值一致。
  • 鸿蒙:霍夫圆检测偶发返回 0 个(同图重跑概率性发生)。已修复,现与其它端一致多线程执行且结果稳定。
  • iOS:二维码接口偶发 JSON 解析失败(报「未能读取数据,因为它的格式不正确」)。已修复。
  • 鸿蒙 / demo:二维码生成后的结果图预览异常(鸿蒙端横向重复 4 份并纵向压扁;demo 端被压成 203x360 非等比)。二维码数据本身正常,预览已与其它端一致。

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.br(0.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 记录完整排障

2.1.1(2026-09-03)

  • 清除 iOS --install 残留的 libOpenCVBridge.a.bak(46.35M 旧库备份被打进插件 zip → 50M)
  • 插件 zip 实测 37,278,259(37.2M),体积战役成果保持(-71%)
  • 功能面与 2.1.0 完全一致(无代码变更,仅发布产物修正)

2.1.0(2026-09-03)

直方图族(imgproc):

  • calcHist(id, bins?):灰度直方图(非灰度自动转灰,bins 默认 256)。返回直方图句柄(1×N 8U,归一化 0-255,可 toBase64 展示)+ bins 数值数组(峰值=最亮 bin 计数归一到 255)。失败 {"id":-1,"bins":[]}
  • calcBackProject(id, histId):以直方图句柄为模型的灰度级反投影(单通道灰度模型,像素值→该灰度的直方图强度),返回 8U 单通道反投影图句柄。hist 尺寸<2 返回 {"id":-1}。非灰度自动转灰
  • compareHist(h1, h2, method?):直方图相似度。method: correlation(默认,-1~1 越大越相似)/ chisqr(越小越相似)/ intersection(越大越相似)/ bhattacharyya(0~1 越小越相似)。长度不符/无效返回 {"value":-1}

连通域(imgproc):

  • connectedComponentsWithStats(id):连通域统计。返回 {count, labelId, components:[{x,y,width,height,area,centerX,centerY}]};count 为非背景连通域数,components 按面积降序(跳过背景),labelId 为 labels 归一化转 8U 的可视化句柄(可 toBase64)。非灰度自动转灰。输入空/失败 {"count":0,"labelId":-1,"components":[]}
  • connectedComponents(id):仅返回 count(内部同 WithStats 实现,统一返回完整结构)

跨端契约:四个平台返回结构完全一致(iOS/Android/鸿蒙 JSON 字符串,H5 对象);直方图/反投影/连通域的句柄均为新句柄,用完需 releaseImage。OpenCV wasm 官方自带 calcHist/calcBackProject/compareHist/connectedComponents(WithStats) 符号(H5 预检通过,无需自编 wasm)。

平台实现:

  • Android:android-bridge.cpp 新增 5 个 JNI 函数(薄桥重编 4 ABI,aar 12.44M)
  • iOS:OpenCVBridge.mm/.h 新增 5 个方法(自编库重编 46.5M)
  • 鸿蒙:napi_bridge.cpp 新增 5 个 NAPI 函数 + OpenCVBridge.ets/index.d.ts/index.uts(重编双 ABI,strip 同 2.0.1)
  • H5:opencv-core.js 新增 5 个方法 + web/index.uts 导出
  • 类型:interface.uts 新增 5 个返回类型(OcvHistResult/OcvBackProjectResult/OcvCompareResult/OcvComponent/OcvConnectedComponentsResult)+ opencv-core.d.ts

2.0.1(2026-09-03)

Android 薄桥重构 + 四端体积优化,发布包 130M → 37M(-71%)

Android 薄桥(架构重构):

  • 放弃 OpenCV Java wrapper(classes.jar + 全量 1124 个 JNI 入口 + converters 层),改为自写 C++ 薄桥 libopencv_bridge.so(native/android/android-bridge.cpp):59 个 API 全部 C++ 直实现,像素常驻 native 池(BGR 8UC3,cv::imread 路径与历史基线一致,四端数值逐位对齐)
  • OpenCVNative.kt 重写为 external 薄层(公开签名不变,Application.kt 调用面零改动),不再依赖 org.opencv.*
  • aar:41.97M → 12.42M(-70%);arm64 薄桥 10.0M / v7a 5.6M / x86 8.3M / x86_64 8.3M(对比官方全模块 arm64 21M+ 减半)
  • 移除了全部冗余 libc++_shared.so(薄桥 -static-libstdc++ 自包含)
  • 已通过 Android arm64 真机 + 模拟器(emulator arm64)全量回归:59 API 全通,数值与 iOS/鸿蒙/H5 完全一致

修复的三连雷(JNI 加载层):

  • 链接 --strip-all 误删 .dynsym 动态导出 → 改 llvm-strip --strip-unneeded(保留 JNI 导出)
  • JNI 函数缺 extern "C" 被 C++ mangling(_Z60Java_...)→ ART 报 No implementation found → 已包裹
  • init/releaseImage 漏改 Kotlin external 名 init0/releaseImage0 后缀 → 已对齐

四端体积优化:

  • iOS:libOpenCVBridge.a 从官方全模块 192M 裁剪到 46.3M(7 模块 + 去 bitcode + 补 TIFF/JPEG2000/WEBP codec),zip 68M → 15.5M
  • 鸿蒙:libopencv_bridge.so strip(删 .symtab,代码字节不变),6.9M+10.4M → 5.2M+8.4M
  • Android:aar 41.97M → 12.42M;四端构建脚本与产物同步:
    • native/ios/build-trim-bridge.sh(iOS 自编裁剪 framework + 桥接合并)
    • native/android/build-bridge.sh + android-bridge.cpp(Android 薄桥一键编译 4 ABI)
  • 16KB 页大小对齐确认:64 位 ABI(arm64/x86_64)p_align=0x4000 满足 Google Play 要求
  • 发布包实测:130M → 37.2M(-71%),四端功能面与官方一致

2.0.0(2026-09-03)

新增 15 个图像处理 API(四端统一:颜色空间 6 + 增强/像素 9 合并发版),版本 1.3.0(44 API)→ 2.0.0(59 API)

颜色空间扩展:

  • cvtLab / cvtXyz / cvtYCrCb:颜色空间转换(H5/鸿蒙 RGBA 池先转 BGR 再转,输出 3ch 数值通道图;非 3/4ch 输入返回 -1)
  • grayToBgr:灰度(1ch)扩为 3 通道(便于灰度图叠加彩色标注)
  • splitChannels:按内存物理序拆前 3 通道为三个单通道句柄(4ch→R,G,B;3ch→序内通道;对 LAB/HSV 产物拆分即得 L,a,b / H,S,V);<3ch 输入返回全 -1
  • mergeChannels:三个单通道句柄按序合成 3ch 新句柄(与 splitChannels 同序)

增强与像素运算:

  • clahe:CLAHE 自适应直方图均衡(非灰度自动转灰,默认 clipLimit=2.0、tileSize=8)
  • addWeighted:加权融合 dst=α·a+β·b+γ(尺寸/通道不一致返回 -1)
  • convertScaleAbs:dst=|α·src+β| 转 8U(默认 α=1 β=0)
  • bitwiseAnd/Or/Xor/Not:双图/单图位运算(双图尺寸/通道不一致返回 -1)
  • boxFilter:均值模糊(ksize 自动奇数化,默认 normalize=true)
  • distanceTransform:DIST_L2+mask3 → 归一化 0-255 转 8U 返回(可选阈值截断;避免 32F 无法 PNG 编码的跨端坑)

注意:splitChannels/mergeChannels 按内存物理序(不做 RGB/BGR 语义重排);对 cvtLab/cvtHsv 等转换产物拆分时四端通道序一致(L,a,b 等),对原图拆分则 Android/iOS(BGR) 与 H5/鸿蒙(RGBA) 序不同,跨端场景请对转换产物使用。

1.3.0(2026-09-02)

新增 10 个图像处理 API(四端统一,句柄模型不变,失败返回 -1 / 空 JSON)+ findContours 增强:

  • 轮廓进阶:convexHull(凸包,返回扁平点集 + 面积)、approxPolyDP(多边形逼近,epsilonRatio 默认 0.02)、minEnclosingCircle(最小外接圆)、minAreaRect(旋转矩形,angle -90~0)——均基于内部 findContours 取第 index 个轮廓,越界返回空结构
  • 几何变换:getAffineTransform / warpAffine(3 点仿射)、getPerspectiveTransform / warpPerspective(4 点透视,可指定输出尺寸)、pyrUp / pyrDown(图像金字塔上/下采样)
  • findContours 增强(向后兼容):新增可选参数 retrMode(external/list/ccomp/tree)与 approxMode(simple/none);每项新增 perimeter(周长)。旧调用(无参数)输出完全兼容。注:完整点集不随 findContours 返回(数千轮廓会使 JSON 达数十 MB 导致 parse 失败),请用 convexHull / approxPolyDP 获取点集

矩阵类参数统一用 number[] 传递(仿照 filter2D);变换矩阵生成 API 返回 JSON 字符串(跨端数组返回值桥接不可靠)。所有几何变换支持自定义输出尺寸(默认原图尺寸),INTER_LINEAR + BORDER_CONSTANT。

1.2.0(2026-09-01)

1.2.0(2026-08-28)

1.1.0(2026-08-28)

新增 8 个图像处理 API(四端统一,句柄模型不变,失败返回 -1):

  • 形态学:morphErode(腐蚀)/ morphDilate(膨胀)/ morphologyEx(开、闭、梯度、顶帽、黑帽)
  • 滤波与阈值:adaptiveThreshold(自适应二值化,光照不均场景)、medianBlur(中值去椒盐噪声)、bilateralFilter(双边保边平滑)
  • 增强:equalizeHist(直方图均衡化)
  • 几何:flipRotate(水平/垂直翻转,逆时针旋转 90/180/270)

全部支持非灰度输入自动转灰度(bilateralFilter 除外,其按原色彩空间处理);ksize 自动修正为奇数。

1.0.0(2026-08-27)

首个公开版本。

核心能力(15 个 API,四端统一)

  • 图像基础处理:loadImage / releaseImage / resize / cvtGray / cvtHsv / threshold / gaussianBlur / drawRect / toBase64
  • 颜色检测:detectColorRange(HSV 范围过滤,返回命中像素数/占比/外接矩形)
  • 边缘检测:canny
  • 轮廓与形状识别:findContours(面积/外接矩形/顶点数/形状分类 circle·rectangle·triangle·quad·other)
  • 模板匹配:matchTemplate(TM_CCOEFF_NORMED + NMS,Top N 位置与分数)
  • 特征点匹配:orbMatch(ORB + BFMatcher(HAMMING) + 0.75 比率测试)

平台支持

平台 引擎 说明
App-Android OpenCV 4.8.0 官方 classes.jar + 原生 so 重打包 aar 内置(4 ABI),兼容 Android 14+(bionic __sfp_handle_exceptions 移除问题已规避)
App-iOS OpenCV 4.8.0 pod OpenCV 4.8.0 + 预编译 ObjC++ 桥接库(内置模拟器版,真机需 device 模式重编,见 docs/IOS.md)
鸿蒙 HarmonyOS OpenCV 4.8.0 OHOS 交叉编译 libopencv_bridge.so(NAPI 桥,句柄制零拷贝架构),arm64-v8a + x86_64 双 ABI
H5 (web) opencv-wasm 4.3.0 wasm 内联 + 异步编译改造

工程质量

  • 四端算法完全一致(同一 OpenCV 4.8.0),跨端契约统一(错误码/空值结构/参数语义)
  • 句柄制架构:像素常驻 native/wasm 内存,跨语言调用零像素拷贝(Android/iOS/鸿蒙/H5 同构)
  • 健壮性:非法输入全兜底(彩色自动转灰/尺寸校验/颜色回退)、异常不穿透边界、无已知内存泄漏
  • 经 7 轮代码审查,累计修复 35+ 项(功能/内存/跨端一致性/边界条件)
  • 所有图像处理均在本地完成,不上传任何数据、不新增权限