yeg0zj

face++主页

首先需要创建faceSet,一个faceSet下有多个facetoken,facetoken就是人脸数据

其次,一张图片每次可以生成多个不同的facetoken,

可以只保留一个facetoken,然后直接判断facetoken是否与数据库的相同,如果执行这一步,可以使用删除的方法

也可以保留多个facetoken,根据一张图片获取多个facetoken然后遍历与数据库相同的,确定人物身份

查询时在faceSet里面查这个图片所对应的facetoken,如果系统只存了一个,那就返回这唯一的一个,如果多个就会返回多个

 

 定义实体类

@Data
@AllArgsConstructor
@NoArgsConstructor
class Face {
    private Double confidence;
    private String gender;
    private int age;
    private String faceToken;
}

@Data
@AllArgsConstructor
@NoArgsConstructor
class FaceBean {
    private String imageId;
    private String requestId;
    private Map<String,Double> thresholds;
    private List<Face> faces;
    private List<Face> results;
}

@Data
@AllArgsConstructor
@NoArgsConstructor
class FaceSet {
    private String facesetToken;
    private int faceCount;
    private int faceAdded;
    private String requestId;
    private String outerId;
    private String errorMessage;

}

 

public class FaceUtils {

    private Logger logger = LogManager.getLogger(FaceUtils.class);

    private final String API_KEY = "api_key";
    private final String API_SECRET = "api_secret";

    /**
     * 创建人脸并添加至指定的人脸库
     * @param file 图片文件
     * @param faceSet 人脸库
     * @return 返回face_token
     * @throws Exception  可能抛出创建人脸异常/绑定人脸异常
     */
    public String createAndBind(File file, String faceSet) throws Exception {
            @Cleanup InputStream inputStream = new FileInputStream(file);
            byte [] bytes = new byte[(int) file.length()];
            inputStream.read(bytes);
            String base64 = Base64.getEncoder().encodeToString(bytes);
            return createFace(base64,faceSet);
    }

    /**
     * 创建人脸并添加至指定的人脸库
     * @param file 图片文件
     * @param faceSet 人脸库
     * @return 返回face_token
     * @throws Exception  可能抛出创建人脸异常/绑定人脸异常
     */
    public String createAndBind(MultipartFile file, String faceSet) throws Exception {
        return  createFace(Base64.getEncoder().encodeToString(file.getBytes()),faceSet);
    }

