【HarmonyOS 5】VisionKit人脸活体检测详解
【HarmonyOS 5】VisionKit人脸活体检测详解
一、VisionKit人脸活体检测是什么?
VisionKit是HamronyOS提供的场景化视觉服务工具包。
华为将常见的解决方案,通常需要三方应用使用SDK进行集成。华为以Kit的形式集成在HarmoyOS系统中,方便三方应用快速开发和赋能。
而VisionKit中包含人脸活体检测的功能接口interactiveLiveness 。人脸活体检测见名知意,主要是为了检测当前人是否为活人本人,而不是照片,硅胶面具,AI视频仿真的可能。
虽然该算法接口已通过中金金融(CECA)认证。但是官方还是建议添加额外的安全措施后,在使用该人脸检测接口,尽量不要直接使用在高风险性的支付和金融场景中。推荐在低危险场景,例如登录,考勤,实名认证等业务场景进行使用。
需要注意的是**,人脸活体检测,不支持模拟器和预览器。**
详情参见官方接口:
https://developer.huawei.com/consumer/cn/doc/harmonyos-references/vision-interactive-liveness
https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/vision-interactiveliveness

二、人脸活体检测如何使用?
人脸活体检测功能interactiveLiveness ,起始版本为 5.0.0 (API12),可通过@kit.VisionKit模块导入,支持动作活体检测模式(INTERACTIVE_MODE),动作数量可配置为 3 或 4 个,包含点头、张嘴、眨眼等 6 种动作。
通过InteractiveLivenessConfig配置检测模式、跳转路径、语音播报等参数,提供startLivenessDetection和getInteractiveLivenessResult接口,能抵御照片、视频等攻击,适用于身份验证场景,需申请ohos.permission.CAMERA相机权限,错误码可参考 Vision Kit 错误码文档。
Vision Kit 错误码文档
https://developer.huawei.com/consumer/cn/doc/harmonyos-references/vision-error-code
1. 核心接口为人脸页面唤起接口:
interactiveLiveness.startLivenessDetection,该接口需要配置config进行设置人脸的模式,动作等操作。
(1) Promise 方式:仅返回跳转结果(boolean)。
interactiveLiveness.startLivenessDetection(routerOptions).then((DetectState: boolean) => {hilog.info(0x0001, "LivenessCollectionIndex", `Succeeded in jumping.`);
}).catch((err: BusinessError) => {hilog.error(0x0001, "LivenessCollectionIndex", `Failed to jump. Code:${err.code},message:${err.message}`);
})
(2) Promise + 回调方式:同时返回跳转结果和检测结果(仅适用于 BACK_MODE)。
interactiveLiveness.startLivenessDetection(routerOptions, (err: BusinessError, result: interactiveLiveness.InteractiveLivenessResult | undefined) => {if(err.code !== 0 && !result) {hilog.error(0x0001, "LivenessCollectionIndex", `Failed to detect. Code:${err.code},message:${err.message}`);return;}hilog.info(0x0001, 'LivenessCollectionIndex', `Succeeded in detecting result:${result}`);
})
2. InteractiveLivenessConfig配置接口:
调用人脸活体检测,需要填入该配置对象,进行相关设置,参数见以下表格:
-
检测模式(DetectionMode)
名称 值 说明 SILENT_MODE “SILENT_MODE” 静默活体检测(暂未支持) INTERACTIVE_MODE “INTERACTIVE_MODE” 动作活体检测(默认模式) -
动作数量(ActionsNumber)
名称 值 说明 ONE_ACTION 1 随机1个动作(暂未支持) TWO_ACTION 2 随机2个动作(暂未支持) THREE_ACTION 3 随机3个动作([眨眼,注视]不同时存在且不相邻,相邻动作不重复) FOUR_ACTION 4 随机4个动作(眨眼仅1次,注视最多1次,[眨眼,注视]不相邻,相邻动作不重复) -
跳转模式(RouteRedirectionMode)
名称 值 说明 BACK_MODE “back” 检测完成后调用router.back返回上一页 REPLACE_MODE “replace” 检测完成后调用router.replaceUrl跳转(默认模式) -
配置项(InteractiveLivenessConfig)
名称 类型 必填/可选 说明 isSilentMode DetectionMode 必填 检测模式(默认INTERACTIVE_MODE) actionsNum ActionsNumber 可选 动作数量(3或4,默认3) successfulRouteUrl string 可选 检测成功跳转路径(未填则用系统默认页面) failedRouteUrl string 可选 检测失败跳转路径(未填则用系统默认页面) routeMode RouteRedirectionMode 可选 跳转模式(默认REPLACE_MODE) challenge string 可选 安全摄像头场景挑战值(16-128位,空值表示不使用) speechSwitch boolean 可选 语音播报开关(默认开启) isPrivacyMode boolean 可选 隐私模式(需申请ohos.permission.PRIVACY_WINDOW权限,默认关闭)
人脸活体检测的配置项对象除了isSilentMode是必填,其他属性均为可选:
import { interactiveLiveness } from '@kit.VisionKit';let isSilentMode = "INTERACTIVE_MODE" as interactiveLiveness.DetectionMode;
let routeMode = "replace" as interactiveLiveness.RouteRedirectionMode;
let actionsNum = 3 as interactiveLiveness.ActionsNumber;
let routerOptions: interactiveLiveness.InteractiveLivenessConfig= {isSilentMode: isSilentMode,routeMode: routeMode,actionsNum: actionsNum,failedRouteUrl: "pages/FailPage",successfulRouteUrl: "pages/SuccessPage"
}
3. getInteractiveLivenessResult获取人脸活体检测结果:
在调用人脸活体检测成功后,可通过该接口获取检测结果。结果内容如下表格所示:
| 名称 | 类型 | 只读 | 可选 | 说明 |
|---|---|---|---|---|
| livenessType | LivenessType | 是 | 否 | 活体检测模式,值包括: - 0(INTERACTIVE_LIVENESS,动作活体检测)- 1(SILENT_LIVENESS,静默活体检测,暂未支持)- 2(NOT_LIVENESS,非活体) |
| mPixelMap | image.PixelMap | 是 | 是 | 检测成功后返回的最具有活体特征的图片(如包含人脸关键点的特征图),检测失败时无此数据。 |
| securedImageBuffer | ArrayBuffer | 是 | 是 | 安全摄像头场景下返回的安全流数据(加密后的图像特征数据),非安全场景无此数据。 |
| certificate | Array | 是 | 是 | 安全摄像头场景下返回的证书链(用于验证安全流的合法性),非安全场景无此数据。 |
let successResult = interactiveLiveness.getInteractiveLivenessResult();
successResult.then(data => {hilog.info(0x0001, "LivenessCollectionIndex", `Succeeded in detecting.`);
}).catch((err: BusinessError) => {hilog.error(0x0001, "LivenessCollectionIndex", `Failed to detect. Code:${err.code},message:${err.message}`);
})
三、DEMO源码示例
import { interactiveLiveness } from '@kit.VisionKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { abilityAccessCtrl, common } from '@kit.AbilityKit';
struct FaceLivenessDemo { userGrant: boolean = false // 权限状态 detectionResult: string = "" // 检测结果展示 actionCount: interactiveLiveness.ActionsNumber = interactiveLiveness.ActionsNumber.THREE_ACTION; // 动作数量(3或4) speechEnabled: boolean = true // 语音播报开关// 表示人脸活体检测完成后使用router.back返回到上一页。 routeMode: interactiveLiveness.RouteRedirectionMode = interactiveLiveness.RouteRedirectionMode.BACK_MODE; // 跳转模式// 权限申请逻辑private async requestPermissions() {const context = getContext() as common.UIAbilityContext;const atManager = abilityAccessCtrl.createAtManager();const results = await atManager.requestPermissionsFromUser(context, ["ohos.permission.CAMERA"]);this.userGrant = results.authResults.every(status => status === 0);}// 检测配置生成private generateDetectionConfig(): interactiveLiveness.InteractiveLivenessConfig {return {// 表示的是人脸活体检测模式,默认动作活体检测模式。// INTERACTIVE_MODE表示动作活体检测模式。isSilentMode: interactiveLiveness.DetectionMode.INTERACTIVE_MODE,// 表示动作活体检测的动作数量,数量范围3或4个,默认3个动作。随机生成,规则如下://// 当actionsNum=3时,[眨眼,注视]组合中的动作元素不会同时存在并且相邻的动作元素不会相同。//// 当actionsNum=4时,眨眼动作元素有且仅有1次,注视动作元素最多出现1次,[眨眼,注视]组合中的动作元素不会相邻,相邻的动作元素不会相同。//// 该参数只有当isSilentMode是INTERACTIVE_MODE的时候有效。actionsNum: this.actionCount,// 表示人脸活体检测成功后跳转的页面路径。如果不填,系统有默认的检测成功页面。// successfulRouteUrl: "pages/result/success", // 自定义成功跳转路径(需提前创建页面)// 表示人脸活体检测失败后跳转的页面路径。如果不填,系统有默认的检测失败页面。// failedRouteUrl: "pages/result/fail", // 自定义失败跳转路径(需提前创建页面)routeMode: this.routeMode, // 跳转模式// 语音播报的开关。//// true表示开启语音播报。// false表示关闭语音播报。// 默认开启语音播报。speechSwitch: this.speechEnabled, // 语音播报控制// 挑战值。仅用于安全摄像头场景(对应initializeAttestContext方法中的“userData”字段)的活体检测。//// 使用安全摄像头场景的前提需要开通Device Security服务。//// 长度范围是16-128之间(challenge传空或者undefined表示不使用安全摄像头)。// challenge: "自定义挑战值1234567890abcdef", // 安全摄像头场景可选// 是否设置隐私模式。//// true:设置隐私模式。// false:不设置隐私模式。// 默认值为false。// isPrivacyMode: true // 隐私模式需额外权限 当设置隐私模式时,需要申请ohos.permission.PRIVACY_WINDOW权限。};}// 启动检测private async startDetection() {if (!this.userGrant) {this.detectionResult = "请先申请相机权限";return;}const config = this.generateDetectionConfig();try {const jumpSuccess = await interactiveLiveness.startLivenessDetection(config);if (jumpSuccess) {hilog.info(0x0001, "Detection", "跳转检测页面成功");// 检测完成后获取结果(需在返回页面时调用)const result = await interactiveLiveness.getInteractiveLivenessResult();this.processResult(result);}} catch (err) {const error = err as BusinessError;hilog.error(0x0001, "Detection", `检测失败: 错误码${error.code}, 信息${error.message}`);this.detectionResult = `检测异常:错误码${error.code}`;}}// 结果处理private processResult(result: interactiveLiveness.InteractiveLivenessResult) {let status = "";let livenessType = result.livenessType;switch (livenessType) {case 0: // 动作活体检测成功status = "活体检测通过";// 可在此处处理特征图片或安全数据break;case 2: // 非活体status = "检测到非活体(照片/视频攻击)";break;default:status = "检测结果异常";}this.detectionResult = status;}build() {Column({ space: 40 }){// 权限申请按钮Button(this.userGrant ? "权限已授权" : "申请相机权限").fontSize(18).margin(10).padding(12).backgroundColor(this.userGrant ? Color.Green : Color.Blue).onClick(() => this.requestPermissions())// 动作数量选择Row({ space: 20 }) {Text("动作数量:").fontSize(16)Button("3个动作").backgroundColor(this.actionCount === 3 ? Color.Blue : Color.White).border({ width: 1, color: Color.Gray }).onClick(() => this.actionCount = 3)Button("4个动作").backgroundColor(this.actionCount === 4 ? Color.Blue : Color.White).border({ width: 1, color: Color.Gray }).onClick(() => this.actionCount = 4)}// 语音播报开关Toggle({ type: ToggleType.Checkbox, isOn: this.speechEnabled }).onChange((isOn: boolean)=>{this.speechEnabled = isOn;})// 跳转模式选择Row({ space: 20 }) {Text("跳转模式:").fontSize(16)Button("替换页面").backgroundColor(this.routeMode === "replace" ? Color.Blue : Color.White).border({ width: 1, color: Color.Gray }).onClick(() => {this.routeMode = interactiveLiveness.RouteRedirectionMode.REPLACE_MODE;})Button("返回上页").backgroundColor(this.routeMode === "back" ? Color.Blue : Color.White).border({ width: 1, color: Color.Gray }).onClick(() => {this.routeMode = interactiveLiveness.RouteRedirectionMode.BACK_MODE;})}// 启动检测按钮Button("开始人脸活体检测").fontSize(20).padding(16).backgroundColor(Color.Orange).onClick(() => this.startDetection())// 结果显示Text(this.detectionResult).fontSize(16).margin({top: 30}).foregroundColor(this.detectionResult.includes("通过") ? Color.Green : Color.Red)}.width("100%").height("100%").justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center)}
}
注意:
1. 人脸活体检测支持两种模式
INTERACTIVE_MODE(动作活体检测):默认模式,需用户完成 3 或 4 个随机动作(如眨眼、点头等),通过动作组合验证活体,规则限制避免相邻动作重复或特定组合(如眨眼和注视不相邻)。
SILENT_MODE(静默活体检测):暂未支持,无需用户做动作,通过其他技术(如微表情、光线反射)检测活体。
2. 配置人脸活体检测的动作数量和跳转逻辑
通过InteractiveLivenessConfig中的actionsNum配置,可选值为 3(默认)或 4,3 个动作时(眨眼,注视) 不同时存在且不相邻,4 个动作时眨眼仅 1 次,注视最多 1 次。
通过routeMode配置跳转模式(BACK_MODE 返回上一页或 REPLACE_MODE 替换跳转,默认 REPLACE_MODE)。
successfulRouteUrl和failedRouteUrl设置成功 / 失败后的自定义跳转路径(未填则用系统默认页面)。
3. 常见错误及处理:
201(Permission denied):未申请ohos.permission.CAMERA权限
1008301002(Route switching failed):路由配置错误,检查successfulRouteUrl/failedRouteUrl路径是否正确,或routeMode是否与页面路由匹配。
1008302000-1008302004(检测相关错误):检测过程中算法初始化失败、超时或动作不符合规则,可通过回调或 Promise 的 catch 捕获错误码,提示用户重新检测并检查动作合规性。
相关文章:
【HarmonyOS 5】VisionKit人脸活体检测详解
【HarmonyOS 5】VisionKit人脸活体检测详解 一、VisionKit人脸活体检测是什么? VisionKit是HamronyOS提供的场景化视觉服务工具包。 华为将常见的解决方案,通常需要三方应用使用SDK进行集成。华为以Kit的形式集成在HarmoyOS系统中,方便三方…...
Pycharm(九)函数的闭包、装饰器
目录 一、函数参数 二、闭包 三、装饰器 一、函数参数 def func01():print("func01 shows as follows") func01() # 函数名存放的是函数所在空间的地址 print(func01)#<function func01 at 0x0000023BA9FC04A0> func02func01 print(func02)#<function f…...
【深度学习】详解矩阵乘法、点积,内积,外积、哈达玛积极其应用|tensor系列02
博主简介:努力学习的22级计算机科学与技术本科生一枚🌸博主主页: Yaoyao2024往期回顾:【深度学习】你真的理解张量了吗?|标量、向量、矩阵、张量的秩|01每日一言🌼: “脑袋想不明白的,就用脚想”…...
MH2103系列coremark1.0跑分数据和优化,及基于arm2d的优化应用
CoreMark 1.0 介绍 CoreMark 是由 EEMBC(Embedded Microprocessor Benchmark Consortium)组织于 2009 年推出的一款用于衡量嵌入式系统 CPU 或 MCU 性能的标准基准测试工具。它旨在替代陈旧的 Dhrystone 标准(Dhrystone 容易受到各种libc不同…...
Flowith AI,解锁下一代「知识交易市场」
前言 最近几周自媒体号都在疯狂推Manus,看了几篇测评后,突然在某个时间节点,在特工的文章下,发现了很小众的Flowith。 被这段评论给心动到,于是先去注册了下账号。一翻探索过后,发现比我想象中要有趣的多&…...
策略模式:优雅应对多变的业务需求
一、策略模式基础概念 策略模式(Strategy Pattern) 是一种行为型设计模式,它通过定义一系列可互换的算法族,并将每个算法封装成独立的策略类,使得算法可以独立于使用它的客户端变化。策略模式的核心思想是 “将算法的…...
SpringBoot企业级开发之【文章分类-新增文章分类】
看一下新增文章的需求: 接口文档: 开发思路: 先在controller下去创建add方法,方法内导入Service类获取add的结果;再在Service接口下去创建add的方法;然后在Service实现类下去实现方法的作用,且导…...
【AI News | 20250421】每日AI进展
AI Repos 1、langgraph-mcp-agents 基于LangGraph的AI智能体系统,集成了MCP,使AI助手能访问各种数据源和API。提供了Streamlit网页界面,方便与LangGraph和MCP工具交互。可以通过界面动态添加、删除以及配置MCP工具,无需重启应用&…...
牛客 | OJ在线编程常见输入输出练习
1.只有输出 言归正传,本张试卷总共包括18个题目,包括了笔试情况下的各种输入输出。 第一题不需要输入,仅需输出字符串 Hello Nowcoder! 即可通过。 #include <iostream> using namespace std; int main(){string s "Hello Nowco…...
python生成动态库在c++中调用
一.Windows下生成动态库.pyd 在setup.py的同目录下使用python setup.py build_ext --inplace 二.在vscode的c中使用.pyd文件(动态库) 1)配置python的环境 python -c "import sys; print(sys.executable)" #确定python安装位置 2…...
程序员学商务英文之Terms of Payment Packing
Dia-3: Packing 1 包装-1 1. I’m here to improve my communication skill of English. 我来这里是为了提升我的英文沟通技能。 2. What a co-incidence! Fancy meeting you here. 这么巧!真没想到在这见到你。 3. Some birds aren’t meant to be caged…...
OpenCV基础函数学习4
【大纲笔记见附件pdf】 目录 一、基于OpenCV的形态学操作 二、基于OpenCV的直方图处理 三、基于OpenCV霍夫变换 四、基于OpenCV模板匹配 一、基于OpenCV的形态学操作 二、基于OpenCV的直方图处理 三、基于OpenCV霍夫变换 四、基于OpenCV模板匹配...
Nginx反向代理用自定义Header参数
【啰嗦两句】 也不知道为啥,我仅仅想在Nginx的反向代理中使用自己定义的“x-api-key”做Header参数,却发现会被忽略,网上搜的资料都是说用“proxy_set_header”,却只愿意介绍最基本的几个参数,你懂的,那些资…...
详解机器学习各算法的优缺点!!
在机器学习这个 “工具库” 里,算法就像各种各样的工具,每一种都有自己的 “脾气” 和 “特长”。有些算法擅长找规律,有些算法能快速分类,还有些在处理复杂数据时特别厉害。 而且,就像锤子适合敲钉子、螺丝刀适合拧螺…...
Manus AI与多语言手写识别
一、手写识别技术的发展历程 1.1 早期的手写识别技术 手写识别技术起源很早,1929年德国人Tausheck就取得了相关专利。早期主要采用模板匹配等方法,该方法需准备字符模板库,提取待识别字符特征后进行匹配。但其局限性明显,对字符…...
C++23 让 Lambda 表达式中的 () 更可选:P1102R2 提案深度解析
文章目录 一、背景与动机:Lambda 表达式中的痛点1.1 问题的根源 二、P1102R2 提案:让 () 可选2.1 提案的核心内容2.2 语法调整的细节2.3 提案的合理性 三、编译器支持:主流编译器的跟进四、对 C 编程的影响:简化语法与提升一致性4…...
规则引擎 - Easy Rules
Easy Rules 依赖demodemo1demo2 总结 Easy Rules 是一个轻量级的 Java 规则引擎,使用简单,适合快速开发和简单的规则场景,适合对于一些判断,是否属于白名单,是否有特殊权限,是否属于当前区域,调…...
3步拆解Linux内核源码的思维模型
3步拆解Linux内核源码的思维模型 ——从“不敢碰”到“庖丁解牛” 一、第一步:资料收集与框架搭建——像拼图一样找到“地图” 初看Linux内核源码的人,往往会被其千万行代码淹没。但正如登山前需要地形图,阅读内核前必须构建认知框架。 1…...
MyBatis与MyBatis-Plus:字段自动填充的两种实现方式
目录 1. 使用 MyBatis 拦截器实现字段自动填充 2. 使用 MyBatis-Plus 实现字段自动填充 1. 使用 MyBatis 拦截器实现字段自动填充 实现步骤 创建拦截器 实现 MyBatis 的 Interceptor 接口,通过拦截 MyBatis 执行的 SQL 操作来自动填充公共字段 Intercepts({Signa…...
深度学习:人工智能的核心驱动力
深度学习 在当今科技飞速发展的时代,人工智能(AI)无疑是最具影响力和变革性的技术之一。而深度学习,作为人工智能领域的核心技术,正以其强大的能力和广泛的应用,深刻地改变着我们的生活和世界。深度学习究竟…...
Java学习路线--自用--带链接
1.Java基础 黑马:黑马程序员Java零基础视频教程_下部 2.MySQL 尚硅谷:MySQL数据库入门到大牛,mysql安装到优化,百科全书级,全网天花板 3.Redis 黑马:黑马程序员Redis入门到实战教程,深度透…...
在Qt中验证LDAP账户(Windows平台)
一、前言 原本以为在Qt(Windows平台)中验证 LDAP 账户很简单:集成Open LDAP的开发库即可。结果临了才发现,Open LDAP压根儿不支持Windows平台。沿着重用的原则,考虑迁移Open LDAP的源代码,却发现工作量不小…...
【sylar-webserver】重构日志系统
文章目录 主要工作流程图FiberConditionBufferBufferManagerLogEvent 序列化 & 反序列化LoggerRotatingFileLogAppender 主要工作 实现, LogEvent 序列化和反序列化 (使用序列化是为了更标准,如果转成最终的日志格式再存储(确…...
树莓派超全系列教程文档--(38)config.txt视频配置
config.txt视频配置 视频选项HDMI模式树莓派4-系列的HDMI树莓派5-系列的HDMI 复合视频模式enable_tvout LCD显示器和触摸屏ignore_lcddisable_touchscreen 通用显示选项disable_fw_kms_setup 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 视频选…...
线性DP:最短编辑距离
Dp 状态表示 f(i,j) 集合所有将A[1~i]变成B[1~j]的操作方式属性min 状态计算 (划分) 增f(i,j)f(i,j-1)1//A[i]元素要增加,说明A前i位置与B前j-1相同删f(i,j)f(i-1,j)1//A[i]元素要删除,说明A前i…...
STM32 HAL库FreeRTOS 中断管理
一、引言 在嵌入式系统开发中,STM32 微控制器凭借其高性能、低功耗和丰富的外设资源,被广泛应用于各种领域。FreeRTOS 作为一款轻量级、开源且功能强大的实时操作系统,为多任务处理提供了良好的支持。中断是嵌入式系统中实现实时响应外部事件…...
STM32——新建工程并使用寄存器以及库函数进行点灯
本文是根据江协科技提供的教学视频所写,旨在便于日后复习,同时供学习嵌入式的朋友们参考,文中涉及到的所有资料也均来源于江协科技(资料下载)。 新建工程并使用寄存器以及库函数进行点灯操作 新建工程步骤1.建立工程2.…...
java集合框架day1————集合体系介绍
在进入正文之前,我们先来思考一下之前学过的数组有什么缺点? <1>长度开始时必须指定,而且一旦指定,不能更改 <2>保存的必须为同一类型的元素 <3>使用数组进行增加/删除元素的代码比较麻烦 为了方便读者理解&…...
百度热力图数据获取,原理,处理及论文应用18
目录 0、数据简介0、示例数据1、百度热力图数据日期如何选择1.1、其他实验数据的时间1.2、看日历天气 2、百度热力图几天够研究?部分文章统计3、数据原理3.1 Bd09mc即百度墨卡托投影坐标系200单位的距离是可以自己设置的吗?3.2 csv文件字段说明3.3 ** 这…...
【区块链技术解析】从原理到实践的全链路指南
目录 前言:技术背景与价值当前技术痛点解决方案概述目标读者说明 一、技术原理剖析核心概念图解核心作用讲解关键技术模块技术选型对比 二、实战演示环境配置要求核心代码实现(10个案例)案例1:创建简单区块链案例2:工作…...
