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