Java后端 + 百度SDK实现人脸识别
人工智能越来越贴近我们的生活,相信大家也经常接触到人脸识别,手机付款、app注册验证、门禁等等。
如果要用Java后台使用这些功能,那么需要怎么做呢?请看完下面这篇文章,就能轻松、简单入门了!
手把手教你实现人脸识别、人脸对比
- 注册百度账号 https://ai.baidu.com/
打开网站,注册百度账号并登录。然后按图1的提示进行操作。
在图1中,选择 “人脸检测” 跳转到 图2。
在图2中 点击 “立即使用” 然后跳转到 图3。
在图3中 点击“创建应用” 然后跳转到 图4.
在图4中 完成应用申请 然后就有了图5(我们最终需要的就是这个 刚创建应用的参数AppID等)
图1:
图2:
图3:
图4:
图5:
- Java SDK 文档地址:https://ai.baidu.com/docs#/Face-Java-SDK/top
这里有详细的API文档。
- pom.xml 配置:
<dependency>
<groupId>com.baidu.aip</groupId>
<artifactId>java-sdk</artifactId>
<version>4.10.0</version>
</dependency>
- 人脸识别java类
下面的 APPID/AK/SK 改成你的,找2张人像图片在线生成Base64然后复制在下面就可以测试了。
import com.baidu.aip.face.AipFace;
import com.baidu.aip.face.MatchRequest;
import org.apache.commons.codec.binary.Base64;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.HashMap;
public class FaceTest {
//设置APPID/AK/SK
private static String APP_ID = "改成你的图5中的参数";
private static String API_KEY = "改成你的图5中的参数";
private static String SECRET_KEY = "改成你的图5中的参数";
public static void main(String[] args) {
// 初始化一个AipFace
AipFace 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代理
/** START 获取读取 图片Base64编码 **/
// 方法一:
String image1 = "找一张有人脸的图片,在线图片生成Base64编码 然后复制到这里";
String image2 = "找一张有人脸的图片,在线图片生成Base64编码 然后复制到这里";
// 方法二:
/*
// 读本地图片
byte[] bytes = FileUtils.fileToBytes("D:\\Documents\\Pictures\\fc.jpg");
byte[] bytes2 = FileUtils.fileToBytes("D:\\Documents\\Pictures\\fj.jpg");
// 将字节转base64
String image1 = Base64.encodeBase64String(bytes);
String image2 = Base64.encodeBase64String(bytes2);
*/
/** END 获取读取 图片Base64编码 **/
// 人脸对比
// image1/image2也可以为url或facetoken, 相应的imageType参数需要与之对应。
MatchRequest req1 = new MatchRequest(image1, "BASE64");
MatchRequest req2 = new MatchRequest(image2, "BASE64");
ArrayList<MatchRequest> requests = new ArrayList<MatchRequest>();
requests.add(req1);
requests.add(req2);
JSONObject res = client.match(requests);
System.out.println(res.toString(2));
// 人脸检测
// 传入可选参数调用接口
HashMap<String, String> options = new HashMap<String, String>();
options.put("face_field", "age");
options.put("max_face_num", "2");
options.put("face_type", "LIVE");
options.put("liveness_control", "LOW");
JSONObject res2 = client.detect(image1, "BASE64", options);
System.out.println(res2.toString(2));
}
}
上面方法二中的相关类:
Base64.encodeBase64String(bytes) 来自 import org.apache.commons.codec.binary.Base64;
FileUtils.fileToBytes(“D:\Documents\Pictures\fc.jpg”);
FileUtils类 如下:
package com.weixin.demo.utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
public class FileUtils {
protected static Logger logger = LoggerFactory.getLogger(FileUtils.class);
public static byte[] fileToBytes(String filePath) {
byte[] buffer = null;
File file = new File(filePath);
FileInputStream fis = null;
ByteArrayOutputStream bos = null;
try {
fis = new FileInputStream(file);
bos = new ByteArrayOutputStream();
byte[] b = new byte[1024];
int n;
while ((n = fis.read(b)) != -1) {
bos.write(b, 0, n);
}
buffer = bos.toByteArray();
} catch (FileNotFoundException ex) {
ex.printStackTrace();
logger.error("", ex);
} catch (IOException ex) {
ex.printStackTrace();
logger.error("", ex);
} finally {
try {
if (null != bos) {
bos.close();
}
} catch (IOException ex) {
ex.printStackTrace();
logger.error("", ex);
} finally {
try {
if (null != fis) {
fis.close();
}
} catch (IOException ex) {
ex.printStackTrace();
logger.error("", ex);
}
}
}
return buffer;
}
public static void bytesToFile(byte[] buffer, final String filePath) {
File file = new File(filePath);
OutputStream output = null;
BufferedOutputStream bufferedOutput = null;
try {
output = new FileOutputStream(file);
bufferedOutput = new BufferedOutputStream(output);
bufferedOutput.write(buffer);
} catch (FileNotFoundException ex) {
ex.printStackTrace();
logger.error("", ex);
} catch (IOException ex) {
ex.printStackTrace();
logger.error("", ex);
} finally {
if (null != bufferedOutput) {
try {
bufferedOutput.close();
} catch (IOException ex) {
ex.printStackTrace();
logger.error("", ex);
}
}
if (null != output) {
try {
output.close();
} catch (IOException ex) {
ex.printStackTrace();
logger.error("", ex);
}
}
}
}
public static void bytesToFile(byte[] buffer, File file) {
OutputStream output = null;
BufferedOutputStream bufferedOutput = null;
try {
output = new FileOutputStream(file);
bufferedOutput = new BufferedOutputStream(output);
bufferedOutput.write(buffer);
} catch (FileNotFoundException ex) {
ex.printStackTrace();
logger.error("", ex);
} catch (IOException ex) {
ex.printStackTrace();
logger.error("", ex);
} finally {
if (null != bufferedOutput) {
try {
bufferedOutput.close();
} catch (IOException ex) {
ex.printStackTrace();
logger.error("", ex);
}
}
if (null != output) {
try {
output.close();
} catch (IOException ex) {
ex.printStackTrace();
logger.error("", ex);
}
}
}
}
/**
* byte数组转换成16进制字符串
*
* @param src
* @return
*/
public static String bytesToHexString(byte[] src) {
StringBuilder stringBuilder = new StringBuilder();
if (src == null || src.length <= 0) {
return null;
}
for (int i = 0; i < src.length; i++) {
int v = src[i] & 0xFF;
String hv = Integer.toHexString(v);
if (hv.length() < 2) {
stringBuilder.append(0);
}
stringBuilder.append(hv);
}
return stringBuilder.toString();
}
/**
* 根据文件流读取图片文件真实类型
*/
public static String getTypeByBytes(byte[] fileBytes) {
byte[] b = new byte[4];
System.arraycopy(fileBytes, 0, b, 0, b.length);
String type = bytesToHexString(b).toUpperCase();
if (type.contains("FFD8FF")) {
return "jpg";
} else if (type.contains("89504E47")) {
return "png";
} else if (type.contains("47494638")) {
return "gif";
} else if (type.contains("49492A00")) {
return "tif";
} else if (type.contains("424D")) {
return "bmp";
}
return type;
}
public static String getTypeByFile(File file) {
String fileName = file.getName();
return fileName.substring(fileName.lastIndexOf(".") + 1);
}
public static String getTypeByFilePath(String filePath) {
return filePath.substring(filePath.lastIndexOf(".") + 1);
}
public static byte[] toByteArray(InputStream input) throws IOException {
ByteArrayOutputStream output = new ByteArrayOutputStream();
byte[] buffer = new byte[4096];
int n = 0;
while (-1 != (n = input.read(buffer))) {
output.write(buffer, 0, n);
}
return output.toByteArray();
}
}
“人脸对比” 测试结果:
主要看 score 参数,越高越匹配。满分100分。
0 [main] INFO com.baidu.aip.client.BaseClient - get access_token success. current state: STATE_AIP_AUTH_OK
2 [main] DEBUG com.baidu.aip.client.BaseClient - current state after check priviledge: STATE_TRUE_AIP_USER
{
"result": {
"score": 90.39932251,
"face_list": [
{"face_token": "594b9857e1bc1a6f0bb6fa7183ca962d"},
{"face_token": "f552428debe38d54081dfbce5d6d6e1e"}
]
},
"log_id": 1345050756015080031,
"error_msg": "SUCCESS",
"cached": 0,
"error_code": 0,
"timestamp": 1565601508
}
“人脸检测” 测试结果:
{
"result": {
"face_num": 1,
"face_list": [{
"liveness": {"livemapscore": 1},
"angle": {
"roll": -3.24,
"pitch": 13.22,
"yaw": 7.82
},
"face_token": "594b9857e1bc1a6f0bb6fa7183ca962d",
"location": {
"top": 570.86,
"left": 197.56,
"rotation": 1,
"width": 339,
"height": 325
},
"face_probability": 1,
"age": 23
}]
},
"log_id": 1368654456015085521,
"error_msg": "SUCCESS",
"cached": 0,
"error_code": 0,
"timestamp": 1565601508
}
人脸检测 相关请求参数、返回参数解释。(详情请访问第2点的SDK地址:即 https://ai.baidu.com/docs#/Face-Java-SDK/top)
人脸对比 相关请求参数、返回参数解释。(详情请访问第2点的SDK地址:即 https://ai.baidu.com/docs#/Face-Java-SDK/top)