HarmonyOS NEXT AI 基础视觉服务 - 人脸对比
作者:zhousg
案例描述
这是一个基于 AI 基础视觉服务实现的人脸对比案例,通过调用设备相册选择两张图片进行人脸特征比对,并展示相似度计算结果。
实现步骤:
1. 模块导入
// 导入功能模块import { photoAccessHelper } from '@kit.MediaLibraryKit';import { fileIo } from '@kit.CoreFileKit';import { image } from '@kit.ImageKit';import { faceComparator } from '@kit.CoreVisionKit';import { promptAction } from '@kit.ArkUI';import { BusinessError } from '@kit.BasicServicesKit';
复制代码
2. 双图选择功能
// 创建通用图片选择方法async chooseImage (): Promise<PixelMap> { const photoPicker = new photoAccessHelper.PhotoViewPicker(); const photoResult = await photoPicker.select({ MIMEType: photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE, maxSelectNumber: 1 }) // 获取选中图片文件句柄 const fileSource = await fileIo.open(photoResult.photoUris[0], fileIo.OpenMode.READ_ONLY); // 生成像素图格式数据 return await image.createImageSource(fileSource.fd).createPixelMap();}
复制代码
3. 图像处理流程
// 双图存储变量定义@Local chooseImage1?: PixelMap@Local chooseImage2?: PixelMap
// 图片点击处理逻辑.onClick(async () => { const chooseImage = await this.chooseImage() this.chooseImage1 = chooseImage // 第一张图存储})
.onClick(async () => { const chooseImage = await this.chooseImage() this.chooseImage2 = chooseImage // 第二张图存储})
复制代码
4. 人脸对比核心实现
// 配置双图对比参数let visionInfo: faceComparator.VisionInfo = { pixelMap: this.chooseImage1,};
let visionInfo1: faceComparator.VisionInfo = { pixelMap: this.chooseImage2,};
// 执行人脸特征对比faceComparator.compareFaces(visionInfo, visionInfo1) .then(result => { // 弹窗显示相似度结果 promptAction.showDialog({ message: JSON.stringify(result) }) }) .catch((e: BusinessError) => { // 异常信息提示 promptAction.showToast({ message: e.message }) })
复制代码
5. 检测结果展示
// 弹窗显示结构化对比结果promptAction.showDialog({ message: JSON.stringify({ similarity: 0.92, // 相似度值示例 isSamePerson: true // 是否为同一人 })})
复制代码
落地代码:
1. UI 组件定义
@Entry@ComponentV2struct FaceComparator { @Local chooseImage1?: PixelMap @Local chooseImage2?: PixelMap
复制代码
2. 主功能方法
// 整合双图选择、特征对比完整逻辑async chooseImage(): Promise<PixelMap> { // 完整选择逻辑...}
复制代码
3. 界面构建
build() { Column({ space: 20 }) { Image(this.chooseImage1) .onClick(/* 第一图选择 */) Image(this.chooseImage2) .onClick(/* 第二图选择 */) Button('人脸对比') .onClick(/* 触发对比逻辑 */) }}
复制代码
总结梳理:
核心点
需要申请相册访问权限
双图选择采用独立存储变量管理
compareFaces 接口返回相似度(0-1)及特征点数据
异常处理通过 BusinessError 捕获设备兼容性问题
完整代码
import { photoAccessHelper } from '@kit.MediaLibraryKit';import { fileIo } from '@kit.CoreFileKit';import { image } from '@kit.ImageKit';import { faceComparator } from '@kit.CoreVisionKit';import { promptAction } from '@kit.ArkUI';import { BusinessError } from '@kit.BasicServicesKit';
@Entry@ComponentV2struct FaceComparator { @Local chooseImage1?: PixelMap @Local chooseImage2?: PixelMap
async chooseImage (): Promise<PixelMap> { const photoPicker: photoAccessHelper.PhotoViewPicker = new photoAccessHelper.PhotoViewPicker(); const photoResult = await photoPicker.select({ MIMEType: photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE, maxSelectNumber: 1 }) const photoUri = photoResult.photoUris[0] const fileSource = await fileIo.open(photoUri, fileIo.OpenMode.READ_ONLY); const imageSource = image.createImageSource(fileSource.fd); const chooseImage = await imageSource.createPixelMap(); return chooseImage }
build() { Column({ space: 20 }) { Image(this.chooseImage1) .alt($r('sys.media.save_button_picture')) .width(200) .aspectRatio(1) .onClick(async () => { const chooseImage = await this.chooseImage() this.chooseImage1 = chooseImage }) Image(this.chooseImage2) .alt($r('sys.media.save_button_picture')) .width(200) .aspectRatio(1) .onClick(async () => { const chooseImage = await this.chooseImage() this.chooseImage2 = chooseImage }) Button('人脸对比') .id('FaceComparatorButton') .onClick(async () => { if (this.chooseImage1 && this.chooseImage2) { let visionInfo: faceComparator.VisionInfo = { pixelMap: this.chooseImage1, }; let visionInfo1: faceComparator.VisionInfo = { pixelMap: this.chooseImage2, }; faceComparator.compareFaces(visionInfo, visionInfo1) .then(result => { promptAction.showDialog({ message: JSON.stringify(result) }) }) .catch((e: BusinessError) => { promptAction.showToast({ message: e.message }) }) } }) } .padding(15) .height('100%') .width('100%') }}
复制代码
划线
评论
复制
发布于: 刚刚阅读数: 6
版权声明: 本文为 InfoQ 作者【zhousg】的原创文章。
原文链接:【http://xie.infoq.cn/article/80f7d00b28a3d759a2aa861f2】。文章转载请联系作者。
zhousg
关注
还未添加个人签名 2025-03-14 加入
还未添加个人简介









评论