    /**
     *
     * @param image_base64  图片文件Base64字符串
     * @param faceSet 人脸库
     */
    private String createFace(String image_base64, String faceSet) throws Exception {
        HashMap<String, Object> map = new HashMap<>();
        map.put("api_key", API_KEY);
        map.put("api_secret", API_SECRET);
        map.put("image_base64", image_base64);
        String url = "https://api-cn.faceplusplus.com/facepp/v3/detect";
        String str;
        try {
            byte[] bacd = post(url, map);
            str = new String(bacd);
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception("生成人脸token出现异常");
        }
        FaceBean faceBean = JSONObject.parseObject(str, FaceBean.class);
        if (ObjectUtils.isEmpty(faceBean.getFaces())){
            throw new Exception("生成人脸token出现异常");
        }
        String face_token = faceBean.getFaces().get(0).getFaceToken();
        url = "https://api-cn.faceplusplus.com/facepp/v3/faceset/addface";
        map.clear();
        map.put("api_key", API_KEY);
        map.put("api_secret", API_SECRET);
        map.put("faceset_token", faceSet);
        map.put("face_tokens", face_token);
        try {
            byte[] bacd = post(url, map);
            String result = new String(bacd);
            FaceSet set = JSONObject.parseObject(result, FaceSet.class);
            if (!ObjectUtils.isEmpty(set.getErrorMessage())) {
                throw new Exception();
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception("绑定人脸库出现异常");
        }
        return face_token;
    }

    /**
     * 查询人脸信息 传入图片 ,从指定人脸库查询人脸
     * @param file  图片文件
     * @param faceSet 人脸库 
     */
    public String searchFace(MultipartFile file, String faceSet) throws IOException {
        String image_base64 = Base64.getEncoder().encodeToString(file.getBytes());
        HashMap<String, Object> map = new HashMap<>();
        String url = "https://api-cn.faceplusplus.com/facepp/v3/search";
        map.put("api_key", API_KEY);
        map.put("api_secret", API_SECRET);
        map.put("faceset_token", faceSet);
        map.put("image_base64", image_base64);
        try {
            String result = new String(this.post(url, map));
            FaceBean faceBean = JSONObject.parseObject(result, FaceBean.class);
            if (ObjectUtils.isEmpty(faceBean.getResults())){
                return "未找到人脸";
            }
            Double aDouble = faceBean.getThresholds().get("1e-3");
            logger.warn("对比度 {}",aDouble);
            //判断对比阈值
            if(faceBean.getResults().get(0).getConfidence()<aDouble){
                return "未找到人脸";
            }
            return faceBean.getResults().get(0).getFaceToken();
        } catch (Exception e) {
            e.printStackTrace();
            return "未找到人脸";
        }
    }

    /**
     * 删除指定库中的指定某张图片
     */
    public String removeFace(HashMap<String, Object> map){
        map.put("api_key",API_KEY);
        map.put("api_secret",API_SECRET);
        String str = null;
        final String DELETE_FACE_SET_URL = "https://api-cn.faceplusplus.com/facepp/v3/faceset/removeface";
        try {
            byte[] bacd = post(DELETE_FACE_SET_URL, map);
            str = new String(bacd);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return str;
    }

    private String boundaryString = getBoundary();

    private byte[] post(String url, HashMap<String, Object> map) throws Exception {
        HttpURLConnection conne;
        URL url1 = new URL(url);
        conne = (HttpURLConnection) url1.openConnection();
        conne.setDoOutput(true);
        conne.setUseCaches(false);
        conne.setRequestMethod("POST");
        conne.setConnectTimeout(30000);
        conne.setReadTimeout(50000);
        conne.setRequestProperty("accept", "*/*");
        conne.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundaryString);
        conne.setRequestProperty("connection", "Keep-Alive");
        conne.setRequestProperty("user-agent", "Mozilla/4.0 (compatible;MSIE 6.0;Windows NT 5.1;SV1)");
        DataOutputStream obos = new DataOutputStream(conne.getOutputStream());
        for (Object o : map.entrySet()) {
            Map.Entry<String, String> entry = (Map.Entry) o;
            String key = entry.getKey();
            String value = String.valueOf(entry.getValue());
            obos.writeBytes("--" + boundaryString + "\r\n");
            obos.writeBytes("Content-Disposition: form-data; name=\"" + key
                    + "\"\r\n");
            obos.writeBytes("\r\n");
            obos.writeBytes(value + "\r\n");
        }
        obos.writeBytes("--" + boundaryString + "--" + "\r\n");
        obos.writeBytes("\r\n");
        obos.flush();
        obos.close();
        InputStream ins = null;
        int code = conne.getResponseCode();
        try {
            if (code == 200) {
                ins = conne.getInputStream();
            } else {
                ins = conne.getErrorStream();
            }
        } catch (SSLException e) {
            e.printStackTrace();
            return new byte[0];
        }
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte[] buff = new byte[4096];
        int len;
        while ((len = ins.read(buff)) != -1) {
            baos.write(buff, 0, len);
        }
        byte[] bytes = baos.toByteArray();
        ins.close();
        return bytes;
    }

    private static String getBoundary() {
        StringBuilder sb = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < 32; ++i) {
            sb.append("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-".charAt(random.nextInt("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_".length())));
        }
        return sb.toString();
    }
}

 

分类:

技术点:

相关文章: