HarmonyOS NEXT AI基础视觉服务-人脸对比

案例描述

这是一个基于AI基础视觉服务实现的人脸对比案例,通过调用设备相册选择两张图片进行人脸特征比对,并展示相似度计算结果。

实现步骤:

1. 模块导入

// 导入功能模块
import { photoAccessHelper } from **********';
import { fileIo } from **********';
import { image } from **********';
import { faceComparator } from **********';
import { promptAction } from **********';
import { BusinessError } from **********';

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(/* 触发对比逻辑 */)
  }
}

总结梳理:

核心点

  1. 需要申请相册访问权限
  2. 双图选择采用独立存储变量管理
  3. compareFaces接口返回相似度(0-1)及特征点数据
  4. 异常处理通过BusinessError捕获设备兼容性问题

完整代码

import { photoAccessHelper } from **********';
import { fileIo } from **********';
import { image } from **********';
import { faceComparator } from **********';
import { promptAction } from **********';
import { BusinessError } from **********';

@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%')
  }
}

全部评论

相关推荐

关于合合的福利,免费早晚餐,六点半晚餐,七点半应该就没人了。ld,mt都很好相处,弹性打卡,最晚十一点。正式员工直接不用打卡。不了解应届生工资,但如果是应届生进去的话,感觉真的不错。去年2024出海软件盈利排名前五,入职之后愈发感觉还是有一些小厂挺不错的,大家投递的时候可以多试试当前以下岗位缺口较大,投递通过率较高:前端、后端、大数据相关其他岗位:产品经理、运营经理、市场管培生、数据产品经理、UI设计、测试等岗位也还在持续招聘中~你将获得:行业领先的人工智能及大数据科技企业提供的优厚薪酬回报+丰富的研发资源+高速的成长机会+全方位福利合合信息,旗下产品扫描全能王,启信宝等📢内推链接:https://intsig.zhiye.com/campus/jobs【内推码】ES3MAK投递的同学评论区留言哦,方便后续跟进,随时查进度 #春招#&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#校招#&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#内推#&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#内推码#&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
点赞 评论 收藏
分享
Java抽象小篮子:第二个项目前端写太多了,除非你要搞全栈,可以考虑把第二个项目换成一个轮子项目,简历怎么写我也发过帖子,你可以看看自己优化一下
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务