|
>大家好,我是 V 哥。 今天给大家介绍在 HarmonyOS 原生鸿蒙开发中,实现人脸识别功能,这个功能在常用的 APP 开发中上镜率还是很高的,在传统的 Android 或 iOS 开发中,通常我们要借助第三方库来实现,而在鸿蒙原生开发中,天然的集成了这个功能,使用起来也超级方便,接下来听 V 哥细细说来。
在鸿蒙 NEXT 中实现人脸识别功能,可通过 **CoreVision Kit** 的 **FaceDetector** 模块实现。以下是基于 API 12+ 的实现流程及核心代码示例:
---
### **一、开发准备** 1. **配置权限** 在 `module.json5` 中添加以下权限: ```json "requestPermissions": [ { "name": "ohos.permission.READ_MEDIA" }, // 读取图片权限 { "name": "ohos.permission.CAMERA" }, // 相机权限 { "name": "ohos.permission.ACCESS_BIOMETRIC" } // 生物认证权限 ] ```
2. **导入依赖** 使用鸿蒙 NEXT 的视觉服务接口: ```typescript import { faceDetector } from '@kit.CoreVisionKit'; import image from '@kit.ImageKit'; // 图像处理模块 ```
---
### **二、核心实现步骤**
****1. 初始化人脸检测器**** ```typescript // 初始化参数配置 let faceDetectConfig: faceDetector.FaceDetectOptions = { maxFaceNum: 5, // 最大检测人脸数 featureLevel: faceDetector.FeatureLevel.TYPE_FULL, // 检测全部特征 algorithmMode: faceDetector.AlgorithmMode.TYPE_MODE_ACCURATE // 高精度模式 };
// 创建检测器实例 let detector = faceDetector.createFaceDetector(faceDetectConfig); ```
****2. 获取图像数据**** 通过相机或相册获取图像,转换为 `PixelMap` 格式: ```typescript // 示例:从相册选择图片并转换为 PixelMap async function getImagePixelMap() { let imageSource = image.createImageSource(selectedImageUri); let decodeOptions = { desiredSize: { width: 1024, height: 1024 } // 调整尺寸优化性能 }; let pixelMap = await imageSource.createPixelMap(decodeOptions); return pixelMap; } ```
****3. 执行人脸检测**** ```typescript async function detectFaces(pixelMap: image.PixelMap) { try { // 执行检测 let faces: faceDetector.Face[] = await detector.detect(pixelMap); // 处理检测结果 faces.forEach((face: faceDetector.Face) => { console.log("人脸置信度: " + face.confidence); console.log("人脸坐标框: " + JSON.stringify(face.rect)); console.log("五官坐标点: " + JSON.stringify(face.landmarks)); }); } catch (error) { console.error("人脸检测失败: " + error.code + ", 信息: " + error.message); } } ```
****4. 身份验证集成****
结合生物认证接口验证机主身份: ```typescript import userAuth from '@kit.BiometricAuthenticationKit';
// 检查是否支持人脸识别 let status = userAuth.getAvailableStatus( userAuth.UserAuthType.FACE, userAuth.AuthTrustLevel.ATL3 ); if (status.isAvailable) { // 执行人脸认证 userAuth.executeAuth( userAuth.UserAuthType.FACE, userAuth.AuthTrustLevel.ATL3, (err, result) => { if (result?.result === userAuth.AuthResult.SUCCESS) { console.log("身份验证通过"); } } ); } ```
### **三、以下是一个完整示例代码**
1. Index.ets 主页面(示例代码是使用元服务项目实现)
``` typescript import { authentication } from '@kit.AccountKit'; import { BusinessError } from '@kit.BasicServicesKit'; import { hilog } from '@kit.PerformanceAnalysisKit';
const DOMAIN = 0x0000;
export const pathStack: NavPathStack = new NavPathStack();
@Entry @ComponentV2 struct Index { build() { Navigation(pathStack) { Column({ space: 20 }) { Button("人脸活体检测-示例") .width("80%") .borderRadius(10) .onClick(() => { pathStack.pushPath({ name: "live" }) }) } .height('100%') .width('100%') } .title("元服务") }
aboutToAppear() { hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate'); this.loginWithHuaweiID(); }
/** * Sample code for using HUAWEI ID to log in to atomic service. * According to the Atomic Service Review Guide, when a atomic service has an account system, * the option to log in with a HUAWEI ID must be provided. * The following presets the atomic service to use the HUAWEI ID silent login function. * To enable the atomic service to log in successfully using the HUAWEI ID, please refer * to the HarmonyOS HUAWEI ID Access Guide to configure the client ID and fingerprint certificate. */ private loginWithHuaweiID() { // Create a login request and set parameters const loginRequest = new authentication.HuaweiIDProvider().createLoginWithHuaweiIDRequest(); // Whether to forcibly launch the HUAWEI ID login page when the user is not logged in with the HUAWEI ID loginRequest.forceLogin = false; // Execute login request const controller = new authentication.AuthenticationController(); controller.executeRequest(loginRequest).then((data) => { const loginWithHuaweiIDResponse = data as authentication.LoginWithHuaweiIDResponse; const authCode = loginWithHuaweiIDResponse.data?.authorizationCode; // Send authCode to the backend in exchange for unionID, session
}).catch((error: BusinessError) => { hilog.error(DOMAIN, 'testTag', 'error: %{public}s', JSON.stringify(error)); if (error.code === authentication.AuthenticationErrorCode.ACCOUNT_NOT_LOGGED_IN) { // HUAWEI ID is not logged in, it is recommended to jump to the login guide page
} }); } } ```
2. LiveDetectPage.ets 页面 ```typescript import { common, abilityAccessCtrl, Permissions } from '@kit.AbilityKit'; import { interactiveLiveness } from '@kit.VisionKit'; import { BusinessError } from '@kit.BasicServicesKit'; import { hilog } from '@kit.PerformanceAnalysisKit'; @Builder export function buildPage(){ LiveDetectPage() } @Component export struct LiveDetectPage { private context: common.UIAbilityContext = this.getUIContext().getHostContext() as common.UIAbilityContext; // 权限 private array: Array< ermissions> = ["ohos.permission.CAMERA"]; // 动作个数 @State actionsNum: number = 0; /** * 是否是静默模式 * 静默模式(SILENT_MODE):表示静默活体检测模式,暂未支持。 * 交互模式(INTERACTIVE_MODE):表示动作活体检测模式。 */ @State isSilentMode: string = "INTERACTIVE_MODE"; // 验证完的跳转模式 @State routeMode: string = "replace"; // 验证结果 @State resultInfo: interactiveLiveness.InteractiveLivenessResult = { livenessType: 0 }; // 验证失败结果 @State failResult: Record<string, number | string> = { "code": 1008302000, "message": "" };
build() { NavDestination() { // 层叠布局 Stack({ // 内容对齐方式:顶部对齐 alignContent: Alignment.Top }) { // 列容器组件 Column() { // 行容器组件 Row() { // 弹性布局:主轴方向为横向,内容对齐方式为起始对齐,垂直方向对齐方式为居中对齐 Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) { // 文本显示组件 Text("验证完的跳转模式:").fontSize(18).width("25%") // 弹性布局:主轴方向为横向,内容对齐方式为起始对齐,垂直方向居中对齐 Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) { // 行容器组件 Row() { // 单选框组件 Radio({ value: "replace", group: "routeMode" }).checked(true).height(24).width(24) .onChange((isChecked: boolean) => { this.routeMode = "replace" }) Text("replace").fontSize(16) }.margin({ right: 15 })
Row() { // 单选框组件 Radio({ value: "back", group: "routeMode" }).checked(false).height(24).width(24) .onChange((isChecked: boolean) => { this.routeMode = "back"; }) Text("back").fontSize(16) } }.width("75%") } }.margin({ bottom: 30 })
// 行容器组件 Row() { // 弹性布局:主轴方向为横向,内容对齐方式为起始对齐,垂直方向对齐方式为居中对齐 Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) { Text("动作数量:").fontSize(18).width("25%") TextInput({ placeholder: this.actionsNum != 0 ? this.actionsNum.toString() : "动作数量为3或4个" }).type(InputType.Number).placeholderFont({ size: 18, weight: FontWeight.Normal, family: "HarmonyHeiTi", style: FontStyle.Normal }).fontSize(18).fontWeight(FontWeight.Bold).fontFamily("HarmonyHeiTi") .fontStyle(FontStyle.Normal).width("65%").onChange((value: string) => { this.actionsNum = Number(value) as interactiveLiveness.ActionsNumber; }) } } }.margin({ left: 24, top: 80 }).zIndex(1)
// 层叠布局组件:内容对齐方式为底部对齐 Stack({ alignContent: Alignment.Bottom }) { if (this.resultInfo?.mPixelMap) { // 如果存在mPixelMap,则显示检测的图片 Image(this.resultInfo?.mPixelMap).width(260) .height(260).align(Alignment.Center) .margin({ bottom: 260 }) // 圆形遮罩 Circle().width(300).height(300).fillOpacity(0) .strokeWidth(60).stroke(Color.White) .margin({ bottom: 250, left: 0 }) }
// 判断检测成功还是失败 Text(this.resultInfo.mPixelMap ? "检测成功" : this.failResult.code != 1008302000 ? "检测失败" : "") .width("100%").height(26).fontSize(20).fontColor("#000000").fontFamily("HarmonyHeiTi") .margin({ top: 50 }).textAlign(TextAlign.Center).fontWeight("Medium").margin({ bottom: 240 })
// 如果检测失败,则显示检测失败的原因 if(this.failResult.code != 1008302000) { Text(this.failResult.message as string) .width("100%").height(26) .textAlign(TextAlign.Center).fontFamily("HarmonyHeiTi").fontWeight("Medium") .margin({ bottom: 200 }) }
// 开始检测的按钮 Button("开始检测").type(ButtonType.Normal).borderRadius(10) .width('60%').height(40).fontSize(16) .margin({ bottom: 56 }) .onClick(() => { this.privateStartDetection(); }) }.height("100%") } }.title('活体检测') .onWillShow(() => { // 释放结果 this.resultRelease(); // 获取检测的结果 this.getDetectionResultInfo(); }) }
// 跳转到人脸活体检测控件 private privateRouterLibrary() { // 交互式活体检测配置实例 let routerOptions: interactiveLiveness.InteractiveLivenessConfig = { // 是否是静默模式 isSilentMode: this.isSilentMode as interactiveLiveness.DetectionMode, // 路由模式:返回还是替换 routeMode: this.routeMode as interactiveLiveness.RouteRedirectionMode, // 动作个数 actionsNum: this.actionsNum }
// 如果可以使用该能力(活体检测能力) // syscap配置 if (canIUse("SystemCapability.AI.Component.LivenessDetect")) { // 开始活体检测 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}`); }) } else { // 如果不可以使用该能力(活体检测能力),则显示不支持该能力的提示 hilog.error(0x0001, "LivenessCollectionIndex", '当前设备不支持活体检测API'); } }
/** * 返回从用户获取到的权限列表,遍历该列表,如果包含了ohos.permission.CAMERA权限,则调用privateRouterLibrary方法 */ private privateStartDetection() { abilityAccessCtrl.createAtManager().requestPermissionsFromUser(this.context, this.array).then((res) => { for (let i = 0; i < res.permissions.length; i++) { if (res.permissions === "ohos.permission.CAMERA" && res.authResults === 0) { this.privateRouterLibrary(); } } }).catch((err: BusinessError) => { hilog.error(0x0001, "LivenessCollectionIndex", `Failed to request permissions from user. Code is ${err.code}, message is ${err.message}`); }) }
/** * 获取检测的结果 */ private getDetectionResultInfo() { // getInteractiveLivenessResult接口调用完会释放资源 // 如果可以使用活体检测能力(syscap配置) if (canIUse("SystemCapability.AI.Component.LivenessDetect")) { // 获取活体检测结果 let resultInfo = interactiveLiveness.getInteractiveLivenessResult(); resultInfo.then(data => { // 获取到结果,则赋值 this.resultInfo = data; }).catch((err: BusinessError) => { // 如果发生了异常,则设置失败结果的字段值 this.failResult = { "code": err.code, "message": err.message } }) } else { // 当前设备不支持活体检测能力 hilog.error(0x0001, "LivenessCollectionIndex", '该设备不支持活体检测API。'); } }
/** * 结果重置 */ private resultRelease() { this.resultInfo = { livenessType: 0 } this.failResult = { "code": 1008302000, "message": "" } } } ```
注意,需要在module.json5中配置权限。
### **四、注意事项** 1. **真机调试** 需使用支持人脸识别的真机(如 P50 系列)测试,模拟器不支持)。 2. **性能优化** - 降低图像分辨率以提升检测速度。 - 使用 `AlgorithmMode.TYPE_MODE_FAST` 快速模式平衡性能与精度。 3. **特征比对** 进阶场景可通过 `FaceComparator` 比对两张人脸相似度。
---
### **五、扩展场景** - **活体检测**:通过 `VisionKit` 监测眨眼、转头动作。 - **暗光增强**:结合 `ImageKit` 调整图像亮度/对比度强化识别效果。
通过上述步骤,可快速实现基础人脸识别功能,并根据需求扩展至复杂场景。
--- ### **六、小结一下**
以上就是在鸿蒙 NEXT 开发中实现人脸识别功能,也称为活体检测,通过鸿蒙 NEXT 提供的能力,可以轻松实现,兄弟们,可以抓紧试试(请自备真机测试)。学习鸿蒙可以关注威哥写的《鸿蒙 HarmonyOS NEXT 开发之路》卷1,卷2已上市,卷3正在加紧印刷中。如果你还没有拿下鸿蒙认证,快到碗里来(https://developer.huawei.com/consumer/cn/training/classDetail/042cb1cc4d7d44ecbdbd902fd1275dcc)。

本文来自博客园,作者:威哥爱编程,转载请注明原文链接:https://www.cnblogs.com/finally-vince/p/19053652
来源:https://www.cnblogs.com/finally-vince/p/19053652 |