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
@ComponentV2
struct 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
@ComponentV2
struct 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 加入
还未添加个人简介
评论