欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java使用百度人脸识别API攻略

程序员文章站 2022-07-12 18:39:45
...

1、首先在百度AI官网获取API Key、 Secret Key

创建新应用,即可免费自动获取。
强调一点:不要用我的API Key和Secrect Key!不要用我的API Key和Secrect Key!不要用我的API Key和Secrect Key!
Java使用百度人脸识别API攻略

2、查阅文档

https://cloud.baidu.com/doc/FACE/index.html
获取Java代码模板

创建获取token的类

package cn.tedu.chatBoardboot.faceDetect;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
import java.util.Map;

import org.json.JSONObject;

/**
 * 获取token类
*@author  Edward
*@date  2020年6月21日---上午11:27:35
*/
public class AuthService {
    /**
     * 获取权限token
     * @return 返回示例:
     * {
     * "access_token": "24.460da4889caad24cccdb1fea17221975.2592000.1491995545.282335-1234567",
     * "expires_in": 2592000
     * }
     */
    public static String getAuth() {
        // 官网获取的 API Key 更新为你注册的
        String clientId = "5IHjmjQEpo6G6xUL4XGlyp1z";
        // 官网获取的 Secret Key 更新为你注册的
        String clientSecret = "LOob7wI8xds3FfM1QxxYw9yT1Tv3IzKc";
        return getAuth(clientId, clientSecret);
    }

    /**
     * 获取API访问token
     * 该token有一定的有效期,需要自行管理,当失效时需重新获取.
     * @param ak - 百度云官网获取的 API Key
     * @param sk - 百度云官网获取的 Securet Key
     * @return assess_token 示例:
     * "24.460da4889caad24cccdb1fea17221975.2592000.1491995545.282335-1234567"
     */
    public static String getAuth(String ak, String sk) {
        // 获取token地址
        String authHost = "https://aip.baidubce.com/oauth/2.0/token?";
        String getAccessTokenUrl = authHost
                // 1. grant_type为固定参数
                + "grant_type=client_credentials"
                // 2. 官网获取的 API Key
                + "&client_id=" + "5IHjmjQEpo6G6xUL4XGlyp1z"
                // 3. 官网获取的 Secret Key
                + "&client_secret=" + "LOob7wI8xds3FfM1QxxYw9yT1Tv3IzKc";
        try {
            URL realUrl = new URL(getAccessTokenUrl);
            // 打开和URL之间的连接
            HttpURLConnection connection = (HttpURLConnection) realUrl.openConnection();
            connection.setRequestMethod("GET");
            connection.connect();
            // 获取所有响应头字段
            Map<String, List<String>> map = connection.getHeaderFields();
            // 遍历所有的响应头字段
            for (String key : map.keySet()) {
                System.err.println(key + "--->" + map.get(key));
            }
            // 定义 BufferedReader输入流来读取URL的响应
            BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            String result = "";
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
            /**
             * 返回结果示例
             */
            System.err.println("result:" + result);
            JSONObject jsonObject = new JSONObject(result);
            String access_token = jsonObject.getString("access_token");
            return access_token;
        } catch (Exception e) {
            System.err.printf("获取token失败!");
            e.printStackTrace(System.err);
        }
        return null;
    }
}
两个key需要自行替换


创建人脸检测与属性分析的类:

package cn.tedu.chatBoardboot.faceDetect;

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.imageio.ImageIO;

import org.springframework.stereotype.Component;

import cn.tedu.chatBoardboot.util.Base64Util;
import cn.tedu.chatBoardboot.util.GsonUtils;
import cn.tedu.chatBoardboot.util.HttpUtil;

/**
 * 人脸检测与属性分析
*@author  Edward
*@date  2020年6月21日---下午2:46:00
*/
@Component
public class FaceDetect {

    /**
    * 重要提示代码中所需工具类
    * FileUtil,Base64Util,HttpUtil,GsonUtils请从
    * https://ai.baidu.com/file/658A35ABAB2D404FBF903F64D47C1F72
    * https://ai.baidu.com/file/C8D81F3301E24D2892968F09AE1AD6E2
    * https://ai.baidu.com/file/544D677F5D4E4F17B4122FBD60DB82B3
    * https://ai.baidu.com/file/470B3ACCA3FE43788B5A963BF0B625F3
    * 下载
    */
	
	
	
