Java前沿生态之人脸识别

前段时间有幸得到了一个人脸识别的Java课程,开始以为是什么高大上的课程,后来才知道原来十分简单
整体都是调用接口,具体怎么实现呢

项目整体都是利用别人企业的工具实现的

首先我们需要注册一个账号,账号的网址如下,注册账号的时候好想要选择身份,我们选择个人就可以:

https://console.faceplusplus.com.cn/dashboard

接下来需要获取一个key和sercret

创建完毕之后,我们就会得到一个key和secret

相关的API文档都可以在官网进行查看,里面有参数的说明和使用方法

 

 

 

接下来废话不多说,上项目:

项目背景:cxk同学被主管叫过去说要提升公司的登录逼格,要将原有的账号密码登录改为人脸识别登录,还好xk同学很高兴,因为之前主管总是说一个很菜的人“你真是徐坤开门,菜到家了”,这次xk同学想发挥自己刚刚学习过的技术。

首先我们创建一个java项目,因为我们只需要实现后端功能,所以需要的jar包很少,只需要导入一个fastjson就可以了,所以根据个人爱好, 创建maven项目也不会麻烦的

项目结构如下

FaceUtil.java

package org.Util;

import java.io.File;
import java.util.HashMap;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

public class FaceUtil {
	
	
	/**
	 * 根据传入图片进行人脸检测
	 * @param file 传入的人脸照片
	 * @return 返回人脸照片的facetoken,如果为空说明图片不符合要求
	 * @throws Exception
	 */
	public static String detect(File file) throws Exception {
		byte[] buff = HTTPUtil.getBytesFromFile(file);
		String url = "https://api-cn.faceplusplus.com/facepp/v3/detect";
		HashMap<String, byte[]> byteMap = new HashMap<>();
		byteMap.put("image_file", buff);
		byte[] bacd = HTTPUtil.post(url, HTTPUtil.map, byteMap);
		String str = new String(bacd);
		if(str.indexOf("error_message")!=-1) {
			return null;
		}
		JSONObject obj = JSONObject.parseObject(str);
		int faceNum=obj.getIntValue("face_num");
		if(faceNum==1) {
			//获取facetoken
			JSONObject face=(JSONObject) ((JSONArray)obj.get("faces")).get(0);
			String faceToken=face.getString("face_token");
			return faceToken;
		}
		return null;
	}
	
	/**
	 * 查询指定的照片是否在人脸集合faceset中存在
	 * @param faceToken
	 * @return
	 * @throws Exception
	 */
	public static boolean search(String faceToken) throws Exception {
		String url = "https://api-cn.faceplusplus.com/facepp/v3/search";
		HTTPUtil.map.put("face_token", faceToken);
		byte[] bacd = HTTPUtil.post(url, HTTPUtil.map, null);
		String str = new String(bacd);
		if(str.indexOf("error_message")==-1) {//请求没有错误
			JSONObject json = JSONObject.parseObject(str);
			JSONObject thresholds=(JSONObject) json.get("thresholds");
			Double le5=thresholds.getDouble("1e-5");
			JSONArray results=(JSONArray) json.get("results");
			if(results!=null && results.size()>=1) {
				Double confidence=((JSONObject)results.get(0)).getDouble("confidence");
				if(confidence>le5) {
					return true;
				}
			}
		}
		return false;
	}	

	/**
	 * 添加人脸到faceset中
	 * @param face_tokens 要添加的人脸
	 * @return 
	 * @throws Exception
	 */
	public static boolean addFace(String face_tokens) throws Exception {
		if(!getDetail()) {//先获取人脸集合,没有集合就创建一个
			System.out.println("没有获取到指定人脸集合");
			boolean res=createFaceSet();
			if(!res) {
				System.out.println("创建人脸集合出问题了!");
				return false;
			}
			System.out.println("创建人脸集合成功!");
		}
		String url = "https://api-cn.faceplusplus.com/facepp/v3/faceset/addface";
		HTTPUtil.map.put("face_tokens", face_tokens);
		byte[] bacd = HTTPUtil.post(url, HTTPUtil.map, null);
		String str = new String(bacd);
		if(str.indexOf("error_message")!=-1) {
			return false;
		}
		return true;
	}	
	
	
	/**
	 * 创建一个人脸的集合 FaceSet,用于存储人脸标识 face_token。
	 * @return
	 * @throws Exception
	 */
	public static boolean createFaceSet() throws Exception {
		String url = "https://api-cn.faceplusplus.com/facepp/v3/faceset/create";
		byte[] bacd = HTTPUtil.post(url, HTTPUtil.map, null);
		String str = new String(bacd);
		System.out.println(str);
		if(str.indexOf("error_message")!=-1) {
			return false;
		}
		System.out.println("创建人脸集合:"+str);
		return true;
	}
	
	/**
	 * 获取一个faceset
	 * @return
	 * @throws Exception
	 */
	public static boolean getDetail() throws Exception {
		String url = "https://api-cn.faceplusplus.com/facepp/v3/faceset/getdetail";
		byte[] bacd = HTTPUtil.post(url, HTTPUtil.map, null);
		String str = new String(bacd);
		if(str.indexOf("error_message")!=-1) {
			return false;
		}
		return true;
	}

}

HTTPUtil.java

package org.Util;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.Random;

import javax.net.ssl.SSLException;

public class HTTPUtil {

