【快速上手系列】使用idea调百度AI接口实现人脸识别功能
创始人
2024-01-31 00:50:59

【快速上手系列】使用idea调百度AI接口实现人脸识别功能

一、人脸检测

步骤

1、百度AI开放平台

登录后点击控制台

请添加图片描述

点击公有云服务——应用列表——点击创建应用

请添加图片描述

填写一下信息然后创建

请添加图片描述

然后回到概览——领取免费资源(如果账号没领取过的话)

请添加图片描述

可以自选,不过嫌麻烦直接全选了也一样

请添加图片描述

然后回到概览——点击调用服务下的API文档

请添加图片描述

获取api

到API文档下滑,可以看到获取Access Token的工具类

请添加图片描述

再往下滑可以看到demo的示例代码(懒的搞下面有代码)

请添加图片描述

获取sdk

点击概览下HTTP SDK

请添加图片描述

调转后可以看到所有的接口需要的各平台sdk,是离线的jar包
请添加图片描述

2、idea创建demo

idea新建一个maven项目

maven依赖

pom.xml

com.baidu.aipjava-sdk4.6.0

org.jsonjson20160810

com.google.code.gsongson2.9.0

项目结构

请添加图片描述

Base64Util:Base64 工具类

FileUtil:文件读取工具类

GetAccessToken:获取token类

GsonUtils:Json工具类.

HttpUtil:http 工具类

tips:不是哪个项目都会用到,看情况,懒的话全扔里就行

五个工具类代码

Base64Util.java

package utils;/*** Base64 工具类*/
public class Base64Util {private static final char last2byte = (char) Integer.parseInt("00000011", 2);private static final char last4byte = (char) Integer.parseInt("00001111", 2);private static final char last6byte = (char) Integer.parseInt("00111111", 2);private static final char lead6byte = (char) Integer.parseInt("11111100", 2);private static final char lead4byte = (char) Integer.parseInt("11110000", 2);private static final char lead2byte = (char) Integer.parseInt("11000000", 2);private static final char[] encodeTable = new char[]{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};public Base64Util() {}public static String encode(byte[] from) {StringBuilder to = new StringBuilder((int) ((double) from.length * 1.34D) + 3);int num = 0;char currentByte = 0;int i;for (i = 0; i < from.length; ++i) {for (num %= 8; num < 8; num += 6) {switch (num) {case 0:currentByte = (char) (from[i] & lead6byte);currentByte = (char) (currentByte >>> 2);case 1:case 3:case 5:default:break;case 2:currentByte = (char) (from[i] & last6byte);break;case 4:currentByte = (char) (from[i] & last4byte);currentByte = (char) (currentByte << 2);if (i + 1 < from.length) {currentByte = (char) (currentByte | (from[i + 1] & lead2byte) >>> 6);}break;case 6:currentByte = (char) (from[i] & last2byte);currentByte = (char) (currentByte << 4);if (i + 1 < from.length) {currentByte = (char) (currentByte | (from[i + 1] & lead4byte) >>> 4);}}to.append(encodeTable[currentByte]);}}if (to.length() % 4 != 0) {for (i = 4 - to.length() % 4; i > 0; --i) {to.append("=");}}return to.toString();}
}

FileUtil.java

