news 2026/4/15 20:08:48

鸿蒙实现自定义类似活体检测功能

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
鸿蒙实现自定义类似活体检测功能

一.背景

目前需要实现活体检测功能,而且是需要静默活体,但是现在官方的活体API还不支持静默,第三方的SDK也不支持,现在自定义一个类似活体检测的功能,但是不会去检测是否活体,拿到照片以后去调用人脸识别

二.实现思路

先调用相机,将相机设置为前置摄像头,将当前相机内容使用XComponent实时渲染,启用定时拍照功能,设置定时器,时间到以后利用截图组件功能去做,然后拿到图片地址去进行人脸识别,不保存到本地

三.代码

这边只放了首页代码,其余代码会在包里,在文章后附带

使用的时候将包放到项目中,直接跳转或者引用xsComponent这个页面

/* * Copyright (c) 2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ import { CameraConstants } from './constants/CameraConstants'; import { CameraUtils } from './utils/CameraUtils'; import { abilityAccessCtrl, bundleManager, common, PermissionRequestResult, Permissions } from '@kit.AbilityKit'; import { BusinessError, emitter } from '@kit.BasicServicesKit'; import Logger from './utils/Logger'; import { TwiceReqPermissionButtonComponent } from './component/TwiceReqPermissionButtonComponent'; import { StackXComponent } from './component/StackXComponent'; import LoadingDialog from '@lyb/loading-dialog'; import { DynamicsRouter } from 'common'; @Builder export function xsIndexBuilder() { xsIndex() } @Entry @Component struct xsIndex { @Provide cameraPosition: number = 1; // 固定为前置摄像头 @Provide notHasPermission: boolean = true; @Provide surfaceId: string = ''; @Provide timerShooting: number = 3; // 固定3秒 @Provide captureTimer: number = 0; @Provide isVisibleTimerSet: boolean = false; @Provide isVisibleTimer: boolean = false; @Provide isVisibleCapture: boolean = true; @Provide captureClickFlag: number = 0; @State autoCaptureStarted: boolean = false; // 标记是否已开始自动拍照 private uiContext: UIContext = this.getUIContext(); private cameraUtils = new CameraUtils(this.uiContext); checkPermissions(permission: Permissions) { let atManager = abilityAccessCtrl.createAtManager(); let bundleInfo = bundleManager.getBundleInfoForSelfSync(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION); let tokenID = bundleInfo.appInfo.accessTokenId; let authResults = atManager.checkAccessTokenSync(tokenID, permission); return authResults === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED; } aboutToDisappear(): void { this.cameraUtils.releaseCamera(); } AppStorage.setOrCreate('cameraUtils', this.cameraUtils); let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager(); let context: Context = this.getUIContext().getHostContext() as common.UIAbilityContext; atManager.requestPermissionsFromUser(context, ['ohos.permission.CAMERA']) .then((data: PermissionRequestResult) => { if (data.authResults[0] === 0) { this.notHasPermission = false; this.cameraUtils.cameraShooting(this.cameraPosition, this.surfaceId, context); // 延迟启动自动拍照,等待相机初始化完成 setTimeout(() => { this.startAutoCapture(); }, 500); } else if (data.authResults[0] === -1) { this.notHasPermission = true; } }) .catch((err: BusinessError) => { Logger.error(`data: ${JSON.stringify(err)}`); }); } // 开始自动拍照流程 startAutoCapture(): void { if (this.autoCaptureStarted || this.notHasPermission) { return; } this.autoCaptureStarted = true; this.isVisibleTimer = true; this.captureTimer = this.timerShooting; this.isVisibleCapture = false; // 3秒后自动拍照 setTimeout(() => { this.cameraUtils.capture(true); // 前置摄像头需要镜像 this.captureClickFlag = this.captureClickFlag + 1; this.isVisibleCapture = true; this.isVisibleTimer = false; }, this.captureTimer * 1000); } onPageShow() { if (!this.notHasPermission) { let permissions: Permissions = 'ohos.permission.CAMERA'; if (this.checkPermissions(permissions)) { this.cameraUtils.cameraShooting(this.cameraPosition, this.surfaceId, this.getUIContext().getHostContext()!); this.notHasPermission = false; // 如果还没有开始自动拍照,则启动 if (!this.autoCaptureStarted) { setTimeout(() => { this.startAutoCapture(); }, 500); } } else { this.notHasPermission = true; } } } onPageHide(): void { if (!this.notHasPermission) { this.cameraUtils.releaseCamera(); } } build() { NavDestination() { Column() { if (this.notHasPermission) { TwiceReqPermissionButtonComponent(); } else { Row() { Image($r('app.media.back')) .width(25) .height(25) .onClick(() => { DynamicsRouter.pop() }) }.width('100%').padding(15) StackXComponent(); } } .height(CameraConstants.FULL_SCREEN) .width(CameraConstants.FULL_SCREEN) .backgroundColor(Color.White) // 白色背景 .padding({ top: this.uiContext.px2vp(AppStorage.get('topAvoid')) as number, bottom: this.uiContext.px2vp(AppStorage.get('bottomAvoid')) as number }); }.hideBackButton(true) } }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/16 10:40:56

自动驾驶能 “自主判断”?答案藏在 GPU 服务器里

当部分城市的指定路段出现能自主应对拥堵或高速场景的 L3 级自动驾驶车辆时,不少人好奇:这些车如何精准跟车、避让障碍?其实,让车辆拥有 “判断力” 的关键,不是车载传感器或芯片,而是云端的 GPU 服务器 —…

作者头像 李华
网站建设 2026/4/15 15:05:55

STM8S103F3最小系统板设计与实践全流程学习心得

作为电子信息专业的学生,在嵌入式系统课程的学习中,我深刻意识到理论知识与实践操作之间的差距。为了巩固STM8系列单片机的相关知识,我独立完成了STM8S103F3最小系统板的设计、焊接与调试工作。从新建工程项目到PCB文件输出,每一个…

作者头像 李华
网站建设 2026/4/16 15:25:20

HunyuanVideo-Foley:高保真视频拟音生成模型

HunyuanVideo-Foley:高保真视频拟音生成模型 在影视剪辑室里,一位音效师正反复调整脚步声的节奏——为了匹配角色走过木地板的画面,他需要精确到帧地对齐每一步落地的瞬间。这样的工作往往耗时数小时,只为几秒的真实感。而在AI生…

作者头像 李华
网站建设 2026/4/16 13:54:51

2342341

4324324324434324243244324423444334344E324

作者头像 李华
网站建设 2026/4/15 11:00:12

1. 网络安全求职秘籍:从漏洞挖掘到应急响应,新手到大神的通关手册

【收藏必备】网络安全面试宝典:从OWASP到内网渗透,小白到专家的进阶指南 本文全面整理网络安全面试题,涵盖HVV、OWASP Top 10漏洞原理与修复方法。详细讲解内网渗透技术、权限维持方法、Windows/Linux系统提权技巧,以及渗透测试流…

作者头像 李华
网站建设 2026/4/16 10:45:31

Seed-Coder-8B-Base生成GraphQL Schema实战测评

Seed-Coder-8B-Base生成GraphQL Schema实战测评 在现代全栈开发中,前后端协作的效率瓶颈往往不在于编码速度,而在于接口契约的模糊性。一个字段该不该返回?是否可为空?数组会不会是null?这些看似细枝末节的问题&#x…

作者头像 李华