大家好,我是 V 哥。
今天給大家介紹在 HarmonyOS 原生鴻蒙開發中,實現人臉識別功能,這個功能在常用的 APP 開發中上鏡率還是很高的,在傳統的 Android 或 iOS 開發中,通常我們要借助第三方庫來實現,而在鴻蒙原生開發中,天然的集成了這個功能,使用起來也超級方便,接下來聽 V 哥細細說來。
在鴻蒙 NEXT 中實現人臉識別功能,可通過 CoreVision Kit 的 FaceDetector 模塊實現。以下是基于 API 12+ 的實現流程及核心代碼示例:
一、開發準備
- 配置權限
在module.json5
中添加以下權限:
"requestPermissions": [{ "name": "ohos.permission.READ_MEDIA" }, // 讀取圖片權限{ "name": "ohos.permission.CAMERA" }, // 相機權限{ "name": "ohos.permission.ACCESS_BIOMETRIC" } // 生物認證權限]
- 導入依賴
使用鴻蒙 NEXT 的視覺服務接口:
import { faceDetector } from '@kit.CoreVisionKit';import image from '@kit.ImageKit'; // 圖像處理模塊
二、核心實現步驟
1. 初始化人臉檢測器
// 初始化參數配置
let faceDetectConfig: faceDetector.FaceDetectOptions = {maxFaceNum: 5, // 最大檢測人臉數featureLevel: faceDetector.FeatureLevel.TYPE_FULL, // 檢測全部特征algorithmMode: faceDetector.AlgorithmMode.TYPE_MODE_ACCURATE // 高精度模式
};// 創建檢測器實例
let detector = faceDetector.createFaceDetector(faceDetectConfig);
2. 獲取圖像數據
通過相機或相冊獲取圖像,轉換為 PixelMap
格式:
// 示例:從相冊選擇圖片并轉換為 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. 執行人臉檢測
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. 身份驗證集成
結合生物認證接口驗證機主身份:
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("身份驗證通過");}});
}
三、以下是一個完整示例代碼
- Index.ets 主頁面(示例代碼是使用元服務項目實現)
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 parametersconst loginRequest = new authentication.HuaweiIDProvider().createLoginWithHuaweiIDRequest();// Whether to forcibly launch the HUAWEI ID login page when the user is not logged in with the HUAWEI IDloginRequest.forceLogin = false;// Execute login requestconst 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}});}
}
- LiveDetectPage.ets 頁面
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<Permissions> = ["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[i] === "ohos.permission.CAMERA" && res.authResults[i] === 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中配置權限。
四、注意事項
- 真機調試
需使用支持人臉識別的真機(如 P50 系列)測試,模擬器不支持)。 - 性能優化
- 降低圖像分辨率以提升檢測速度。
- 使用
AlgorithmMode.TYPE_MODE_FAST
快速模式平衡性能與精度。
- 特征比對
進階場景可通過FaceComparator
比對兩張人臉相似度。
五、擴展場景
- 活體檢測:通過
VisionKit
監測眨眼、轉頭動作。 - 暗光增強:結合
ImageKit
調整圖像亮度/對比度強化識別效果。
通過上述步驟,可快速實現基礎人臉識別功能,并根據需求擴展至復雜場景。
六、小結一下
以上就是在鴻蒙 NEXT 開發中實現人臉識別功能,也稱為活體檢測,通過鴻蒙 NEXT 提供的能力,可以輕松實現,兄弟們,可以抓緊試試(請自備真機測試)。學習鴻蒙可以關注威哥寫的《鴻蒙 HarmonyOS NEXT 開發之路》卷1,卷2已上市,卷3正在加緊印刷中。如果你還沒有拿下鴻蒙認證,快到碗里來(https://developer.huawei.com/consumer/cn/training/classDetail/042cb1cc4d7d44ecbdbd902fd1275dcc)。