package utils;import java.io.*;/*** 文件读取工具类*/
public class FileUtil {/*** 读取文件内容,作为字符串返回*/public static String readFileAsString(String filePath) throws IOException {File file = new File(filePath);if (!file.exists()) {throw new FileNotFoundException(filePath);} if (file.length() > 1024 * 1024 * 1024) {throw new IOException("File is too large");} StringBuilder sb = new StringBuilder((int) (file.length()));// 创建字节输入流  FileInputStream fis = new FileInputStream(filePath);  // 创建一个长度为10240的Bufferbyte[] bbuf = new byte[10240];  // 用于保存实际读取的字节数  int hasRead = 0;  while ( (hasRead = fis.read(bbuf)) > 0 ) {  sb.append(new String(bbuf, 0, hasRead));  }  fis.close();  return sb.toString();}/*** 根据文件路径读取byte[] 数组*/public static byte[] readFileByBytes(String filePath) throws IOException {File file = new File(filePath);if (!file.exists()) {throw new FileNotFoundException(filePath);} else {ByteArrayOutputStream bos = new ByteArrayOutputStream((int) file.length());BufferedInputStream in = null;try {in = new BufferedInputStream(new FileInputStream(file));short bufSize = 1024;byte[] buffer = new byte[bufSize];int len1;while (-1 != (len1 = in.read(buffer, 0, bufSize))) {bos.write(buffer, 0, len1);}byte[] var7 = bos.toByteArray();return var7;} finally {try {if (in != null) {in.close();}} catch (IOException var14) {var14.printStackTrace();}bos.close();}}}
}

GetAccessToken.java(需要输入自己应用的API Key和Secret Key哦)

package utils;import org.json.JSONObject;import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
import java.util.Map;/*** 获取token类*/
public class GetAccessToken {/*** 获取权限token* @return 返回示例:* {* "access_token": "24.460da4889caad24cccdb1fea17221975.2592000.1491995545.282335-1234567",* "expires_in": 2592000* }*/public static String getAuth() {// 官网获取的 API Key 更新为你注册的String clientId = "XXXXXXXXXXXXXXXXXXXXXXX";// 官网获取的 Secret Key 更新为你注册的String clientSecret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";return getAuth(clientId, clientSecret);}/*** 获取API访问token* 该token有一定的有效期,需要自行管理,当失效时需重新获取.* @param ak - 百度云官网获取的 API Key* @param sk - 百度云官网获取的 Secret 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=" + ak// 3. 官网获取的 Secret Key+ "&client_secret=" + sk;try {URL realUrl = new URL(getAccessTokenUrl);// 打开和URL之间的连接HttpURLConnection connection = (HttpURLConnection) realUrl.openConnection();connection.setRequestMethod("GET");connection.connect();// 获取所有响应头字段Map> 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;}}

GsonUtils.java

/** Copyright (C) 2017 Baidu, Inc. All Rights Reserved.*/
package utils;import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonParseException;import java.lang.reflect.Type;/*** Json工具类.*/
public class GsonUtils {private static Gson gson = new GsonBuilder().create();public static String toJson(Object value) {return gson.toJson(value);}public static  T fromJson(String json, Class classOfT) throws JsonParseException {return gson.fromJson(json, classOfT);}public static  T fromJson(String json, Type typeOfT) throws JsonParseException {return (T) gson.fromJson(json, typeOfT);}
}

HttpUtil.java

package utils;import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
import java.util.Map;/*** http 工具类*/
public class HttpUtil {public static String post(String requestUrl, String accessToken, String params)throws Exception {String contentType = "application/x-www-form-urlencoded";return HttpUtil.post(requestUrl, accessToken, contentType, params);}public static String post(String requestUrl, String accessToken, String contentType, String params)throws Exception {String encoding = "UTF-8";if (requestUrl.contains("nlp")) {encoding = "GBK";}return HttpUtil.post(requestUrl, accessToken, contentType, params, encoding);}public static String post(String requestUrl, String accessToken, String contentType, String params, String encoding)throws Exception {String url = requestUrl + "?access_token=" + accessToken;return HttpUtil.postGeneralUrl(url, contentType, params, encoding);}public static String postGeneralUrl(String generalUrl, String contentType, String params, String encoding)throws Exception {URL url = new URL(generalUrl);// 打开和URL之间的连接HttpURLConnection connection = (HttpURLConnection) url.openConnection();connection.setRequestMethod("POST");// 设置通用的请求属性connection.setRequestProperty("Content-Type", contentType);connection.setRequestProperty("Connection", "Keep-Alive");connection.setUseCaches(false);connection.setDoOutput(true);connection.setDoInput(true);// 得到请求的输出流对象DataOutputStream out = new DataOutputStream(connection.getOutputStream());out.write(params.getBytes(encoding));out.flush();out.close();// 建立实际的连接connection.connect();// 获取所有响应头字段Map> headers = connection.getHeaderFields();// 遍历所有的响应头字段for (String key : headers.keySet()) {System.err.println(key + "--->" + headers.get(key));}// 定义 BufferedReader输入流来读取URL的响应BufferedReader in = null;in = new BufferedReader(new InputStreamReader(connection.getInputStream(), encoding));String result = "";String getLine;while ((getLine = in.readLine()) != null) {result += getLine;}in.close();System.err.println("result:" + result);return result;}
}
测试类

FaceDetect.java(写入路径然后运行就行)

import com.baidu.aip.util.Base64Util;
import utils.FileUtil;
import utils.GetAccessToken;
import utils.HttpUtil;
import utils.GsonUtils;
import java.util.*;/*** 人脸检测与属性分析*/
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() {// 请求urlString url = "https://aip.baidubce.com/rest/2.0/face/v3/detect";try {Map map = new HashMap<>();//这里需要将本地图片进行Base64编码byte[] bytes = FileUtil.readFileByBytes("e:\\11.jpg");String img = Base64Util.encode(bytes);map.put("image", img);map.put("face_field", "faceshape,facetype");//这里也要改成BASE64map.put("image_type", "BASE64");String param = GsonUtils.toJson(map);// 注意这里仅为了简化编码每一次请求都去获取access_token,线上环境access_token有过期时间, 客户端可自行缓存,过期后重新获取。String accessToken = GetAccessToken.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) {FaceDetect.faceDetect();}
}

测试结果:

请添加图片描述

Test.java(这个要输入AppID、 API Key 、Secret Key 和图片路径)

import com.baidu.aip.face.AipFace;
import org.apache.commons.codec.binary.Base64;
import org.json.JSONArray;
import org.json.JSONObject;import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;public class Test {//设置AppID、API Key和Secret Keypublic static final String APP_ID = "XXXXXXXXXXXXXX";public static final String API_KEY = "XXXXXXXXXXXXXXXXXXXXXXXXXX";public static final String SECRET_KEY = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";public static void main(String[] args) {String image = base64();String imageType = "BASE64";// 初始化一个AipFaceAipFace client = new AipFace(APP_ID, API_KEY, SECRET_KEY);// 可选:设置网络连接参数client.setConnectionTimeoutInMillis(2000);client.setSocketTimeoutInMillis(60000);// 可选:设置代理服务器地址, http和socket二选一,或者均不设置
//        client.setHttpProxy("proxy_host", proxy_port);  // 设置http代理
//        client.setSocketProxy("proxy_host", proxy_port);  // 设置socket代理// 传入可选参数调用接口,根据需求自行设置HashMap options = new HashMap();options.put("face_field", "age,beauty,expression,face_shape,gender,glasses,race,eye_status,emotion,face_type");
//        options.put("max_face_num", "2");
//        options.put("face_type", "LIVE");
//        options.put("liveness_control", "LOW");JSONObject res = client.detect(image, imageType, options);if (res.getString("error_msg") != null && res.getString("error_msg").equals("SUCCESS")) {JSONArray faceList = res.getJSONObject("result").getJSONArray("face_list");JSONObject jsonObject = faceList.getJSONObject(0);System.out.println("年龄:" + jsonObject.getInt("age"));// 美丑打分,范围0-100,越大表示越美。System.out.println("美丑打分:" + jsonObject.getDouble("beauty"));// none:不笑;smile:微笑;laugh:大笑System.out.println("表情:" + jsonObject.getJSONObject("expression").getString("type"));// square: 正方形 triangle:三角形 oval: 椭圆 heart: 心形 round: 圆形System.out.println("脸型:" + jsonObject.getJSONObject("face_shape").getString("type"));// male:男性 female:女性System.out.println("性别:" + jsonObject.getJSONObject("gender").getString("type"));// yellow: 黄种人 white: 白种人 black:黑种人 arabs: 阿拉伯人System.out.println("人种:" + jsonObject.getJSONObject("race").getString("type"));// [0,1]取值,越接近0闭合的可能性越大System.out.println("右眼状态(睁开/闭合):" + jsonObject.getJSONObject("eye_status").getInt("right_eye"));System.out.println("左眼状态(睁开/闭合):" + jsonObject.getJSONObject("eye_status").getInt("left_eye"));System.out.println("人脸置信度,范围【0~1】:" + jsonObject.getInt("face_probability"));// none:无眼镜,common:普通眼镜,sun:墨镜System.out.println("是否带眼镜:" + jsonObject.getJSONObject("glasses").getString("type"));// angry:愤怒 disgust:厌恶 fear:恐惧 happy:高兴 sad:伤心 surprise:惊讶 neutral:无情绪System.out.println("情绪:" + jsonObject.getJSONObject("emotion").getString("type"));// human: 真实人脸 cartoon: 卡通人脸System.out.println("真实人脸/卡通人脸:" + jsonObject.getJSONObject("face_type").getString("type"));System.out.println("face_token:" + jsonObject.getString("face_token"));} else {System.out.println(res.toString());}}public static String base64() {//将图片文件转化为字节数组字符串,并对其进行Base64编码处理InputStream in = null;byte[] data = null;//读取图片字节数组try {in = new FileInputStream("e:\\11.jpg");data = new byte[in.available()];in.read(data);in.close();} catch (IOException e) {e.printStackTrace();}return new String(Base64.encodeBase64(data));}
}

测试结果:

请添加图片描述

二、人脸对比

步骤

1、百度开放平台

获取Java-SDK文档

在百度开放平台中选择技术文档

请添加图片描述

然后在技术文档选择SDK文档—Java-SDK—然后如图

请添加图片描述

下载Java-SDK的demo源码:

JAVA SDK下载地址:https://github.com/Baidu-AIP/java-sdk

demo的目录结构

请添加图片描述

需要添加的maven依赖

请添加图片描述

pom.xml(本例子好像并没有用到)

com.baidu.aipjava-sdk${version}

2、idea创建demo

首先创建一个springboot项目(maven啥的应该也可以,但是结构要自己搞😬)

然后文件我是粘过来的

项目结构如图

请添加图片描述

其中face包中的AipFace类是百度提供给我们的人脸识别相关接口的工具类,这是主要要用到的

请添加图片描述

然后可以准备两张图片来先测试一下

测试

新建一个测试类Test.java

分别将自己应用的 AppID 、 API Key 、 Secret Key和准备的两张图片路径放进去改一下运行即可

package com.r.demo3;import com.r.demo3.face.AipFace;
import com.r.demo3.face.MatchRequest;
import org.json.JSONObject;
import sun.misc.BASE64Encoder;import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;/*** @Author Tuerlechat,* @Date 2022/11/9*/
public class Test {public static final String APP_ID = "---你的APPID---";public static final String API_KEY = "---你的APIKEY---";public static final String SECRET_KEY = "---你的SECRETKEY---";public static void main(String[] args) {AipFace aipFace = new AipFace(APP_ID, API_KEY, SECRET_KEY);//准备的两张图片String img1="e:\\测试\\1.jpg";String img2="e:\\测试\\2.jpg";//两张不一样的图片String getImageStr1 = GetImageStr(img1);String getImageStr2 = GetImageStr(img2);//        String getImageStr3 = GetImageStr(img1);List input = new ArrayList<>();MatchRequest mr1 = new MatchRequest(getImageStr1, "BASE64");MatchRequest mr2 = new MatchRequest(getImageStr2, "BASE64");
//        MatchRequest mr2 = new MatchRequest(getImageStr3, "BASE64");input.add(mr1);input.add(mr2);JSONObject match = aipFace.match(input);System.out.println(match);}public static String GetImageStr(String imgFile) {//将图片文件转化为字节数组字符串,并对其进行Base64编码处理InputStream in = null;byte[] data = null;//读取图片字节数组try {in = new FileInputStream(imgFile);data = new byte[in.available()];in.read(data);in.close();} catch (IOException e) {e.printStackTrace();}//对字节数组Base64编码BASE64Encoder encoder = new BASE64Encoder();return encoder.encode(data);//返回Base64编码过的字节数组字符串}}

我用了两张自己的照片,运行可以看到结果显示

请添加图片描述

请求成功然后相似度99点多😂

然后可以建一个controller来访问前端页面验证登录测试

人脸登录测试

controller层

这里还是需要你的自己应用的 AppID 、 API Key 、 Secret Key,这里还有一张图片路径是一会用于验证登录

FaceController.java

package com.r.demo3.controller;import com.r.demo3.face.AipFace;
import com.r.demo3.face.MatchRequest;
import org.json.JSONObject;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import sun.misc.BASE64Encoder;import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;/*** @Author Tuerlechat,* @Date 2022/11/9*/
@RestController
@RequestMapping("/Face")
public class FaceController {public static final String APP_ID = "---你的APPID---";public static final String API_KEY = "---你的APIKEY---";public static final String SECRET_KEY = "---你的SECRETKEY---";@PostMapping( "/test")public String Test(@RequestParam("image") String image) {String substring = image.substring("data:image/jpeg;base64,".length());AipFace aipFace = new AipFace(APP_ID, API_KEY, SECRET_KEY);String img1="e:\\Shardddnshot.jpg";//两张不一样的图片String getImageStr1 = GetImageStr(img1);List input = new ArrayList<>();MatchRequest mr1 = new MatchRequest(getImageStr1, "BASE64");MatchRequest mr2 = new MatchRequest(substring, "BASE64");input.add(mr1);input.add(mr2);JSONObject match = aipFace.match(input);System.out.println(match);return match.toString();}public static String GetImageStr(String imgFile) {//将图片文件转化为字节数组字符串,并对其进行Base64编码处理InputStream in = null;byte[] data = null;//读取图片字节数组try {in = new FileInputStream(imgFile);data = new byte[in.available()];in.read(data);in.close();} catch (IOException e) {e.printStackTrace();}//对字节数组Base64编码BASE64Encoder encoder = new BASE64Encoder();return encoder.encode(data);//返回Base64编码过的字节数组字符串}
}

前端页面

photo.html(记得改一下页面中的jquery路径)


人脸验证登录


开始摄像
拍照
登录

然后启动springboot,访问photo.html

进来之后是这样的:

请添加图片描述

tips:如果没输错东西但是点击开始摄像却没摄像头的话,在url地址栏右侧那个小摄像机打开开启电脑相机的权限,像这样

请添加图片描述

不方便露脸,所以用了两张jisoo和rose的照片来测试一下🤓

请添加图片描述

可以看到是能够成功登录的,说明人脸验证成功

换一张试试

请添加图片描述

可以看到登录失败,说明人脸验证是生效的

这样就搞好啦😁

相关内容

热门资讯

中国电信人工电话多少 中国电信... 当我们在使用中国移动、中国电信和中国联通提供的电信业务时,可能会发生争议。建议直接向服务提供商投诉,...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
坐月子十大禁忌 坐月子的风俗禁... 前段时间,伊能静发微博说生两个孩子都40多天没洗澡,每天都用药水擦了擦身体。但也强调了,月子怎么做是...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...