java调用face_java使用face++简单实现人脸识别注册登录

前言

人脸识别,好高大上!!!

理解之后很简单。

支付宝使用的就是face++,

至于face++账号信息,apikey…..,本文不做讲述,网上很多.

一.设计思想

1. 先想一想,如果让你实现人脸识别,你会怎么做?

寻找图片上的关键点,制作一套算法,分析脸部信息,将得到的数据存入数据库,

登录的时候,通过同样的算法,分析数据,和数据库中存入的信息进行比对……

工作量好大!!!

face++有着它独有的非常优秀的算法,我们可以将我们的图片上传到face++服务器来获取对应的图片数据,剩下的事情就很简单了

2. 四个face++ api简介:

这里只介绍用到的api,

2.1 使用api肯定需要先注册一下信息,获取api_key和api_secret,可以注册试用的进行获取

2.2 create

作用: 创建一个FaceSet,创建一个脸部信息集合,引用官网的描述:

参数:api_key,api_secret,……

返回值: faceset_token, outer_id……,这里写的两个返回值需要记住,是这个脸部信息集合的唯一标识,具体返回值信息如下图:

2.3 addFace

作用:向脸部信息集合faceSet添加一条或多条脸部信息,便于后期搜索

参数: 不用说,肯定需要,api_key,api_secret,faceSet_token或outer_id(脸部信息唯一标识),还有图片信息,官网截图:

返回值:可以获取插入的结果信息

.

2.4 Search

作用: 传入一张图片信息到face++服务器,会返回最相似的face_token

参数:api_key,api_secret,image_url或image_file或image_base64或face_token,详细参数列表如下

返回值:返回值包含和你传入图片信息最像的图片的face_token,(可以再和数据库中对应的信息进行比较)

2.4 Detect

作用:

传入一张图片信息,获取这张图片的face_token,注意,一张相同图片获取多次的face_token不同

参数:api_key,api_secret, image_url或image_file或image_base64,

返回值:图片对应的face_token

在faces中包含face_token

3. 设计分析创建调用create api创建faceSet,取得faceSet_token,对应你的一张用户信息表

注册时:调用detect api传入用户注册的图片信息,获取face_token,

将face_token存入faceSet,(调用addFace api存入)

将face_token存入数据库登录: 从前端获取用户图片,将图片编码为base64作为参数image_base64调用search api

返回值为在faceSet中,和传入图片相似度高的face_token

通过返回的face_token,在数据库中进行查询,实现登陆

二.用到的技术

有了上面的分析,即使使用javaweb也能实现了

本案例使用

maven

java的ssm框架

配上Druid连接池

前端使用了jquery,(不懂前端,通过参考和自己设计写的很low)

三.实现

3.1前端界面:

实体类:

User{

String username;

String password;

String other; //在本案例中没有作用

String faceToken;

}

技术不高,自己写的一个简单的界面

注册界面:register.html

Title

* {

margin: 0;

padding: 0;

}

html, body {

width: 100%;

height: 100%;

}

body {

background: url(img/bg.jpg) no-repeat center;

}

h1 {

color: #fff;

text-align: center;

line-height: 80px;

}

.media {

width: 534px;

height: 400px;

margin: 40px auto 0;

transform-style: preserve-3d;

transform: perspective(600px) rotateY(25deg);

}

#register {

width: 200px;

height: 50px;

background: #0089ff;

margin: 60px auto 0;

text-align: center;

line-height: 50px;

color: #fff;

/* color: red;*/

border-radius: 16px;

transform-style: preserve-3d;

transform: perspective(600px) rotateY(25deg) rotateZ(-10deg);

cursor: pointer;

}

用户名:

密码 :

备注字段:

//这里写的是网页脚本

//调用摄像头获取媒体视频流

/***

* 默认的写法:navigator.getUserMedia

* 火狐:navigator.mozGetUserMedia

* 微软:navigator.msGetUserMedia

* 谷歌:navigator.webkitGetUserMedia

*

* @type {((constraints: MediaStreamConstraints, successCallback: NavigatorUserMediaSuccessCallback, errorCallback: NavigatorUserMediaErrorCallback) => void) | *}

*/

var getUserMedia = (navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia);

var video = document.getElementById("myVideo");

/***

* 四个参数 getUserMedia.call(navigator,{video:true,audio:false},function(){},function(){});

* 1.要调用的对象

* 2.约束对象:eg:只调用视频

* 3.调用成功的方法

* 4.调用失败的方法

*/

getUserMedia.call(navigator, {video: true, audio: false}, function (localMediaStream) {

//这里是调用成功的方法,如果调用成功,将视频流对象传到myVideo,localMediaStream是传入的视频流对象

/*document.getElementById("myVideo").src= window.URL.createObjectURL(localMediaStream);

* 上一行的代码已经过时了

* */

try {

video.src = window.URL.createObjectURL(localMediaStream);

} catch (e) {

//执行的是这段代码

video.srcObject = localMediaStream;

}

/***

* 下面三行代码可以代替了video的autoplay属性

*/

/* video.onloadedmetadata = function () {

video.play();

}*/

}, function (e) {

console.log("获取摄像头失败", e);//通过控制台将我们的错误信息打印

});

//获取登陆按钮

var btn_register = document.getElementById("register");

var toUpPic = document.getElementById("toUpPic");

//获取canvas对象

var canvas = document.getElementById("myCanvas");

//获取上下文对象

var context = canvas.getContext("2d");

//登陆按钮绑定点击事件

