体验人脸识别

90 阅读5分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第7天,点击查看活动详情

未来项目可能需要使用人脸识别相关技术,所以今天做一下技术储备.

人脸识别说的比较高大上,其实背后就是一个机器学习训练出来的模型,如果有条件,可以尝试自己训练一个模型,如果没有条件,就可以像本文一样,调用一些平台开放出来的技术能力.

我们本次体验的是阿里云的人脸识别技术,截至本篇文档发布,阿里云的人脸人体能力还是免费,后续可能需要收费.

贴一个地址: vision.console.aliyun.com/cn-shanghai…

准备

  1. 阿里云开通人脸人体能力,链接在上面(免费)
  2. 阿里云新建RAM账户,授予AliyunVIAPIFullAccess权限(视觉管理api全部权限) ram.console.aliyun.com/users
    1. RAM账号较为安全,官网建议使用子账户.
  1. 阿里云OSS服务,作为文件上传存储介质(收费,体验免费)

流程简述

人脸识别的基本流程如下:

  1. 创建人脸数据库(个人账号最多创建1000个人脸数据库,最多100w张人脸)
  2. 上传人脸样本,也就是将来要搜索的人脸数据
  3. 调用人脸查询接口,传递要查询的图片,返回查询结果

那么oss在这里起到的作用是什么呢? 这是因为阿里云的人脸识别接口传递的都是人脸图片的url,而不是直接文件流,这样就需要先把文件上传到一个图床服务,oss的作用就在这里了.

实战

创建java项目之类的就不再赘述了.

1. 引入jar包

<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-java-sdk-core</artifactId>
    <version>4.5.14</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.aliyun/aliyun-java-sdk-facebody -->
<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-java-sdk-facebody</artifactId>
    <version>1.2.2</version>
</dependency>
<dependency>
    <groupId>com.aliyun.oss</groupId>
    <artifactId>aliyun-sdk-oss</artifactId>
    <version>3.15.1</version>
</dependency>

前两个是人脸识别的sdk,第三个是oss的sdk包.

2. show me code

package com.zy.facebody;

import com.aliyun.oss.ClientBuilderConfiguration;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.comm.Protocol;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.facebody.model.v20191230.*;
import com.aliyuncs.profile.DefaultProfile;
import com.google.gson.Gson;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;

/**
 * @Author: Zy
 * @Date: 2022/12/2 10:24
 */
public class TestFaceBody {
    static DefaultProfile profile;

    static {
        profile = DefaultProfile.getProfile("cn-shanghai", "申请的accessKeyId", "申请的accessSecret");
    }

    public static void main(String[] args) throws FileNotFoundException {
        String dbName = "compare_face_test";
        String entityId = "test_1";

//        File entityFile = new File("C:\Users\zy963\Desktop\entity.jpg");
        File searchFile = new File("C:\Users\zy963\Desktop\search4.jpg");

        // 添加样本
//        addFaceEntity(dbName, entityId);
//        addFace(dbName, entityId, new FileInputStream(entityFile), entityFile.getName());

        // 查询人脸数据库
        searchFace(dbName, searchFile.getName(), new FileInputStream(searchFile));
    }

    /**
     * 创建人脸数据库
     *
     * @param dbName 数据库名
     * @return void
     * @author Zy
     * @date 2022/12/2
     */
    public static void createFaceDb(String dbName) {
        IAcsClient client = new DefaultAcsClient(profile);

        CreateFaceDbRequest request = new CreateFaceDbRequest();
        request.setSysRegionId("cn-shanghai");
        request.setName(dbName);

        try {
            CreateFaceDbResponse response = client.getAcsResponse(request);
            System.out.println(new Gson().toJson(response));
        } catch (ClientException e) {
            System.out.println("ErrCode:" + e.getErrCode());
            System.out.println("ErrMsg:" + e.getErrMsg());
            System.out.println("RequestId:" + e.getRequestId());
        }
    }


    /**
     * 添加人脸样本
     * 人脸样本就是要存储的人脸数据
     *
     * @param entityId 样本id
     * @return void
     * @author Zy
     * @date 2022/12/2
     */
    public static void addFaceEntity(String dbName, String entityId) {
        IAcsClient client = new DefaultAcsClient(profile);

        AddFaceEntityRequest request = new AddFaceEntityRequest();
        request.setSysRegionId("cn-shanghai");
        request.setDbName(dbName);
        request.setEntityId(entityId);
        request.setLabels("测试");

        try {
            AddFaceEntityResponse response = client.getAcsResponse(request);
            System.out.println(new Gson().toJson(response));
        } catch (ClientException e) {
            System.out.println("ErrCode:" + e.getErrCode());
            System.out.println("ErrMsg:" + e.getErrMsg());
            System.out.println("RequestId:" + e.getRequestId());
        }
    }