	private final static int CONNECT_TIME_OUT = 30000;
	private final static int READ_OUT_TIME = 50000;
	private static String boundaryString = getBoundary();
	
	public  static HashMap<String, String> map = new HashMap<>();
	static {
		Properties pro=new Properties();
		InputStream in=FaceUtil.class.getResourceAsStream("/api.properties");
		try {
			pro.load(in);
		} catch (IOException e) {
			e.printStackTrace();
			System.out.println("配置文件加载错误!");
		}
		map.put("api_key", pro.getProperty("API_KEY"));
		map.put("api_secret", pro.getProperty("API_SECRET"));
		map.put("display_name", pro.getProperty("DISPLAY_NAME"));
		map.put("outer_id", pro.getProperty("OUTER_ID"));
	}
	
	
	
	public static byte[] post(String url, HashMap<String, String> map, HashMap<String, byte[]> fileMap)
			throws Exception {
		HttpURLConnection conne;
		URL url1 = new URL(url);
		conne = (HttpURLConnection) url1.openConnection();
		conne.setDoOutput(true);
		conne.setUseCaches(false);
		conne.setRequestMethod("POST");
		conne.setConnectTimeout(CONNECT_TIME_OUT);
		conne.setReadTimeout(READ_OUT_TIME);
		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());
		Iterator iter = map.entrySet().iterator();
		while (iter.hasNext()) {
			Map.Entry<String, String> entry = (Map.Entry) iter.next();
			String key = entry.getKey();
			String value = 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");
		}
		if (fileMap != null && fileMap.size() > 0) {
			Iterator fileIter = fileMap.entrySet().iterator();
			while (fileIter.hasNext()) {
				Map.Entry<String, byte[]> fileEntry = (Map.Entry<String, byte[]>) fileIter.next();
				obos.writeBytes("--" + boundaryString + "\r\n");
				obos.writeBytes("Content-Disposition: form-data; name=\"" + fileEntry.getKey() + "\"; filename=\""
						+ encode(" ") + "\"\r\n");
				obos.writeBytes("\r\n");
				obos.write(fileEntry.getValue());
				obos.writeBytes("\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();
	}

	private static String encode(String value) throws Exception {
		return URLEncoder.encode(value, "UTF-8");
	}

	public static byte[] getBytesFromFile(File f) {
		if (f == null) {
			return null;
		}
		try {
			FileInputStream stream = new FileInputStream(f);
			ByteArrayOutputStream out = new ByteArrayOutputStream(1000);
			byte[] b = new byte[1000];
			int n;
			while ((n = stream.read(b)) != -1)
				out.write(b, 0, n);
			stream.close();
			out.close();
			return out.toByteArray();
		} catch (IOException e) {
		}
		return null;
	}
}

ImageUtils.java

package org.Util;

import java.util.Base64;
import java.util.UUID;
import java.util.Base64.Decoder;

import javax.servlet.http.HttpServletRequest;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;

public class ImageUtils {
	
	/**
	 * 上传图片到指定位置
	 * @param request
	 * @param picName 客户端文件的name
	 * @param picPath 文件上传的路径
	 * @return
	 */
	public static File uploadImg(HttpServletRequest request,String picName,String picPath) {
		String imgData = request.getParameter(picName);//获取客户端传输到服务器的图片
		String path = request.getServletContext().getRealPath("/"+picPath+"/");//获取指定的图片上传到服务器的路径
		String fileName = UUID.randomUUID().toString().replace("-", "")+".png";//给图片一个随机名称
		boolean flag=generateImage(imgData.substring(22), path, fileName);//上传图片
		System.out.println("图片上传:"+flag+",地址:"+path);
		return new File(path+"/"+fileName);
	}

    private static boolean generateImage(String imgStr, String filePath, String fileName) {
        try {
            if (imgStr == null) {
                return false;
            }
            Decoder decoder = Base64.getDecoder();
            byte[] b = decoder.decode(imgStr);
            File file = new File(filePath);
            if (!file.exists()) {
                file.mkdirs();
            }
            OutputStream out = new FileOutputStream(filePath+fileName);
            out.write(b);
            out.flush();
            out.close();
            return true;
        } catch (Exception e) {
            return false;
        }
    }

}

test.java

package org.yc;

import org.Util.FaceUtil;

import java.io.File;

public class test {
    public static void main(String[] args){
        File file=new File("D:\\my bug\\ideal\\test\\web\\static\\cxk.png");
        try {
            String str=FaceUtil.detect( file );         //人脸健测
            System.out.println("face_token:"+str);
            boolean res=FaceUtil.search( str );         //搜索结果
            System.out.println("人脸搜索的结果:"+res);
            //获取人脸集合
            res=FaceUtil.getDetail();
            if(!res){
                FaceUtil.createFaceSet();
                System.out.println("如果没有指定的outer_id,则创建一个人脸集合");
            }
            System.out.println("outer_id为ycFaceSet的人脸集合:"+res);
            System.out.println("添加face_token到人脸集合中");
            FaceUtil.addFace( str );
            res=FaceUtil.search( str );
            System.out.println("再次检测outer_id中的是否有这个face_token:"+res);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

api.properties

API_KEY=账号的key
API_SECRET=账号的secret
DISPLAY_NAME=ycFaceSet
OUTER_ID=ycFaceSet

接下来献上我的主角:

我们通过代码可以发现即使换了人脸,试别的结果也是true。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值