百度人脸识别应用(一)

602 阅读3分钟

「这是我参与11月更文挑战的第 3 天,活动详情查看:2021最后一次更文挑战

1、前言

最近的项目中,有一个考试功能出现了很多替考作弊的现象,经过研究决定加入百度的人脸查找,实现一张人脸数据对应一个账号信息。

2、人脸查找API的使用

首先人脸查找,是在指定人脸集合中,找到最相似的人脸。(根据人脸特征对比) 这里的人脸集合就是一个人脸库,在一个百度云用户下可以维护多个人脸库,人脸库中可以放多张人脸数据,并且同一个人脸数据可以存在不同的人脸库中。但一个人脸库中建议最多放80w条数据,不然对比起来会很耗时。所以如果我们的人脸数据很大的情况下,就需要对所有的人脸库进行一便检索了,这是我们需要注意的一个地方。

好了,下面我们直接上代码,这里我使用的百度的Java SDK 进行开发的。

首先我们需要先在配置文件中配置AppID、APIKey等信息。

//创建百度API
public static AipFace initBaiduV2ApiFace() {
        try {
            Properties properties = ResourceUtil.getResourceProperties();
            String APP_ID = properties.getProperty("face.baidu.AppID").trim();
            String API_KEY = properties.getProperty("face.baidu.APIKey").trim();
            String SECRET_KEY = properties.getProperty("face.baidu.SecretKey").trim();
            AipFace client = new AipFace(APP_ID, API_KEY, SECRET_KEY);
            // 可选:设置网络连接参数
            // 建立连接的超时时间(单位:毫秒)
            client.setConnectionTimeoutInMillis(15000);
            // 通过打开的连接传输数据的超时时间(单位:毫秒)
            client.setSocketTimeoutInMillis(60000);
            return client;
        } catch (Exception e) {
            Log4jUtil.logError.error("创建百度API失败:" + e.getMessage());
            return null;
        }
    }

需要注意的时,这里的image是base64编码后的图片数据,需urlencode,每次只支持单张图片,编码后的图片大小不超过10M。(PS:图片的base64编码指将图片数据编码成一串字符串,使用该字符串代替图像地址。您可以首先得到图片的二进制,然后用Base64格式编码即可。需要注意的是,图片的base64编码是不包含图片头的,如data:image/jpg;base64

public class FaceFindComponent {

    /**
     * 人脸查找
     * @param certId    --该用户唯一ID
     * @param imageData --人脸照片的Base64值
     * @return
     * @throws ExecutionException
     * @throws InterruptedException
     */
    public MessageModel certFaceFind(String certId, String imageData) throws IOException {
        //1、查找所有的用户组
        String groupIds = getGroupIds();
        //2、人脸查找
        BASE64Decoder decoder = new BASE64Decoder();
        byte[] imageBytes = decoder.decodeBuffer(imageData);
        JSONObject resObject = aipFace.identifyUser(groupIds, imageBytes, null);
        //3、解析返回结果
        return parseFaceFindResObject(certId, resObject);
    }

    /**
     * 转换百度人脸识别返回结果集
     * @param srcObject
     * @return
     */
    private MessageModel parseFaceFindResObject(String certIdDe, JSONObject srcObject) {
        LOGGER.info("人脸查找返回信息为:{}", srcObject);
        if (srcObject.has("error_code")) {
            Object error_code = srcObject.get("error_code");
            String errCode = String.valueOf(error_code);
            Properties properties = ResourceUtil.getResourcePropertiesBaiDu();
            messageModel.setErrorCode(messageModel.constErrorCode);
            String errorMsg = String.format("人脸识别失败,返回码:(%s),错误信息:%s。请重试!", errCode, properties.getProperty("baidu."+errCode));
            LOGGER.error(errorMsg);
            return messageModel;
        }
        //查找到的人脸结果数
        int resultNum = (int) srcObject.get("result_num");
        if (resultNum > 0) {
            //人脸库中已经存在,则不能让其他用户重复建档
            JSONArray result = (JSONArray) srcObject.get("result");
            for (Object item : result) {
            	JSONObject jsObj = (JSONObject) item;
            	JSONArray scores = (JSONArray) jsObj.get("scores");
                String resCertId = (String) jsObj.get("user_info");
                if (!resCertId.equals(certIdDe)) {
                    for (Object sc: scores) {
                        int resCompare = ((Double)sc).compareTo(80.0);
                        if (1 == resCompare || 0 == resCompare) {
                            LOGGER.info("该用户已在人脸库中建档,用户信息:{}", certIdDe);
                            return messageModel;
                        }
                    }
                }
            }
        }
        //可正常进行后续人脸建档操作
        LOGGER.info("人脸信息唯一检测通过,可正常进行后续人脸建档操作,用户信息:{}", certIdDe);
        return messageModel;
    }

    /**
     * 获取到所有的用户组ID(用于百度人脸识别的用户组)
     * @return
     */
    private String getGroupIds() {
        return faceGroupMapper.getFaceGroupIds();
    }
    
}