更新记录

1.0.0(2026-11-12) 下载此版本

Demo

0.1.1(2026-11-12) 下载此版本

  • 修复 iOS / HarmonyOS 二进制缺少新增 API 的问题:用 binding.cc 重编三端二进制,actionCheckJpeg / actionCheckRgba / colorCheckJpeg / colorCheckRgba / previewFrameRgba / previewFileRgba / livenessCheckFramesRgba 在 Android / iOS / HarmonyOS 全部可用(17 个 API 对齐)
  • 修复 Android 原生崩溃:YuNet 返回越界人脸框时 ROI 断言异常(0 <= roi.x && ... <= m.rows)穿透 napi 导致 App abort;现统一夹紧 ROI,并在 napi 入口兜底把 C++ 异常转为 JS 异常(actionCheckRgba / livenessCheckFramesRgba 等不再可能整机闪退)
  • iOS 侧明确走 utssdk/app-js + uasm/app-ios xcframework(iOS 恒为 JS 引擎,不需要 utssdk/app-ios)
  • utssdk/app-js 新增相机 RGBA 帧自动转正(按分辨率探测并缓存),<camera> 的 onCameraFrame 帧可直接送 actionCheckRgba / colorCheckRgba / livenessCheckFramesRgba

平台兼容性

uni-app x(5.26)

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

其他

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

da-face-uasm

基于 OpenCV DNN 的活体检测 + 人脸识别 + 图片比对 uasm 插件(uni-app x)。

支持静默活体(ONNX 单帧)、动作活体(68 点关键点 EAR/MAR 多帧)、人脸检测、特征提取(MobileFaceNet embedding)、余弦相似度比对。App 平台(Android/iOS/HarmonyOS)原生二进制,web/小程序 WebAssembly,同一套源码编译。

能力

能力 方法 说明
静默活体 livenessCheck 单帧反射光/皮肤纹理分析(Silent-Face ONNX),判断真人/照片/屏幕
动作活体 livenessCheckFrames 多帧 68 点关键点,眨眼(EAR)/张嘴(MAR)时序
人脸检测 detectFaces 位置 + 关键点(Haar 级联 + 关键点模型)
特征提取 extractEmbedding MobileFaceNet embedding(128D/512D)
比对 compare / compareImages / findBest 余弦相似度,纯数学
一体化 analyzeFace 活体→检测→特征→库中比对,一次调用

安装

把 uni_modules/da-face-uasm 放入工程 uni_modules/ 目录。模型文件放 static/(建议 static/face/):

static/face/
├── mobilefacenet.onnx      # 特征提取(embedding)
├── silentface.onnx         # 静默活体
├── haarcascade_frontalface_default.xml   # 人脸检测
└── face_landmark.onnx      # 68 点关键点(动作活体 + 对齐)

使用

一体化识别(活体 + 检测 + 特征 + 比对)

// App 平台
const face = uni.loadUasmSync('uni_modules/da-face-uasm')
// web 平台
// const face = await uni.loadUasm('uni_modules/da-face-uasm')

const r = face.analyzeFace(imgBase64, {
  gallery: [{ name: '张三', embedding: [0.12, ...] }],
  threshold: 0.65
})
// r.isLive / r.score / r.faces[0].match.name / r.faces[0].match.similarity

分步(对齐主流 UTS 插件做法)

// 1. 活体检测(单帧)
const live = face.livenessCheck(imgBase64)   // { isLive, score }

// 2. 检测 + 提取特征
const faces = face.detectFaces(imgBase64)
const emb = face.extractEmbedding(faceImgBase64)   // number[]

// 3. 比对(纯数学)
const sim = face.compare(emb, galleryEmb)          // 0~1
const hit = face.findBest(emb, gallery, 0.65)      // { name, similarity } | null

无界面活体(纯 API,宿主自绘 UI)

插件只提供 API,不内置任何 UI 组件/页面。活体检测为回调驱动的无界面模式:

import { init, startLiveness, stopLiveness } from '@/uni_modules/da-face-uasm'

await init()