    public static String faceDetect(String uri) {
        // 请求url
        String url = "https://aip.baidubce.com/rest/2.0/face/v3/detect";
        // 测试成功! 先把Json回到页面上,看看如何处理。
        File image = new File(uri);
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        String Base64 = null;
        try {
			BufferedImage img = ImageIO.read(image);
			ImageIO.write(img, "jpg", out);
			byte[]bytes = out.toByteArray();
			Base64=Base64Util.encode(bytes);
		} catch (IOException e1) {
			e1.printStackTrace();
		}
        
        
        try {
            Map<String, Object> map = new HashMap<>();
            
            map.put("image", Base64);
            map.put("face_field", "age,beauty,expression,race,gender,glasses,emotion,face_type,mask");
            map.put("image_type", "BASE64");

            String param = GsonUtils.toJson(map);

            // 注意这里仅为了简化编码每一次请求都去获取access_token,线上环境access_token有过期时间, 客户端可自行缓存,过期后重新获取。
            String accessToken = AuthService.getAuth();

            String result = HttpUtil.post(url, accessToken, "application/json", param);
            System.out.println(result);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    
    public static void main(String[] args) {
    	String uri = "C:\\Users\\Administrator\\Desktop\\sweet.jpg";
		FaceDetect.faceDetect(uri);
	}

}

工具类需要自己去百度指定网址下载并部署到本地项目中。
上面的image和image_type以及获取token的方法需要自行替换,imageType我这里是利用百度给的工具类将图片转换成BASE64格式来操作的,也可以自行在网上找类似工具转换。

到这里就可以获取到百度返回的json数据了。

3、通过页面上传的图片地址,调用faceDetect()方法获取json结果,并返回给页面

这里有个坑,百度回给的json数据是字符串格式的,所以在前端页面需要将其转换成json对象再处理,而且这个json数据有个大坑,就是face_list里面其实只有一个元素,因此代码如下:

	$("#btn-beauty").click(function() {
		$.ajax({
			"url" : "/users/file/beauty",
			//文件上传的指定格式
			//js和jq混用时,jq对象需要从数组变回单元素
			"data" : new FormData($("#form-beauty")[0]),
			//后两个属性表示,在前端不做处理
			"contentType":false,
			"processData":false,
			"type" : "post",
			"dataType" : "json",
			"success" : function(json) {
				if (json.state == 2000) {
					//前端jq无法读出face_list Cannot read property 'face_list' of undefined  放弃,后端完成
					//与下划线无关,timestamp也提取不出来
					//情况不太一样,之前传过来的就是List但是这次传过来就是字符串
					alert("data:"+json.data)
					//转换成json对象
					var obj = JSON.parse(json.data)
					alert("error_msg:"+obj.error_msg)
					//转换成功了,可以得到error_msg,但是Cannot read property 'beauty' of undefined
					var face_list = obj.result.face_list
					//转换成String输出
					alert("face_list:"+JSON.stringify(face_list))
					//face_list也拿到了
					var beauty = obj.result.face_list[0].beauty
					alert("beauty:"+JSON.stringify(beauty))
					var age = obj.result.face_list[0].age
					alert("age:"+JSON.stringify(age))
					var race = obj.result.face_list[0].race.type
					alert("race:"+JSON.stringify(race))
					//终于搞出来了,百度这个api给的face_list居然只有一项

				}else{
					alert(json.message)
				}

			},
			//当服务器响应时,只要HTTP响应码不是2xx,就会执行error
			"error": function(){
				alert("你的登录信息已过期,请重新登录! \n\n*注意:开发阶段,看到当前提示时,应该及时检查浏览器的Console和Network面板的信息,以确定出现错误的真正原因! ")
				location.href="/web/login.html"
			}
		});

弄了几个小时才弄好,希望后人少进坑。

PS:
不要尝试在后端对json进行处理了,fastjson(Springboot自带)和Gson同在的时候会有冲突 会报错:.concurrent.ThreadPoolTaskExecutor

	@Test
	public void aaa()  {
    	String uri = "C:\\Users\\Administrator\\Desktop\\sweet.jpg";
		String result = FaceDetect.faceDetect(uri);
		System.err.println(result);
		JsonParser parser = new JsonParser();
		JsonObject object = (JsonObject) parser.parse(result);
		System.err.println(object.get("error_code").getAsString());

		// 先不纠结了,就这样吧,fastjson和Gson同在的时候会有冲突 .concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskExecutor'
		
	}