效果演示图,右边的是人脸数据,可用来比对人脸
注意这里只有真机才能测试是否成功, 测试机型pce-w30
实现这个效果很简洁:打开相册、选取图片、打开文件、创建imageSource、创建PixelMap、喂给faceDetector拿到结果
在这里我简单封装了两个工具类方便后续使用,分别是:照片选择类、人脸识别类
大部分解读都写在注释里面了,供参考
// 引入必要的模块
import { faceDetector } from '@kit.CoreVisionKit'; // 引入人脸检测模块
import { promptAction } from '@kit.ArkUI'; // 引入UI提示模块
/**
* FaceDetectClass 类用于处理面部检测的逻辑
*/
export class FaceDetectClass {
// 静态属性,用于存储当前面部数据的JSON字符串
static faceDataStr: string = "";
/**
* 异步检测面部信息
* @param pixMap - 包含图像数据的PixelMap对象
* @returns 返回Promise,解析为面部数据的JSON字符串,或在失败时拒绝
*/
static async detectFace(pixMap: PixelMap): Promise<string> {
return new Promise<string>(async (resolve, reject) => {
try {
// 构造VisionInfo对象,包含待检测的图像数据
const visionInfo: faceDetector.VisionInfo = {
pixelMap: pixMap
};
// 调用人脸检测接口
const faceData = await faceDetector.detect(visionInfo);
// 检查是否检测到面部
if (faceData.length === 0) {
// 如果没有检测到面部,显示提示并拒绝Promise
promptAction.showToast({
message: "获取面部数据失败"
});
reject("未检测到面部");
} else {
// 将面部数据转换为JSON字符串
const faceJsonStr = JSON.stringify(faceData);
// 更新静态属性以存储当前面部数据
FaceDetectClass.faceDataStr = faceJsonStr;
// 解析Promise,返回面部数据的JSON字符串
resolve(faceJsonStr);
}
} catch (err) {
// 捕获并处理异常
promptAction.showToast({
message: `识别面部失败: ${err.message}`
});
reject(err); // 拒绝Promise,并传递错误对象
}
});
}
}
// 引入必要的模块
import { photoAccessHelper } from '@kit.MediaLibraryKit'; // 引入媒体库访问助手,用于选择照片
import { fileIo } from '@kit.CoreFileKit'; // 引入文件IO模块,用于文件操作
import { image } from '@kit.ImageKit'; // 引入图像处理模块,用于处理图像数据
/**
* PhotoPickerClass 类提供了选择照片和根据URI创建PixelMap的功能
*/
export class PhotoPickerClass {
// 静态属性,用于存储照片选择器实例
static photoPicker: photoAccessHelper.PhotoViewPicker = new photoAccessHelper.PhotoViewPicker();
/**
* 异步选择一张照片并返回其URI
* @returns 返回所选照片的URI
*/
static async selectImageUri() {
try {
// 调用照片选择器选择照片,限制为图像类型且最大选择数为1
const selectionResult = await PhotoPickerClass.photoPicker.select({
MIMEType: photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE, // 指定MIME类型为图像
maxSelectNumber: 1 // 设置最大选择数量为1
});
// 返回第一张照片的URI(因为maxSelectNumber为1,所以这里总是安全的)
return selectionResult.photoUris[0];
} catch (error) {
// 处理可能的错误,例如用户取消选择或发生其他错误
console.error('Failed to select image:', error);
// 重新抛出错误,以便调用者可以处理
return error.message
}
}
/**
* 根据提供的图片URI创建PixelMap对象
* @param imgUri 图片的URI
* @returns 返回创建的PixelMap对象
*/
static creatPixMapByUri(imgUri: string): Promise<PixelMap | undefined> {
return new Promise<PixelMap | undefined>((resolve, reject) => {
try {
// 以只读模式打开文件
const file = fileIo.openSync(imgUri, fileIo.OpenMode.READ_ONLY);
// 使用文件描述符创建图像源
const imgSource = image.createImageSource(file.fd);
// 从图像源同步创建PixelMap对象
const imgPixMap = imgSource.createPixelMapSync();
// 关闭文件(注意:在某些环境中,这可能不是必需的,因为createImageSource可能已接管文件)
if (imgSource) {
imgSource.release()
}
// 返回创建的PixelMap对象
resolve(imgPixMap);
} catch (error) {
// 处理可能的错误,例如文件不存在或无法读取
console.error('Failed to create PixelMap from URI:', imgUri, error);
reject("创建pixelMap错误" + error.message)
}
})
}
}
import { promptAction } from '@kit.ArkUI'
import { FaceDetectClass } from '../utils/FaceDetector'
import { PhotoPickerClass } from '../utils/PhotoPicker'
@Entry
@Component
struct Index {
@State currentUri: string = ""
@State dataValue: string = ""
@State testPixMap: PixelMap | undefined = undefined
@State cltData: string[] = []
aboutToDisappear(): void {
if (this.testPixMap) {
// 释放资源
this.testPixMap.release()
}
}
build() {
Row({ space: 15 }) {
// 选择图片部分
Column() {
Column() {
Image(this.currentUri)
.width(400)
.aspectRatio(1)
.objectFit(ImageFit.Contain)
}
.justifyContent(FlexAlign.Center)
.layoutWeight(1)
.width("100%")
Column({ space: 15 }) {
Button("删除数据")
.margin({ bottom: 30 })
.fontSize(30)
.width(300)
.height(60)
.onClick(() => {
this.cltData.pop()
})
Button("选择照片")
.margin({ bottom: 30 })
.fontSize(30)
.width(300)
.height(60)
.onClick(async () => {
try {
this.currentUri = await PhotoPickerClass.selectImageUri()
this.testPixMap = await PhotoPickerClass.creatPixMapByUri(this.currentUri)
} catch (err) {
promptAction.showToast({
message: `Error + ${err.message}`
})
}
})
}
}
.height('100%')
.layoutWeight(1)
.border({ width: 2, color: Color.Blue })
.borderRadius(10)
// 识别人脸部分
Column() {
Column({ space: 10 }) {
ForEach(this.cltData, (dataItem: string) => {
Text(dataItem ? dataItem : "")
})
}
.padding(15)
.layoutWeight(1)
.width("100%")
Button("识别人脸")
.margin({ bottom: 30 })
.fontSize(30)
.width(300)
.height(60)
.onClick(async () => {
try {
if (this.testPixMap) {
this.dataValue = await FaceDetectClass.detectFace(this.testPixMap)
this.cltData.push(this.dataValue)
promptAction.showToast({
message: "识别成功"
})
}
} catch (err) {
promptAction.showToast({
message: `识别错误____ ${err.message}`
})
}
})
}
.height('100%')
.layoutWeight(1)
.border({ width: 2, color: Color.Blue })
.borderRadius(10)
}
.padding(10)
.height('100%')
.width('100%')
}
}
标签:CoreVision,FaceDetector,面部,Kit,width,PixelMap,error,import,message
From: https://blog.csdn.net/2303_78789385/article/details/142593565