// 取帧方式取决于运行时脚本引擎(见下方「两种取帧路线」):
// - JS 引擎(manifest "vapor": true 的 Android 项目、iOS):页面必须放置 <camera>;
// - native 引擎(Android "vapor": false + 自定义基座):走内置原生 Camera2,页面无需 <camera>。
startLiveness({
  actions: [1, 0, 5],            // 顺序+数量可配:0眨眼 1摇头 2点头 3张嘴 4远近 5炫彩;空=随机3个+炫彩
  onPreview: (preview) => { /* 预览帧:原生 Camera2 为 JPEG 文件路径(双文件交替);<camera> 路线为 base64 */ },
  onAction: (code, prompt) => { /* 当前动作提示,宿主按 prompt 展示 */ },
  onActionCheck: (code, passed) => { /* 单动作判定 */ },
  onError: (msg) => { /* 启动失败(相机缺失/权限/初始化失败),宿主展示错误 */ },
  onResult: (res) => { /* 最终 { isLive, score },任一动作失败即 false */ },
})

// 任意时刻彻底关闭摄像头(会话停止,残留帧不再回调)
stopLiveness()
  • 预览帧引擎入口:actionCheckJpeg/colorCheckJpeg(JPEG 多帧,配合原生摄像头文件回调)
  • RGBA 裸帧入口:livenessCheckFramesRgba/actionCheckRgba/colorCheckRgba(uni.createCameraFrame 直通,免 JPEG 编码)
  • RGBA 帧自动转正:相机缓冲是传感器朝向(竖屏时画面横躺),以上三个 RGBA 入口会自动探测应逆/顺时针转 90°,探测到人脸后再判定,宿主无需自己旋转
  • 预览帧编码:previewFrameRgba(base64)/previewFileRgba(原子覆写文件,不闪屏)
  • 宿主自己用 <camera> 渲染取景时传 preview: false,跳过插件预览编码,检测帧率更稳

Demo(test 工程)

  • pages/face/headless-demo:无界面活体演示(插件只回调动作/判定/结果,宿主自绘圆环/提示/炫彩;取景由页面 <camera> 提供)
  • pages/face/camera-demo:<camera> 组件活体 demo(页面内置官方 <camera> + uni.createCameraContext().onCameraFrame 采 RGBA 帧),逐个测试帧流 API:actionCheckRgba / colorCheckRgba / livenessCheckFramesRgba / previewFrameRgba / actionCheckJpeg
  • pages/face/api-test:所有 API 逐一测试(init/version/livenessCheck/detectFaces/extractEmbedding/compare/findBest/compareImages/analyzeFace/选图识别)

两种取帧路线

路线 页面要求 生效条件 入口 API
内置原生摄像头(Camera2) 无需 <camera> 仅 native 脚本引擎:Android manifest "vapor": false + 自定义基座 startLiveness(onPreview/onAction/onActionCheck/onResult/onError)
<camera> 组件 页面需放 <camera> App Android/iOS 全场景,含 Vapor("vapor": true 强制 JS 引擎);onCameraFrame 要求 uni-app x 4.61+ startLiveness(onPreview 返回 base64)/ actionCheckRgba / colorCheckRgba / livenessCheckFramesRgba / previewFrameRgba / previewFileRgba / actionCheckJpeg

为什么 Vapor 项目必须放 <camera>:Android 开启 "vapor": true 时编译器强制 UNI_APP_X_UVUE_SCRIPT_ENGINE='js',插件解析优先级变为 utssdk/app-js/index.uts > utssdk/app-android,原生 Camera2 不会被加载。此时 startLiveness 依赖页面内 <camera> 供帧;页面没放会触发 onError('未找到摄像头…')。

若必须做到「页面无 <camera>」,需关闭 vapor 并使用 native 引擎 + 自定义基座,或改为纯原生插件(aar)。

平台支持

  • App:Android(arm64-v8a/x86_64)、iOS(xcframework)、HarmonyOS(arm64-v8a/x86_64)——原生 Node-API
  • web/H5:WebAssembly(异步 uni.loadUasm)
  • 小程序:微信/支付宝 wasm(worker 桥接)

编译

见 uasm-face/README.md(uni-gyp + emscripten 工具链)。

注意

  • 所有图片以 Base64 字符串传入(uasm 桥不支持 ArrayBuffer 直传)
  • embedding 为 number[],可存 uni.setStorage/文件/服务端
  • 活体阈值与比对阈值需用真实数据标定(同一人通常 >0.7,不同人 <0.5,阈值取分界)
  • 动作活体需摄像头连续帧;若只需单张图,用静默活体
  • Android 需 CAMERA 权限(插件 AndroidManifest.xml 已声明;宿主 manifest 如有冲突以宿主为准)

隐私、权限声明

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

无

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

插件不采集任何数据

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

无

许可协议

MIT协议

暂无用户评论。