toUpPic.onclick = function () {

//点击登录按钮获取面部信息,(点击登录按钮的时候将图像画到)

// context.drawImage(video,x轴开始位置,y轴开始位置,x轴结束位置,y轴结束位置);

context.drawImage(video, 0, 0, 534, 400);

//image/png 表示画成什么格式

var imgSrc = document.getElementById("myCanvas").toDataURL("image/png");

alert(imgSrc);

// var Baseimg=imgSrc.split(",")[1];

$.post("getFaceToken.do", {imgSrc: imgSrc}, function (faceToken) {

alert(faceToken);

if (faceToken) {

$("#faceToken").val(faceToken);

} else {

alert("登录失败,请重新扫描");

}

});

}

btn_register.οnclick=function () {

$("#registerForm").submit();

}

登录界面:login.html

Title

* {

margin: 0;

padding: 0;

}

html, body {

width: 100%;

height: 100%;

}

body {

background: url(img/bg.jpg) no-repeat center;

}

h1 {

color: #fff;

text-align: center;

line-height: 80px;

}

.media {

width: 534px;

height: 400px;

margin: 40px auto 0;

transform-style: preserve-3d;

transform: perspective(600px) rotateY(25deg);

}

#login {

width: 200px;

height: 50px;

background: #0089ff;

margin: 60px auto 0;

text-align: center;

line-height: 50px;

color: #fff;

/* color: red;*/

border-radius: 16px;

transform-style: preserve-3d;

transform: perspective(600px) rotateY(25deg) rotateZ(-10deg);

cursor: pointer;

}

登陆

//这里写的是网页脚本

//调用摄像头获取媒体视频流

/***

* 默认的写法:navigator.getUserMedia

* 火狐:navigator.mozGetUserMedia

* 微软:navigator.msGetUserMedia

* 谷歌:navigator.webkitGetUserMedia

*

* @type {((constraints: MediaStreamConstraints, successCallback: NavigatorUserMediaSuccessCallback, errorCallback: NavigatorUserMediaErrorCallback) => void) | *}

*/

var getUserMedia = (navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia);

var video = document.getElementById("myVideo");

/***

* 四个参数 getUserMedia.call(navigator,{video:true,audio:false},function(){},function(){});

* 1.要调用的对象

* 2.约束对象:eg:只调用视频

* 3.调用成功的方法

* 4.调用失败的方法

*/

getUserMedia.call(navigator, {video: true, audio: false}, function (localMediaStream) {

//这里是调用成功的方法,如果调用成功,将视频流对象传到myVideo,localMediaStream是传入的视频流对象

/*document.getElementById("myVideo").src= window.URL.createObjectURL(localMediaStream);

* 上一行的代码已经过时了

* */

try {

video.src = window.URL.createObjectURL(localMediaStream);

} catch (e) {

//执行的是这段代码

video.srcObject = localMediaStream;

}

/***

* 下面三行代码可以代替了video的autoplay属性

*/

/* video.onloadedmetadata = function () {

video.play();

}*/

}, function (e) {

console.log("获取摄像头失败", e);//通过控制台将我们的错误信息打印

});

//获取登陆按钮

var btn_login = document.getElementById("login");

//获取canvas对象

var canvas=document.getElementById("myCanvas");

//获取上下文对象

var context = canvas.getContext("2d");

//登陆按钮绑定点击事件

btn_login.onclick = function () {

//点击登录按钮获取面部信息,(点击登录按钮的时候将图像画到)

// context.drawImage(video,x轴开始位置,y轴开始位置,x轴结束位置,y轴结束位置);

context.drawImage(video, 0, 0, 534, 400);

//image/png 表示画成什么格式

var imgSrc = document.getElementById("myCanvas").toDataURL("image/png");

alert(imgSrc);

// var Baseimg=imgSrc.split(",")[1];

$.post("login.do",{imgSrc:imgSrc},function (result) {

if(result){

location.href="success.jsp";

}else{

alert("登录失败,请重新扫描");

}

})

}

3.2后端界面

face相关类,通过face++官网查到一个demo,本案例修改demo并封装了自己的信息,打成实现功能

获取到的demo:

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.URLDecoder;

import java.net.URLEncoder;

import java.util.HashMap;

import java.util.Iterator;

import java.util.Map;

import java.util.Random;

import javax.net.ssl.SSLException;

public class FaceTest {

public static void main(String[] args) throws Exception{

File file = new File("你的本地图片路径");

byte[] buff = getBytesFromFile(file);

String url = "https://api-cn.faceplusplus.com/facepp/v3/detect";

HashMap map = new HashMap<>();

HashMap byteMap = new HashMap<>();

map.put("api_key", "你的KEY");

map.put("api_secret", "你的SECRET");

map.put("return_landmark", "1");

map.put("return_attributes", "gender,age,smiling,headpose,facequality,blur,eyestatus,emotion,ethnicity,beauty,mouthstatus,eyegaze,skinstatus");

byteMap.put("image_file", buff);

try{

byte[] bacd = post(url, map, byteMap);

String str = new String(bacd);

System.out.println(str);

}catch (Exception e) {

e.printStackTrace();

}

}

private final static int CONNECT_TIME_OUT = 30000;

private final static int READ_OUT_TIME = 50000;

private static String boundaryString = getBoundary();

protected static byte[] post(String url, HashMap map, HashMap 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 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 fileEntry = (Map.Entry) 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;

}

}

哪里需要改?

四.总结

人无我有,人有我优

思路很清晰,具体实现很难!!!

实现后感觉很简单

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值