动态

详情 返回 返回

鴻蒙 NEXT開發中輕鬆實現人臉識別功能 - 动态 详情

>大家好,我是 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<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中配置權限。

### **四、注意事項**
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://files.mdnice.com/user/57732/2f80e74d-cd64-4f9c-b763-38ddf26899b5.png)

 

Add a new 评论

Some HTML is okay.