智慧社区:调用腾讯云的人脸识别接口完成人脸采集的功能

目录

1.业务逻辑

2.代码实现

[2.1 获取API的密钥](#2.1 获取API的密钥)

[2.2 创建人员库](#2.2 创建人员库)

[2.3 配置API](#2.3 配置API)

[2.4 编写接口](#2.4 编写接口)

(1)严谨性校验

(2)构建人脸

(3)更新用户状态,设置图片Url


1.业务逻辑

首先居民需要录入自己的人脸,在采集人脸中录入,随后人脸图片进入腾讯云的人员库和服务器的数据库。

上传成功后如图:

2.代码实现

2.1 获取API的密钥

首先进入控制台总览,然后搜索访问管理:

新建密钥后记得保存密钥,key一旦创建完成,就不会再显示。

2.2 创建人员库

搜索人脸识别:

找到人员管理,然后新建人员库:

按照要求填写必填项,其中人员库id需要配置在配置文件当中

2.3 配置API

在上面的工作都完成之后,就可以进行代码编写了

封装了一个Api参数类,用来读取配置文件中关于腾讯云接口的一些参数:

java 复制代码
package com.qcby.config;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@ConfigurationProperties(value="plateocr")
@Component
@Data
@ApiModel(value = "ApiConfiguration",description = "人脸识别参数描述")
public class ApiConfiguration {

    @ApiModelProperty("人脸识别secretId")
    private String secretId;
    @ApiModelProperty("人脸识别secretKey")
    private String secretKey;
    //	服务器ip
    @ApiModelProperty("人脸识别服务器ip")
    private String serverIp;
    //	服务器区域
    @ApiModelProperty("人脸识别服务器区域")
    private String area;
    //	默认分组
    @ApiModelProperty("人脸识别默认分组")
    private String groupId;
    //	用户id前缀
    @ApiModelProperty("人脸识别用户id前缀")
    private String personIdPre;
    //	随机数
    @ApiModelProperty("人脸识别随机数")
    private String nonceStr;
    //	是否使用
    @ApiModelProperty("人脸识别,是否启用人脸识别功能")
    private boolean used = false;
    //	识别准确率
    @ApiModelProperty("人脸识别比对准确度,如符合80%就识别通过")
    private float passPercent;
}

同时在配置文件中配置:

secret-id和key需要在腾讯云的人脸控制台中获取

used是是否开启识别,需要的话就是true

server-ip:域名是 API 的接入点,并不代表产品或者接口实际提供服务的地域,接口支持的地域如下:

area:ap-地区,例如ap-beijing

group-id:人员库的id。在上一步获取到了

pass-percent:识别的严格度,例如这个值是80%,现有人脸和人员库人脸对比符合80%就可以通过

person-id-pre:人员库当中人员id的前缀,我加上了user_,假如入库的人员id=9,那么这个人在我的人员库id就是user_9。

java 复制代码
#配置人脸识别Api
plateocr:
  secret-id: AKIDQsHXbTDmETXR9ey68yb1INErSxa9Zpsr
  secret-key: sXzDG8oGUYQ6cx74oKgplTyIPIySkpjS
  used: true
  server-ip: iai.tencentcloudapi.com
  area: ap-guangzhou
  group-id: AiCommunity
  pass-percent: 0.8
  person-id-pre: user_

2.4 编写接口

工具类FaceApi:

java 复制代码
package com.qcby.util;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.qcby.config.ApiConfiguration;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.iai.v20180301.IaiClient;
import com.tencentcloudapi.iai.v20180301.models.*;
import org.apache.log4j.Logger;

public class FaceApi {

    private Logger logger = Logger.getLogger(FaceApi.class);

    //人脸分析
    public RootResp detectFace(ApiConfiguration config, String url) {
        RootResp result = new RootResp();
        try{
            Credential cred = new Credential(config.getSecretId(), config.getSecretKey());
            HttpProfile httpProfile = new HttpProfile();
            httpProfile.setEndpoint(config.getServerIp());
            ClientProfile clientProfile = new ClientProfile();
            clientProfile.setHttpProfile(httpProfile);
            IaiClient client = new IaiClient(cred, config.getArea(), clientProfile);
            JSONObject paramObj = new JSONObject();
            paramObj.put("Url", url);
            paramObj.put("MaxFaceNum",1);
            paramObj.put("MinFaceSize",34);
            paramObj.put("NeedFaceAttributes",0);
            paramObj.put("NeedQualityDetection",1);
            DetectFaceRequest req = DetectFaceRequest.fromJsonString(paramObj.toJSONString(),DetectFaceRequest.class);
            DetectFaceResponse resp = client.DetectFace(req);
            result.setData(DetectFaceResponse.toJsonString(resp));
        } catch (TencentCloudSDKException e) {
            result.setRet(-1);
            result.setMsg(e.toString());
            logger.error(e.toString());
        }
        logger.info(result);
        return result;
    }

    //添加个体
    public RootResp newperson(ApiConfiguration config, String personId, String personName, String image) {
        RootResp result = new RootResp();
        try{
            Credential cred = new Credential(config.getSecretId(), config.getSecretKey());
            HttpProfile httpProfile = new HttpProfile();
            httpProfile.setEndpoint(config.getServerIp());
            ClientProfile clientProfile = new ClientProfile();
            clientProfile.setHttpProfile(httpProfile);
            IaiClient client = new IaiClient(cred, config.getArea(), clientProfile);
            JSONObject paramObj = new JSONObject();
            paramObj.put("GroupId", config.getGroupId());
            paramObj.put("PersonId", config.getPersonIdPre() + personId);
            paramObj.put("PersonName", personName);
            paramObj.put("Image", image);
            CreatePersonRequest req = CreatePersonRequest.fromJsonString(paramObj.toJSONString(), CreatePersonRequest.class);
            CreatePersonResponse resp = client.CreatePerson(req);
            result.setData(CreatePersonResponse.toJsonString(resp));
        } catch (TencentCloudSDKException e) {
            result.setRet(-1);
            result.setMsg(e.toString());
            logger.error(e.toString());
        }
        logger.info(result);
        return result;
    }

    //删除个体
    public RootResp delperson(ApiConfiguration config, String personId) {
        RootResp result = new RootResp();
        try{
            Credential cred = new Credential(config.getSecretId(), config.getSecretKey());
            HttpProfile httpProfile = new HttpProfile();
            httpProfile.setEndpoint(config.getServerIp());
            ClientProfile clientProfile = new ClientProfile();
            clientProfile.setHttpProfile(httpProfile);
            IaiClient client = new IaiClient(cred, config.getArea(), clientProfile);
            JSONObject paramObj = new JSONObject();
            paramObj.put("PersonId", config.getPersonIdPre() + personId);
            DeletePersonRequest req = DeletePersonRequest.fromJsonString(paramObj.toJSONString(), DeletePersonRequest.class);
            DeletePersonResponse resp = client.DeletePerson(req);
            result.setData(DeletePersonResponse.toJsonString(resp));
        } catch (TencentCloudSDKException e) {
            result.setRet(-1);
            result.setMsg(e.toString());
            logger.error(e.toString());
        }
        logger.info(result);
        return result;
    }

    //增加人脸
    public RootResp addface(ApiConfiguration config, String personId, String image) {
        RootResp result = new RootResp();
        try{
            Credential cred = new Credential(config.getSecretId(), config.getSecretKey());
            HttpProfile httpProfile = new HttpProfile();
            httpProfile.setEndpoint(config.getServerIp());
            ClientProfile clientProfile = new ClientProfile();
            clientProfile.setHttpProfile(httpProfile);
            IaiClient client = new IaiClient(cred, config.getArea(), clientProfile);
            JSONObject paramObj = new JSONObject();
            JSONArray images = new JSONArray();
            images.add(image);
            paramObj.put("PersonId", config.getPersonIdPre() + personId);
            paramObj.put("Images", images);
            CreateFaceRequest req = CreateFaceRequest.fromJsonString(paramObj.toJSONString(), CreateFaceRequest.class);
            CreateFaceResponse resp = client.CreateFace(req);
            result.setData(CreateFaceResponse.toJsonString(resp));
        } catch (TencentCloudSDKException e) {
            result.setRet(-1);
            result.setMsg(e.toString());
            logger.error(e.toString());
        }
        logger.info(result);
        return result;
    }

    //删除人脸
    public RootResp delface(ApiConfiguration config, String personId, String faceId) {
        RootResp result = new RootResp();
        try{
            Credential cred = new Credential(config.getSecretId(), config.getSecretKey());
            HttpProfile httpProfile = new HttpProfile();
            httpProfile.setEndpoint(config.getServerIp());
            ClientProfile clientProfile = new ClientProfile();
            clientProfile.setHttpProfile(httpProfile);
            IaiClient client = new IaiClient(cred, config.getArea(), clientProfile);
            JSONObject paramObj = new JSONObject();
            JSONArray faces = new JSONArray();
            faces.add(faceId);
            paramObj.put("PersonId", config.getPersonIdPre() + personId);
            paramObj.put("FaceIds", faces);
            DeleteFaceRequest req = DeleteFaceRequest.fromJsonString(paramObj.toJSONString(), DeleteFaceRequest.class);
            DeleteFaceResponse resp = client.DeleteFace(req);
            result.setData(DeleteFaceResponse.toJsonString(resp));
        } catch (TencentCloudSDKException e) {
            result.setRet(-1);
            result.setMsg(e.toString());
            logger.error(e.toString());
        }
        logger.info(result);
        return result;
    }

    //人脸验证
    public RootResp faceVerify(ApiConfiguration config, String personId, String image) {
        RootResp result = new RootResp();
        try{
            Credential cred = new Credential(config.getSecretId(), config.getSecretKey());
            HttpProfile httpProfile = new HttpProfile();
            httpProfile.setEndpoint(config.getServerIp());
            ClientProfile clientProfile = new ClientProfile();
            clientProfile.setHttpProfile(httpProfile);
            IaiClient client = new IaiClient(cred, config.getArea(), clientProfile);
            JSONObject paramObj = new JSONObject();
            paramObj.put("PersonId", config.getPersonIdPre() + personId);
            paramObj.put("Image", image);
            VerifyFaceRequest req = VerifyFaceRequest.fromJsonString(paramObj.toJSONString(), VerifyFaceRequest.class);
            VerifyFaceResponse resp = client.VerifyFace(req);
            result.setData(VerifyFaceResponse.toJsonString(resp));
        } catch (TencentCloudSDKException e) {
            result.setRet(-1);
            result.setMsg(e.toString());
            logger.error(e.toString());
        }
        logger.info(result);
        return result;
    }

    //人员搜索按库返回
    public RootResp searchPersonsReturnsByGroup(ApiConfiguration config, String image) {
        RootResp result = new RootResp();
        try{
            Credential cred = new Credential(config.getSecretId(), config.getSecretKey());
            HttpProfile httpProfile = new HttpProfile();
            httpProfile.setEndpoint(config.getServerIp());
            ClientProfile clientProfile = new ClientProfile();
            clientProfile.setHttpProfile(httpProfile);
            IaiClient client = new IaiClient(cred, config.getArea(), clientProfile);
            JSONObject paramObj = new JSONObject();
            paramObj.put("GroupIds", new String[] {config.getGroupId()});
            paramObj.put("Image", image);
            //最多返回的最相似人员数目
            paramObj.put("MaxPersonNumPerGroup", 5);
            //返回人员具体信息
            paramObj.put("NeedPersonInfo", 1);
            //最多识别的人脸数目
            paramObj.put("MaxFaceNum", 1);
            SearchFacesReturnsByGroupRequest req = SearchFacesReturnsByGroupRequest.fromJsonString(paramObj.toJSONString(), SearchFacesReturnsByGroupRequest.class);
            SearchFacesReturnsByGroupResponse resp = client.SearchFacesReturnsByGroup(req);
            result.setData(VerifyFaceResponse.toJsonString(resp));
        } catch (TencentCloudSDKException e) {
            result.setRet(-1);
            result.setMsg(e.toString());
            logger.error(e.toString());
        }
        logger.info(result);
        return result;
    }
}

我们主要使用newperson()和searchPersonsReturnsByGroup()方法,前者用于人脸采集,把人脸入库;后者用于识别人脸,在进出小区时用到。

结果封装类:

java 复制代码
package com.qcby.util;

import com.alibaba.fastjson.JSON;

public class RootResp {
    private int ret = 0;

    public int getRet() {
        return this.ret;
    }

    public void setRet(int ret) {
        this.ret = ret;
    }

    private String msg;

    public String getMsg() {
        return this.msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    private Object data;

    public Object getData() {
        return this.data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    @Override
    public String toString() {
        return JSON.toJSONString(this);
    }
}
java 复制代码
package com.qcby.util;
import java.util.HashMap;

public class Result extends HashMap<String,Object> {

    public static Result ok(){
        Result result = new Result();
        result.put("code", 200);
        result.put("msg", "操作成功");
        return result;
    }

    public static Result error(String msg){
        Result result = new Result();
        result.put("code", 500);
        result.put("msg", msg);
        return result;
    }

    @Override
    public Result put(String key, Object value) {
        super.put(key, value);
        return this;
    }
}

人脸采集接口:

java 复制代码
    /**
     * 人脸采集
     *
     */
    @PostMapping("/addPerson")
    public Result addPersonFace(@RequestBody PersonFaceAddForm form){
        //程序严谨性判断
        Person person = this.personService.getById(form.getPersonId());
        if(person == null){
            return Result.error("居民不存在");
        }

        // 检查是否已存在人脸信息
        if(person.getFaceUrl() != null && !person.getFaceUrl().isEmpty() && person.getState() == 2) {
            return Result.error("该居民已录入人脸信息,无法重复录入");
        }

        if(person.getState() == 2){
            return Result.error("人脸识别已通过,不需要重复识别");
        }
        if(form.getFileBase64() == null || form.getFileBase64().equals("")){
            return Result.error("请上传Base64编码的图片");
        }
        if(apiConfiguration.isUsed()){
            //构建人脸
            String faceId = personVal(form,person.getUserName());
            if(faceId != null){
                //生成头像访问路径
                String filename = faceId + "." + form.getExtName();
                String faceUrl = urlPrefix + "community/upload/face/" + filename;
                person.setState(2);
                person.setFaceUrl(faceUrl);
                boolean updateResult = personService.updateById(person);
                if (!updateResult){
                    return Result.error("人脸录入失败!");
                }
            }
        }else{
            return Result.error("未开启人脸识别接口");
        }
        return Result.ok();
    }

需要调用的方法:

java 复制代码
/**
     * 添加人脸,创建人脸信息并且添加到腾讯云的人脸库
     * @param form
     * @param userName
     * @return
     */
    private String personVal(PersonFaceAddForm form,String userName){
        String faceId = null;
        String faceBase64 = form.getFileBase64();
        String extname = form.getExtName();
        String personId = form.getPersonId()+"";
        //D:/community/upload/face/
        String savePath = face;
        if (faceBase64!=null && !faceBase64.equals("")) {
            FaceApi faceApi = new FaceApi();
            RootResp resp = faceApi.newperson(apiConfiguration, personId, userName, faceBase64);
            if(resp.getRet()==0) {
                JSONObject data = JSON.parseObject(resp.getData().toString());
                faceId = data.getString("FaceId");
                if(faceId!=null) {
                    String filename = faceId + "." + extname;
                    savePath += filename;
                    try {
                        Base64Util.decoderBase64File(faceBase64, savePath);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
            else {
                return faceId;
            }
        }
        return faceId;
    }

form实体类中封装了这个居民的personId,上传图片的文件拓展名extName,图片的Base64编码fileBase64

接口当中的执行:

(1)严谨性校验

在数据库中查询该居民是否存在,查询这个居民是否已经采集过人脸,检验图片的base64是否合法

(2)构建人脸

在进行完严谨性校验之后,如果启用了人脸识别功能,会调用personVal方法来调用工具类当中的添加人员的方法,执行成功之后会返回这个用户在人员库当中的id

java 复制代码
            String faceId = personVal(form,person.getUserName());

在personVal当中,传入了form,还是那几个属性。

在方法内部首先获取了这三个属性,定义了返回结果faceId=null,获取了文件的保存路径savePath

savePath在配置文件当中配置,通过@Value注解获取值:

java 复制代码
upload:
  face: D:/community/upload/face/
  urlPrefix: http://localhost:8282/
  excel: D:/community/upload/excel/
java 复制代码
    @Value("${upload.face}")
    private String face;
java 复制代码
        String faceId = null;
        String faceBase64 = form.getFileBase64();
        String extname = form.getExtName();
        String personId = form.getPersonId()+"";
        //D:/community/upload/face/
        String savePath = face;

获取到这些值之后创建了FaceApi对象,准备调用其的newperson方法

java 复制代码
        if (faceBase64!=null && !faceBase64.equals("")) {
            FaceApi faceApi = new FaceApi();
            RootResp resp = faceApi.newperson(apiConfiguration, personId, userName, faceBase64);
            if(resp.getRet()==0) {
                JSONObject data = JSON.parseObject(resp.getData().toString());
                faceId = data.getString("FaceId");
                if(faceId!=null) {
                    String filename = faceId + "." + extname;
                    savePath += filename;
                    try {
                        Base64Util.decoderBase64File(faceBase64, savePath);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
            else {
                return faceId;
            }
        }

传入参数后调用方法,如果接口调用无误,resp.getRet()会等于0,接口返回的数据如下:

java 复制代码
{
  "FaceId" : "6618560869116710459",
  "FaceRect" : {
    "X" : 31,
    "Y" : 52,
    "Width" : 60,
    "Height" : 78
  },
  "SimilarPersonId" : "",
  "FaceModelVersion" : "3.0",
  "RequestId" : "b5b6ffe2-93d7-4efb-b333-2df72cc468e7"
}

取出faceId用作上传图片的唯一名字,随后获取到savePath:

java 复制代码
Base64Util.decoderBase64File(faceBase64, savePath);

这个方法参数传入了Base64 编码的字符串(faceBase64) + 保存路径(savePath),然后将 Base64 解码成二进制数据,保存为文件到指定路径,也就是我的D:/community/upload/face/6618560869116710459.png

返回faceId

(3)更新用户状态,设置图片Url

随后回到接口方法,生成图片的访问路径faceUrl,然后存到数据库中,因为上传的图片和此处生成的图片名字都由faceId拼接,所以能够访问到,urlPrefix和savePath同理,都在yaml配置文件中配置。

java 复制代码
            //构建人脸
            String faceId = personVal(form,person.getUserName());
            if(faceId != null){
                //生成头像访问路径
                String filename = faceId + "." + form.getExtName();
                String faceUrl = urlPrefix + "community/upload/face/" + filename;
                person.setState(2);
                person.setFaceUrl(faceUrl);
                boolean updateResult = personService.updateById(person);
                if (!updateResult){
                    return Result.error("人脸录入失败!");
                }
            }

更新完后返回Result.ok()

上传完之后状态变成了已识别,也能看到图片。

相关推荐
逛逛GitHub2 小时前
推荐 8 个爷青回 GitHub 开源游戏,太怀念了。
github
QQ__17646198242 小时前
Ubuntu系统克隆Github仓库项目到本地
linux·ubuntu·github
冬天的风滚草3 小时前
揭秘云原生混布资源调度器Koordinator (六)MetricCache 指标缓存机制
云计算
冬天的风滚草3 小时前
揭秘云原生混布资源调度器Koordinator (一)Koordinator 整体架构设计
云计算
可爱又迷人的反派角色“yang”3 小时前
docker(五)
linux·运维·网络·docker·容器·云计算
EMQX3 小时前
大规模使用 AWS IoT Core 的成本困境:EMQX 如何削减 80% 开支
物联网·mqtt·云计算·aws
weixin_307779134 小时前
通过AWS Transfer Family集成Active Directory实现安全SFTP文件访问
安全·云计算·aws
木子欢儿4 小时前
阿里云系统磁盘总读BPS突然增长很高,导致网站502 Bad Gateway
阿里云·云计算·gateway
翼龙云_cloud5 小时前
亚马逊云渠道商:AWS Lightsail 极速部署演示环境搭建指南
运维·服务器·云计算·aws