    /**
     * 上传样本数据,支持oss
     *
     * @param dbName      人脸数据库名
     * @param entityId    样本id
     * @param inputStream 输入流
     * @return void
     * @author Zy
     * @date 2022/12/2
     */
    public static void addFace(String dbName, String entityId, FileInputStream inputStream, String fileName) {
        OSS ossClient = getOssClient();
        String bucketName = "oss的bucketName";
        // 创建PutObject请求。
        ossClient.putObject(bucketName, fileName, inputStream);

        ossClient.shutdown();
        String url = "https://" + bucketName + ".oss-cn-shanghai.aliyuncs.com/" + fileName;
        System.out.println(url);


        IAcsClient client = new DefaultAcsClient(profile);

        AddFaceRequest request = new AddFaceRequest();
        request.setSysRegionId("cn-shanghai");
        request.setDbName(dbName);
        request.setImageUrl(url);
        request.setEntityId(entityId);
        request.setExtraData("小明");

        try {
            AddFaceResponse response = client.getAcsResponse(request);
            System.out.println(new Gson().toJson(response));
        } catch (ClientException e) {
            System.out.println("ErrCode:" + e.getErrCode());
            System.out.println("ErrMsg:" + e.getErrMsg());
            System.out.println("RequestId:" + e.getRequestId());
        }
    }


    /**
     * 搜索人脸
     *
     * @param dbName      人脸数据库名称
     * @param fileName    图片文件名称
     * @param inputStream 图片文件流
     * @return void
     * @author Zy
     * @date 2022/12/2
     */
    public static void searchFace(String dbName, String fileName, InputStream inputStream) {
        OSS ossClient = getOssClient();
        String bucketName = "oss的bucketName";
        // 创建PutObject请求。
        ossClient.putObject(bucketName, fileName, inputStream);

        ossClient.shutdown();
        String url = "https://" + bucketName + ".oss-cn-shanghai.aliyuncs.com/" + fileName;
        System.out.println(url);
        IAcsClient client = new DefaultAcsClient(profile);
        SearchFaceRequest request = new SearchFaceRequest();
        request.setSysRegionId("cn-shanghai");
        request.setDbName(dbName);
        request.setImageUrl(url);
        request.setLimit(5);

        try {
            SearchFaceResponse response = client.getAcsResponse(request);
            System.out.println(new Gson().toJson(response));
        } catch (ClientException e) {
            System.out.println("ErrCode:" + e.getErrCode());
            System.out.println("ErrMsg:" + e.getErrMsg());
            System.out.println("RequestId:" + e.getRequestId());
        }

    }

    /**
     * oss client创建
     *
     * @param
     * @return com.aliyun.oss.OSS
     * @author Zy
     * @date 2022/12/2
     */
    public static OSS getOssClient() {
        // yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
        String endpoint = "oss的endpoint";
        // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
        String accessKeyId = "申请的accessKeyId";
        String accessKeySecret = "申请的accessKeyId";
        // 创建OSSClient实例。
        return new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
    }

}

代码不再赘述,都是官网的api,有兴趣可以参考官网: help.aliyun.com/document_de…

实现的效果也不太好贴图,毕竟是本人丑照.

不过识别还是很准确的.

能力概述

阿里云平台的人脸识别能力包含很多种,比如活体检测,人脸定位,人脸识别1:1,人脸识别1:N等,我们做人脸识别主要用的是人脸识别1:N,简单理解一下:

  1. 阿里云通过大量的训练做出一个识别准确度比较高的模型.
  2. 上传样本,阿里云将照片图片解析成特征项
    1. 人脸识别是不存储图片的,最多保留24H,可以理解为将图片转化为特征后,图片就没用了.
  1. 搜索人脸时,也是通过同样的方式来处理图片的.

总结

这次只是简单的调用平台api,并没有做很多识别准确度的测试,不过我觉得应该没啥问题.

有时间了可以对人脸识别的工具做一次封装,封成一个starter,便于使用.

阿里云平台或者其他平台的这种服务能力都并没有与springBoot这种流行技术结合起来,需要自己手动封装.