最近研究了一下阿里的人臉識別功能,只是調用阿里提供的接口返回數據給我們就OK了。
詳細文檔可參考阿里的api 阿里人臉識別api
人臉比對的方法
直接上代碼吧:
1 package com.guoxin.common.test; 2 3 import sun.misc.BASE64Encoder; 4 import javax.crypto.Mac; 5 import javax.crypto.spec.SecretKeySpec; 6 import org.slf4j.Logger; 7 import org.slf4j.LoggerFactory; 8 import com.alibaba.fastjson.JSON; 9 import com.alibaba.fastjson.JSONObject; 10 import java.io.*; 11 import java.net.HttpURLConnection; 12 import java.net.URL; 13 import java.net.URLConnection; 14 import java.security.MessageDigest; 15 import java.text.SimpleDateFormat; 16 import java.util.Date; 17 import java.util.Locale; 18 19 //@SuppressWarnings("restriction") 20 public class FaceDemoVerify { 21 private final static Logger logger = LoggerFactory.getLogger(FaceDemoVerify.class.getName()); 22 /* 23 * 計算MD5+BASE64 24 */ 25 public static String MD5Base64(String s) { 26 if (s == null) 27 return null; 28 String encodeStr = ""; 29 byte[] utfBytes = s.getBytes(); 30 MessageDigest mdTemp; 31 try { 32 mdTemp = MessageDigest.getInstance("MD5"); 33 mdTemp.update(utfBytes); 34 byte[] md5Bytes = mdTemp.digest(); 35 BASE64Encoder b64Encoder = new BASE64Encoder(); 36 encodeStr = b64Encoder.encode(md5Bytes); 37 } catch (Exception e) { 38 throw new Error("Failed to generate MD5 : " + e.getMessage()); 39 } 40 return encodeStr; 41 } 42 /* 43 * 計算 HMAC-SHA1 44 */ 45 public static String HMACSha1(String data, String key) { 46 String result; 47 try { 48 SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(), "HmacSHA1"); 49 Mac mac = Mac.getInstance("HmacSHA1"); 50 mac.init(signingKey); 51 byte[] rawHmac = mac.doFinal(data.getBytes()); 52 result = (new BASE64Encoder()).encode(rawHmac); 53 } catch (Exception e) { 54 throw new Error("Failed to generate HMAC : " + e.getMessage()); 55 } 56 return result; 57 } 58 /* 59 * 等同於javaScript中的 new Date().toUTCString(); 60 */ 61 public static String toGMTString(Date date) { 62 SimpleDateFormat df = new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss z", Locale.UK); 63 df.setTimeZone(new java.util.SimpleTimeZone(0, "GMT")); 64 return df.format(date); 65 } 66 /* 67 * 發送POST請求 68 */ 69 public static String sendPost(String url, String body, String ak_id, String ak_secret) throws Exception { 70 PrintWriter out = null; 71 BufferedReader in = null; 72 String result = ""; 73 int statusCode = 200; 74 try { 75 URL realUrl = new URL(url); 76 /* 77 * http header 參數 78 */ 79 String method = "POST"; 80 String accept = "application/json"; 81 String content_type = "application/json"; 82 83 // String content_type = "application/octet-stream"; 84 85 String path = realUrl.getFile(); 86 String date = toGMTString(new Date()); 87 // 1.對body做MD5+BASE64加密 88 String bodyMd5 = MD5Base64(body); 89 String stringToSign = method + "\n" + accept + "\n" + bodyMd5 + "\n" + content_type + "\n" + date + "\n" 90 + path; 91 // 2.計算 HMAC-SHA1 92 String signature = HMACSha1(stringToSign, ak_secret); 93 // 3.得到 authorization header 94 String authHeader = "Dataplus " + ak_id + ":" + signature; 95 // 打開和URL之間的連接 96 URLConnection conn = realUrl.openConnection(); 97 // 設置通用的請求屬性 98 conn.setRequestProperty("accept", accept); 99 conn.setRequestProperty("content-type", content_type); 100 conn.setRequestProperty("date", date); 101 conn.setRequestProperty("Authorization", authHeader); 102 // 發送POST請求必須設置如下兩行 103 conn.setDoOutput(true); 104 conn.setDoInput(true); 105 // 獲取URLConnection對象對應的輸出流 106 out = new PrintWriter(conn.getOutputStream()); 107 // 發送請求參數 108 out.print(body); 109 // flush輸出流的緩沖 110 out.flush(); 111 // 定義BufferedReader輸入流來讀取URL的響應 112 statusCode = ((HttpURLConnection)conn).getResponseCode(); 113 if(statusCode != 200) { 114 in = new BufferedReader(new InputStreamReader(((HttpURLConnection)conn).getErrorStream())); 115 } else { 116 in = new BufferedReader(new InputStreamReader(conn.getInputStream())); 117 } 118 String line; 119 while ((line = in.readLine()) != null) { 120 result += line; 121 } 122 } catch (Exception e) { 123 e.printStackTrace(); 124 } finally { 125 try { 126 if (out != null) { 127 out.close(); 128 } 129 if (in != null) { 130 in.close(); 131 } 132 } catch (IOException ex) { 133 ex.printStackTrace(); 134 } 135 } 136 if (statusCode != 200) { 137 throw new IOException("\nHttp StatusCode: "+ statusCode + "\nErrorMessage: " + result); 138 } 139 return result; 140 } 141 /* 142 * GET請求 143 */ 144 public static String sendGet(String url, String ak_id, String ak_secret) throws Exception { 145 String result = ""; 146 BufferedReader in = null; 147 int statusCode = 200; 148 try { 149 URL realUrl = new URL(url); 150 /* 151 * http header 參數 152 */ 153 String method = "GET"; 154 String accept = "application/json"; 155 String content_type = "application/json"; 156 157 // String content_type = "application/octet-stream"; 158 String path = realUrl.getFile(); 159 String date = toGMTString(new Date()); 160 // 1.對body做MD5+BASE64加密 161 // String bodyMd5 = MD5Base64(body); 162 String stringToSign = method + "\n" + accept + "\n" + "" + "\n" + content_type + "\n" + date + "\n" + path; 163 // 2.計算 HMAC-SHA1 164 String signature = HMACSha1(stringToSign, ak_secret); 165 // 3.得到 authorization header 166 String authHeader = "Dataplus " + ak_id + ":" + signature; 167 // 打開和URL之間的連接 168 URLConnection connection = realUrl.openConnection(); 169 // 設置通用的請求屬性 170 connection.setRequestProperty("accept", accept); 171 connection.setRequestProperty("content-type", content_type); 172 connection.setRequestProperty("date", date); 173 connection.setRequestProperty("Authorization", authHeader); 174 connection.setRequestProperty("Connection", "keep-alive"); 175 // 建立實際的連接 176 connection.connect(); 177 // 定義 BufferedReader輸入流來讀取URL的響應 178 statusCode = ((HttpURLConnection)connection).getResponseCode(); 179 if(statusCode != 200) { 180 in = new BufferedReader(new InputStreamReader(((HttpURLConnection)connection).getErrorStream())); 181 } else { 182 in = new BufferedReader(new InputStreamReader(connection.getInputStream())); 183 } 184 String line; 185 while ((line = in.readLine()) != null) { 186 result += line; 187 } 188 } catch (Exception e) { 189 e.printStackTrace(); 190 } finally { 191 try { 192 if (in != null) { 193 in.close(); 194 } 195 } catch (Exception e) { 196 e.printStackTrace(); 197 } 198 } 199 if (statusCode != 200) { 200 throw new IOException("\nHttp StatusCode: "+ statusCode + "\nErrorMessage: " + result); 201 } 202 return result; 203 } 204 public static void main(String[] args) throws Exception { 205 // 發送POST請求示例 206 String ak_id = "L.............BL"; //用戶ak 207 String ak_secret = "7W..................4EPW"; // 用戶ak_secret 208 String url = "https://dtplus-cn-shanghai.data.aliyuncs.com/face/verify"; 209 210 //上傳本地圖片 211 // Request body 212 String pic_path = "C:\\Users\\TEST\\1.jpg";//本地圖片的路徑 213 String pic_path2 = "C:\\Users\\TEST\\8.jpg";//本地圖片的路徑 214 215 File picBase64 = new File(pic_path); 216 File picBase642 = new File(pic_path2); 217 String pic = encodeImageToBase64(picBase64); 218 String pic2 = encodeImageToBase64(picBase642); 219 // String pic = encodeImageToBase64(pic_path); 220 // String pic2 = encodeImageToBase64(pic_path2); 221 //提出base64編碼的換行符問題 222 String data = pic.replaceAll("[\\s*\t\n\r]", ""); 223 String data2 = pic2.replaceAll("[\\s*\t\n\r]", ""); 224 data = "'" + data + "'"; 225 data2 = "'" + data2 + "'"; 226 String body = "{\"type\":1,\n" + 227 "\"content_1\":"+data+",\n" + 228 "\"content_2\":"+data2+"\n" + 229 "}"; 230 231 String re = sendPost(url, body, ak_id, ak_secret); 232 System.out.println("response body:" + re); 233 234 getJsonData(re); 235 } 236 237 /** 238 * 將本地圖片編碼為base64 239 * 240 * @param file 241 * @return 242 * @throws Exception 243 */ 244 public static String encodeImageToBase64(File file) throws Exception { 245 //將圖片文件轉化為字節數組字符串,並對其進行Base64編碼處理 246 // loggerger.info("圖片的路徑為:" + file.getAbsolutePath()); 247 InputStream in = null; 248 byte[] data = null; 249 //讀取圖片字節數組 250 try { 251 in = new FileInputStream(file); 252 data = new byte[in.available()]; 253 in.read(data); 254 in.close(); 255 } catch (IOException e) { 256 e.printStackTrace(); 257 throw new Exception("圖片上傳失敗,請聯系客服!"); 258 } 259 //對字節數組Base64編碼 260 BASE64Encoder encoder = new BASE64Encoder(); 261 String base64 = encoder.encode(data); 262 return base64;//返回Base64編碼過的字節數組字符串 263 } 264 265 /** 266 * 將網絡圖片編碼為base64 267 * 268 * @param url 269 * @return 270 * @throws BusinessException 271 */ 272 public static String encodeImageToBase64(URL url) throws Exception { 273 //將圖片文件轉化為字節數組字符串,並對其進行Base64編碼處理 274 logger.info("圖片的路徑為:" + url.toString()); 275 //打開鏈接 276 HttpURLConnection conn = null; 277 try { 278 conn = (HttpURLConnection) url.openConnection(); 279 //設置請求方式為"GET" 280 conn.setRequestMethod("GET"); 281 //超時響應時間為5秒 282 conn.setConnectTimeout(5 * 1000); 283 //通過輸入流獲取圖片數據 284 InputStream inStream = conn.getInputStream(); 285 //得到圖片的二進制數據,以二進制封裝得到數據,具有通用性 286 ByteArrayOutputStream outStream = new ByteArrayOutputStream(); 287 //創建一個Buffer字符串 288 byte[] buffer = new byte[1024]; 289 //每次讀取的字符串長度,如果為-1,代表全部讀取完畢 290 int len = 0; 291 //使用一個輸入流從buffer里把數據讀取出來 292 while ((len = inStream.read(buffer)) != -1) { 293 //用輸出流往buffer里寫入數據,中間參數代表從哪個位置開始讀,len代表讀取的長度 294 outStream.write(buffer, 0, len); 295 } 296 //關閉輸入流 297 inStream.close(); 298 byte[] data = outStream.toByteArray(); 299 //對字節數組Base64編碼 300 BASE64Encoder encoder = new BASE64Encoder(); 301 String base64 = encoder.encode(data); 302 // logger.info("網絡文件[{}]編碼成base64字符串:[{}]", url.toString(), base64); 303 return base64;//返回Base64編碼過的字節數組字符串 304 } catch (IOException e) { 305 e.printStackTrace(); 306 throw new Exception("圖片上傳失敗,請聯系客服!"); 307 } 308 } 309 310 311 public static void getJsonData(String re){ 312 // String s = "{\"confidence\":80.6434326171875,\"thresholds\":[61.0,69.0,75.0],\"rectA\":[92,50,74,87],\"rectB\":[171,101,118,137],\"errno\":0,\"request_id\":\"754af075-1d6b-4cb0-a709-7015eac53a7c\"}"; 313 JSONObject jsonObj = JSON.parseObject(re); 314 315 String confidence = jsonObj.getString("confidence"); 316 System.out.println(confidence); 317 } 318 }
選擇兩本地照片或者網絡,經過base64編碼處理,作為兩個參數傳入調用,人臉比對接口,返回數據。
結果 如下
{\"confidence\":80.6434326171875,\"thresholds\":[61.0,69.0,75.0],\"rectA\":[92,50,74,87],\"rectB\":[171,101,118,137],\"errno\":0,\"request_id\":\"754af075-1d6b-4cb0-a709-7015eac53a7c\"}
confidence值即為比對結果的分數,分值越大兩張臉相似度高。
