首先需要创建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 + " "); obos.writeBytes("Content-Disposition: form-data; name="" + key + "" "); obos.writeBytes(" "); obos.writeBytes(value + " "); } obos.writeBytes("--" + boundaryString + "--" + " "); obos.writeBytes(" "); 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(); } }