2017年下半年以来,随着iPhoneX的人脸解锁功能把人脸识别这一黑科技带入大家的视野中之后,各种有关人脸识别功能的新闻和报道层出不穷。不仅是对普通群众来说,对我们程序猿来说,百度,微软,阿里等各大公司推出的可供调用的人脸识别api也如雨后春笋一般冒出来。鉴于公司以后业务发展需要,同时也是个人兴趣所致,对调用其他公司api实现人脸识别进行了一定的技术调研,于是调研成果写成几篇博客分享出来,供大家一起交流与学习。 
今天主要来看face++这加公司的人脸识别api,选这家公司作为调研对象主要原因还是这家公司的在人脸识别上还是做得比较好的。支付宝,神州,世纪佳缘,联想都使用了这家公司的人脸识别技术。光从用户上来看实力还是得到承认的。这里把face++的官网贴出来:face++官网。感兴趣的童鞋可以去看一下。话不多说,先来看我用官方例子调用的代码:

package com.example.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.URLEncoder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Random;import javax.net.ssl.SSLException;public class FacePlus {
public static void main(String[] args) throws Exception{File file = new File("C:\\Users\\lenovo\\Desktop\\4034970a304e251f535c3f9ba486c9177f3e532e.jpg");byte[] buff = getBytesFromFile(file);String url = "https://api-cn.faceplusplus.com/facepp/v3/detect";HashMap<String, String> map = new HashMap<>();HashMap<String, byte[]> byteMap = new HashMap<>();map.put("api_key", "your api key");map.put("api_secret", "your api secrect");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<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;}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137

代码用java写的,首先new一个file,传入你要检测的人脸的路径,然后用io流将它转换为byte数组。将你要传入的参数和图片的byte数组装入两个HashMap中。说一下这里传入的参数,api_key和api_secret这两个参数是你创建的face++账户后给你的。创建账户很简单你只需要去face++的官网用邮箱或者手机号注册一下就行,不需要花钱即可长期免费使用face++的api,只是免费的账号对调用的并发量进行了限制。对于我们初期的调研测试及一些小的需求用例来说,这并不造成任何影响。所以只管去申请一个就行了。后面的参数return_landmark 表示要检测的人脸的关键点,参数设为1表示要检测83个人脸关键点,传2表示要检测106个关键点,传0表示不检测,利用这个我们可以设置人脸检测的严格程度。再往后走,return_attributes 表示返回的检测参数,可选的有gender,age,smiling,headpose,facequality,blur,eyestatus,emotion,ethnicity,beauty,mouthstatus,eyegaze,skinstatus这些参数。分别表示性别,年龄,笑容分析结果,是否佩戴眼镜,人脸姿势,人脸模糊,眼睛状态信息,情绪识别结果,人脸质量判断结果(这个参数很关键),人种分析结果,颜值识别结果,嘴部状态信息,眼球位置与视线方向信息,面部特征识别结果。运行上面这段程序,返回json字符串如下:

{"image_id": "9nXe3gisuOcnPc9aJ7VpWw==", "request_id": "1514123739,b2e92c18-9ac3-4953-9ced-c9887e3ce533", "time_used": 303, "faces": [{"landmark": {"mouth_upper_lip_left_contour2": {"y": 304, "x": 173}, "mouth_upper_lip_left_contour3": {"y": 309, "x": 177}, "mouth_lower_lip_right_contour3": {"y": 321, "x": 209}, "mouth_upper_lip_left_contour1": {"y": 301, "x": 186}, "left_eye_upper_left_quarter": {"y": 200, "x": 140}, "left_eyebrow_lower_middle": {"y": 183, "x": 144}, "contour_chin": {"y": 378, "x": 197}, "left_eyebrow_lower_left_quarter": {"y": 185, "x": 126}, "right_eyebrow_lower_left_quarter": {"y": 187, "x": 238}, "mouth_lower_lip_right_contour1": {"y": 311, "x": 214}, "mouth_lower_lip_left_contour2": {"y": 315, "x": 170}, "left_eye_bottom": {"y": 212, "x": 151}, "mouth_lower_lip_bottom": {"y": 322, "x": 195}, "contour_left9": {"y": 374, "x": 170}, "mouth_lower_lip_top": {"y": 311, "x": 195}, "right_eyebrow_upper_middle": {"y": 176, "x": 257}, "right_eyebrow_left_corner": {"y": 185, "x": 221}, "right_eye_bottom": {"y": 213, "x": 250}, "contour_left7": {"y": 345, "x": 130}, "contour_left6": {"y": 326, "x": 115}, "contour_left5": {"y": 304, "x": 105}, "contour_left4": {"y": 280, "x": 99}, "contour_left3": {"y": 255, "x": 97}, "contour_left2": {"y": 231, "x": 95}, "contour_left1": {"y": 207, "x": 95}, "left_eye_lower_left_quarter": {"y": 210, "x": 140}, "mouth_upper_lip_top": {"y": 303, "x": 195}, "contour_right3": {"y": 260, "x": 297}, "contour_right2": {"y": 237, "x": 301}, "mouth_left_corner": {"y": 308, "x": 160}, "contour_right4": {"y": 283, "x": 293}, "contour_right7": {"y": 346, "x": 262}, "left_eyebrow_left_corner": {"y": 189, "x": 110}, "nose_right": {"y": 270, "x": 226}, "right_eye_upper_right_quarter": {"y": 205, "x": 261}, "nose_tip": {"y": 263, "x": 197}, "contour_right5": {"y": 306, "x": 286}, "nose_contour_lower_middle": {"y": 280, "x": 198}, "right_eye_top": {"y": 202, "x": 249}, "mouth_lower_lip_left_contour3": {"y": 320, "x": 181}, "right_eye_right_corner": {"y": 211, "x": 271}, "right_eye_lower_right_quarter": {"y": 213, "x": 260}, "mouth_upper_lip_right_contour2": {"y": 306, "x": 219}, "right_eyebrow_lower_right_quarter": {"y": 191, "x": 273}, "left_eye_left_corner": {"y": 207, "x": 130}, "mouth_right_corner": {"y": 312, "x": 234}, "mouth_upper_lip_right_contour3": {"y": 311, "x": 214}, "right_eye_lower_left_quarter": {"y": 212, "x": 240}, "left_eyebrow_right_corner": {"y": 184, "x": 181}, "left_eyebrow_lower_right_quarter": {"y": 184, "x": 162}, "right_eye_center": {"y": 209, "x": 250}, "left_eye_upper_right_quarter": {"y": 201, "x": 164}, "mouth_lower_lip_left_contour1": {"y": 310, "x": 178}, "contour_left8": {"y": 361, "x": 148}, "nose_left": {"y": 269, "x": 171}, "right_eyebrow_lower_middle": {"y": 188, "x": 256}, "left_eye_top": {"y": 198, "x": 152}, "left_eye_center": {"y": 206, "x": 152}, "left_eye_lower_right_quarter": {"y": 211, "x": 163}, "nose_contour_right1": {"y": 213, "x": 214}, "contour_right9": {"y": 374, "x": 223}, "right_eye_left_corner": {"y": 210, "x": 230}, "left_eyebrow_upper_left_quarter": {"y": 175, "x": 124}, "left_eye_pupil": {"y": 204, "x": 152}, "right_eyebrow_upper_left_quarter": {"y": 176, "x": 238}, "contour_right8": {"y": 362, "x": 245}, "right_eyebrow_right_corner": {"y": 195, "x": 289}, "right_eye_upper_left_quarter": {"y": 204, "x": 239}, "left_eyebrow_upper_middle": {"y": 171, "x": 144}, "right_eyebrow_upper_right_quarter": {"y": 181, "x": 275}, "nose_contour_left1": {"y": 212, "x": 185}, "nose_contour_left2": {"y": 252, "x": 177}, "mouth_upper_lip_right_contour1": {"y": 302, "x": 204}, "contour_right1": {"y": 213, "x": 302}, "nose_contour_right2": {"y": 253, "x": 220}, "mouth_lower_lip_right_contour2": {"y": 317, "x": 222}, "contour_right6": {"y": 327, "x": 276}, "nose_contour_right3": {"y": 276, "x": 212}, "nose_contour_left3": {"y": 276, "x": 183}, "left_eye_right_corner": {"y": 209, "x": 173}, "left_eyebrow_upper_right_quarter": {"y": 173, "x": 164}, "right_eye_pupil": {"y": 207, "x": 250}, "mouth_upper_lip_bottom": {"y": 310, "x": 195}}, "attributes": {"emotion": {"sadness": 0.0, "neutral": 100.0, "disgust": 0.0, "anger": 0.0, "surprise": 0.0, "fear": 0.0, "happiness": 0.0}, "beauty": {"female_score": 79.73, "male_score": 80.154}, "gender": {"value": "Male"}, "age": {"value": 26}, "mouthstatus": {"close": 100.0, "surgical_mask_or_respirator": 0.0, "open": 0.0, "other_occlusion": 0.0}, "glass": {"value": "None"}, "skinstatus": {"dark_circle": 59.871, "stain": 66.202, "acne": 92.027, "health": 5.441}, "headpose": {"yaw_angle": 5.8753686, "pitch_angle": 7.470607, "roll_angle": 1.2101119}, "blur": {"blurness": {"threshold": 50.0, "value": 0.37}, "motionblur": {"threshold": 50.0, "value": 0.37}, "gaussianblur": {"threshold": 50.0, "value": 0.37}}, "smile": {"threshold": 30.1, "value": 1.27}, "eyestatus": {"left_eye_status": {"normal_glass_eye_open": 0.001, "no_glass_eye_close": 0.0, "occlusion": 0.0, "no_glass_eye_open": 99.999, "normal_glass_eye_close": 0.0, "dark_glasses": 0.0}, "right_eye_status": {"normal_glass_eye_open": 0.012, "no_glass_eye_close": 0.0, "occlusion": 0.0, "no_glass_eye_open": 99.988, "normal_glass_eye_close": 0.0, "dark_glasses": 0.0}}, "facequality": {"threshold": 70.1, "value": 87.66}, "ethnicity": {"value": "White"}, "eyegaze": {"right_eye_gaze": {"position_x_coordinate": 0.47, "vector_z_component": 0.961, "vector_x_component": 0.031, "vector_y_component": -0.274, "position_y_coordinate": 0.451}, "left_eye_gaze": {"position_x_coordinate": 0.507, "vector_z_component": 0.906, "vector_x_component": -0.075, "vector_y_component": -0.417, "position_y_coordinate": 0.429}}}, "face_rectangle": {"width": 207, "top": 169, "left": 95, "height": 207}, "face_token": "7a1d92282a7b6b31bbc65277cba413c2"}]}
  • 1

这时我随便选的一张照片放上去的分析结果,虽然有点乱,不过重要在展示一下调用结果。官网上有一个示例调用结果:

{"image_id": "Dd2xUw9S/7yjr0oDHHSL/Q==","request_id": "1470472868,dacf2ff1-ea45-4842-9c07-6e8418cea78b","time_used": 752,"faces": [{"landmark": {"mouth_upper_lip_left_contour2": {"y": 185,"x": 146},"contour_chin": {"y": 231,"x": 137},.............省略关键点信息 "right_eye_pupil": {"y": 146,"x": 205},"mouth_upper_lip_bottom": {"y": 195,"x": 159}},"attributes": {"gender": {"value": "Female"},"age": {"value": 21},"glass": {"value": "None"},"headpose": {"yaw_angle": -26.625063,"pitch_angle": 12.921974,"roll_angle": 22.814377},"smile": {"threshold": 30.1,"value": 2.566890001296997}},"face_rectangle": {"width": 140,"top": 89,"left": 104,"height": 141},"face_token": "ed319e807e039ae669a4d1af0922a0c8"}]
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53

实际上就是带着一大串参数的json字符串。讲完了基本的调用我们先来实现一个简单点的需求:

  • 在web应用中调用摄像头,拍下电脑前人的照片,把照片传到后台调用api再把结果传到前台。

先来实现这个简单的demo吧,后面再讲一讲更复杂的业务。我先用springboot建个项目,如下图:

引入关键的web包:

然后运行xxxApplication.java类,因为springboot自带tomcat服务器,所以不必将它放在服务器中运行就可以直接启动项目。话说springboot真是好用,又不用写一大堆配置文件,又不需要主动去找一大堆的maven依赖,直接点点点就完了,简直不要太爽。扯远了,先来看看实现效果:

一进入页面就调用摄像头将用户的头像显示在页面上(不要在意马赛克),此时,点击拍照结果如下:

点击拍照之后,会将用户的照片显示在右侧,同时将照片传入后台解析,调用api将照片传给face++检测,得到检测结果返回给前端并将结果显示在右侧文本框中。ps:由于本人摄像头及现场光线原因,拍出的照片有些模糊造成显示的年龄信息不准确(博主TM哪有45啊!!)。 
接下来把源码贴出来,先看前台网页:

<!DOCTYPE html>
<html>    <head>    <meta charset="utf-8">    <title>face++</title>    <style>  video,canvas{  border:1px solid gray;  width:400px;  height:400px;  border-radius:50%;  }     </style>  </head>    <body>    <video autoplay style="position: absolute;left: 1%"></video>  <canvas id="myCanvas" style="position: absolute;left: 30%;"></canvas>  <button id="capture" style="position: absolute;left: 30%;top: 55%">拍照</button><div id="attr" style="position: absolute;right: 200px">性别:<input type="text" id="sex"><br><br><br><br><br><br>年龄:<input type="text" id="age"><br><br><br><br><br><br>微笑程度:<input type="text" id="smile"><br><br><br><br><br><br>开心程度:<input type="text" id="emotion"><br><br></div>  <script src="http://code.jquery.com/jquery-latest.js"></script><script type="text/javascript">function hasUserMedia(){//判断是否支持调用设备api,因为浏览器不同所以判断方式不同哦    return !!(navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia);    }    if(hasUserMedia()){    //alert(navigator.mozGetUserMedia)    navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;    var video=document.querySelector("video");    var canvas=document.querySelector("canvas");  var streaming = false;  navigator.getUserMedia({    video:true,//开启视频    audio:false//先关闭音频,因为会有回响,以后两台电脑通信不会有响声    },function(stream){//将视频流交给video    video.src=window.URL.createObjectURL(stream);     streaming = true;  },function(err){    console.log("capturing",err)    });    document.querySelector("#capture").addEventListener("click",function(event){  if(streaming){  //alert(video.clientHeight)  //canvas.width = video.clientWidth;  //canvas.height= video.clientHeight;  canvas.width = 800;  canvas.height = 800;  var context = canvas.getContext('2d');  context.drawImage(video,20,20)  var info = {imgString: canvas.toDataURL("image/png")}$.post("/face",info,function(data){console.log(data);$("#sex").val(JSON.stringify(data.faces[0].attributes.gender.value))$("#age").val(JSON.stringify(data.faces[0].attributes.age.value))$("#smile").val(JSON.stringify(data.faces[0].attributes.smile.value))$("#emotion").val(JSON.stringify(data.faces[0].attributes.emotion.happiness))},"json") }  })  }else{    alert("浏览器暂不支持")    }   </script>   </body>
</html>    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86

前端页面写的简单粗暴了一点,主要是此处重在实现功能,页面以后可以交给前端和UI来优化。前台我采用了webrtc技术去调用摄像头。webrtc可以理解为是一种在浏览器中用javascript调用摄像头并进行流传输的技术,感兴趣的童鞋可以自行百度一下。 
将摄像头采集到的视频放入html5的video标签中,然后使用canvas.toDataURL(“image/png”)将得到某一帧的图片转换为base64编码过的字符串,然后将该字符串用ajax发送到后台,后台代码:

package com.example.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.URLEncoder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Random;import javax.net.ssl.SSLException;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;import sun.misc.BASE64Decoder;@Controller
public class TestController {@RequestMapping(value="/face")@ResponseBodypublic String getFace(String imgString) throws IOException {System.out.println(imgString);System.out.println(imgString.substring(imgString.indexOf(",")+1));byte[] buff = getStringImage(imgString.substring(imgString.indexOf(",")+1));String url = "https://api-cn.faceplusplus.com/facepp/v3/detect";HashMap<String, String> map = new HashMap<>();HashMap<String, byte[]> byteMap = new HashMap<>();map.put("api_key", "1ewiKTxhRrctByKOrdrfMC8Nt3BUyi6S");map.put("api_secret", "L10UARcTmmQzWlPHytExSgU1JQbPMnz3");
//      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);String str =null;try{byte[] bacd = post(url, map, byteMap);str = new String(bacd);System.out.println(str);}catch (Exception e) {e.printStackTrace();}return str;}/*** Base64字符串转 二进制流** @param base64String Base64* @return base64String* @throws IOException 异常*/public static byte[] getStringImage(String base64String) throws IOException {BASE64Decoder decoder = new sun.misc.BASE64Decoder();return base64String != null ? decoder.decodeBuffer(base64String) : null;}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<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;}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163

这里用BASE64Decoder包将base64编码的图片转换为byte数组,然后后面的程序就和上面的实例一样了,将byte数组传给face++即可。

至此,一个小的调用face++实现人脸检测的demo已经实现。不过,这个demo满足不了现实中的复杂的业务场景,在后面的博客中,我会继续讲解更为复杂的业务的场景的实现,感兴趣的童鞋可以持续关注哦。

转自:https://blog.csdn.net/zoroduyu/article/details/78827627

人脸识别(一)调用face++实现人脸检测相关推荐

  1. 百度人脸识别API调用实现

    目录 一. 准备工作 A. 应用创建 1. 百度用户创建登录 2. 进入人脸识别服务 3. 应用创建 4.应用查看 B. 开发准备 1. 工具类下载 2. maven依赖注入 二. 调用实现 A. 看 ...

  2. 人脸识别接口_人工智能 人脸识别双目模组摄像头 活体检测的重要作用

    人脸识别,是基于人的脸部特征信息进行身份识别的一种生物识别技术.用摄像机或摄像头采集含有人脸的图像或视频流,并自动在图像中检测和跟踪人脸,进而对检测到的人脸进行脸部识别的一系列相关技术,通常也叫做人像 ...

  3. 阿里云人脸识别C#调用示例参考

    概述 前面介绍了关于阿里云人脸识别Java调用示例参考,本文主要介绍C#调用阿里云人脸识别服务,参数等的获取参考阿里云人脸识别使用流程简介. Code Sample 1.使用网络图片 using Sy ...

  4. 阿里云人脸识别C#调用示例参考 1

    概述 前面介绍了关于阿里云人脸识别Java调用示例参考,本文主要介绍C#调用阿里云人脸识别服务,参数等的获取参考阿里云人脸识别使用流程简介. Code Sample 1.使用网络图片 using Sy ...

  5. 人脸识别资源大列表(人脸识别检测,关键点检测 看这些就够了)

    文章内相关链接,可以直接点解页面 链接:点这里 几篇知乎 <人脸识别方向有哪些大牛?目前的发展如何? - 知乎> O从认知心理学的角度来说,人脸识别方向有哪些- <谈到人脸识别技术, ...

  6. 阿里云人脸识别PHP调用示例参考

    概述 前面分别给出了关于阿里云人脸识别Java调用示例参考.阿里云人脸识别C#调用示例参考.阿里云人脸识别Python3调用示例参考 .本文主要介绍PHP调用阿里云人脸识别服务,参数等的获取参考阿里云 ...

  7. 百度AI人脸识别接口调用

    人脸识别作为当下比较潮流的一门技术,已经应用于很多的产品之中了. 今天我们看下百度提供的人脸识别接口如何使用. 1.登录百度智能云平台 首先我们需要登录百度智能云平台,使用百度账号可以直接登录.这个不 ...

  8. 阿里云人脸识别接口调用卡顿,超时

    阿里云人脸识别接口调用卡顿 在服务端通过pom引入阿里云人脸识别sdk的时候,如果生产环境在内网开通了网络策略连接了 cloudauth.aliyuncs.com 这个地址. 但是sdk调用人脸识别服 ...

  9. 基于Emgu CV+百度人脸识别,实现视频动态 人脸抓取与识别

    背景 目前AI 处于风口浪尖,作为 公司的CTO,也作为自己的技术专研,开始了AI之旅,在朋友圈中也咨询 一些大牛对于AI 机器学习框架的看法,目前自己的研究方向主要开源的 AI 库,如:Emgu C ...

  10. python人脸识别门禁_树莓派人脸识别门禁系统图文教程

    前面发布了人脸识别门禁系统的系列视频教程,现在补上图文版,方便查看指令和代码,这篇文章也是对之前的文章的更新与完善. 本系统中树莓派调用百度智能云人脸识别API,实现人脸识别门禁,主要分为三个模块来实 ...

最新文章

  1. Scrum敏捷开发看板工具分享
  2. jquery点击元素之外触发事件
  3. Go简单的Goroutine示例
  4. C++用递归方式实现在对不更改随机数组的情况下查找最大值
  5. jQuery上拉加载更多
  6. 51Nod 1445 变色DNA
  7. 【JZOJ6227】【20190621】ichi
  8. 进程和线程的简单对比
  9. 接口测试及服务器性能压测,接口测试及服务器性能压测
  10. Vue动态加载组件的两类方式(import和require)
  11. 最好用的文件上传插件 bootstrap fileInput
  12. (转)以太坊(Ethereum)全零地址(0x000000...)揭秘
  13. opencv 曲线拟合
  14. 苹果手机相机九宫格怎么设置_用苹果手机拍照,这3个媲美单反的设置不会用,就别说自己用苹果...
  15. 虚拟机如何进入PE系统
  16. c语言mac小游戏,Mac自带小游戏怎么玩以打发空闲时间
  17. IDM UltraEdit编辑器V26.00.0.48 烈火汉化64位版
  18. onMeasure方法
  19. Auto CAD:图纸幅面规格之图纸幅面、标题栏与会签栏、图签与布局空间之详细攻略
  20. 算法:每个元音包含偶数次的最长字符串

热门文章

  1. 破解利器C32Asm和IDApro
  2. java后台 重置手机密码(邮箱点击确认)
  3. 360 || 2021校园招聘的一道笔试题思路分享
  4. 手风琴页面html,滑动手风琴的制作(只涉及HTML+css)
  5. 酒店管理系统Python#qt
  6. 软件对硬盘性能测试,新买的固态硬盘 有哪些软件可以测试性能?
  7. 为什么要找一个不提倡加班的工作?是我我们太懒,不求上进吗?
  8. 漫漫找工路——百度、移动、华为等公司应聘经历总结
  9. 用python制作文字特效
  10. Tomcat安装、配置、优化及负载均衡详解