百度人脸识别api实现及demo
2016-03-17 23:57 阅读(230)

要说人脸检测、识别国内最好的还是face++,但是无奈,face++的技术支持太差了,既没有交流群,技术支持邮件也没人理。没办法,最后尝试使用百度的。

地址:https://bce.baidu.com/product/bfr.html

注意,虽然该服务表面上是免费的,但是对象存储BOS 是收费的,没有bos你没办法上传图片,不过也很便宜。

百度的人脸识别使用了rest风格的api,只需要简单的http请求即可。整个api的难点在于权限认证, 足足调了2天。

完整实例下载:https://pan.baidu.com/s/1mh4rjZy


权限认证实现:

package com.baidubce;

import java.io.UnsupportedEncodingException;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Map;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Hex;

/**
 * 认证字符串生成
 * @author pc
 *
 */
public class BceAuthString {

	
	
	/**
	 * 生成BceAuthString(认证字符串)
	 */
	public String createBceAuthString(String accessKeyID, String secretAccessKey, String httpMethod, String path, Map<String, String> header, String UTCTime){
		String authStringPrefix = "bce-auth-v1/{accessKeyId}/{timestamp}/{expirationPeriodInSeconds}";
		authStringPrefix = authStringPrefix.replace("{accessKeyId}", accessKeyID);
		authStringPrefix = authStringPrefix.replace("{timestamp}", UTCTime);
		authStringPrefix = authStringPrefix.replace("{expirationPeriodInSeconds}", "1800");
		
		String canonicalRequest = this.createCanonicalRequest(httpMethod, path, header);
		String signingKey = this.createSigningKey(secretAccessKey, authStringPrefix);		
		String signature = this.createSignature(signingKey, canonicalRequest);
		
		String signedHeaders = createSignedHeaders(header);
		String bceAuthString = authStringPrefix + "/" + signedHeaders + "/" + signature;
		return bceAuthString;
	}
	/**
	 * 创建CanonicalRequest
	 * CanonicalRequest = HTTP Method + "\n" + CanonicalURI + "\n" + CanonicalQueryString + "\n" + CanonicalHeaders
	 */
	private String createCanonicalRequest(String httpMethod, String path, Map<String, String> header){
		httpMethod = httpMethod.toUpperCase();
		
		if(path == null || path.trim().equals(""))
			path  = "";
		String canonicalURI = path;
		String canonicalQueryString = "";
		int index = path.indexOf("?");
		if(index != -1){
			canonicalURI = path.substring(0, index);
			canonicalQueryString = path.substring(index + 1);
		}
		//生成CanonicalURI
		if(!canonicalURI.startsWith("/"))
			canonicalURI = "/" + canonicalURI;
		canonicalURI = uriEncode(canonicalURI, false);
		//生成CanonicalQueryString
		String[] queryArray = canonicalQueryString.split("&");
		for(int i = 0; i<queryArray.length; i++){
			String item = queryArray[i];
			if(item == null || item.trim().equals(""))
				continue;
			String key = item.split("=")[0];
			String value = item.split("=")[1];
			key = uriEncode(key, true);
			value = uriEncode(value, true);
			queryArray[i] = key + "=" + value;
		}
		Arrays.sort(queryArray);  
		StringBuffer sb = new StringBuffer();
		for(int i = 0; i<queryArray.length; i++){
			String item = queryArray[i];
			if(item == null || item.trim().equals(""))
				continue;
			sb.append(item + "&");
		}
		if(sb.length() > 0)
			sb.deleteCharAt(sb.length() - 1);
		canonicalQueryString = sb.toString();
		
		//生成CanonicalHeaders
		String[] headerArray = new String[header.size()];
		index = 0;
		for (Map.Entry<String, String> entry : header.entrySet()) {
            String key = entry.getKey().toLowerCase();
            String value = entry.getValue().trim();
			headerArray[index] = uriEncode(key, true) + ":" + uriEncode(value, true);
			index++;
		}
		Arrays.sort(headerArray);  
		sb = new StringBuffer();
		for(int i = 0; i<headerArray.length; i++){
			String item = headerArray[i];
			sb.append(item + "\n");
		}
		String canonicalHeaders = sb.toString();	
		if(canonicalHeaders.length() > 0)
			canonicalHeaders = canonicalHeaders.substring(0, canonicalHeaders.lastIndexOf("\n"));
		
		return httpMethod + "\n" + canonicalURI + "\n" + canonicalQueryString + "\n" + canonicalHeaders;
	}
	/**
	 * 生成SigningKey 
	 * @param input
	 * @param encodeSlash
	 * @return
	 */
	private String createSigningKey(String secretAccessKey, String authStringPrefix){		
		String signingKey  = sha256Hex(secretAccessKey, authStringPrefix);
		return signingKey;
	}
	/**
	 * 生成Signature
	 * @param input
	 * @param encodeSlash
	 * @return
	 */
	private String createSignature(String signingKey, String canonicalRequest){
		String signature = sha256Hex(signingKey, canonicalRequest);
		return signature;
	}
	/**
	 * 创建signedHeaders
	 * @param input
	 * @param encodeSlash
	 * @return
	 */
	private String createSignedHeaders(Map<String, String> header){
		String[] headerArray = new String[header.size()];
		int index = 0;
		for (Map.Entry<String, String> entry : header.entrySet()) {
            String key = entry.getKey().toLowerCase();
			headerArray[index] = key;
			index++;
		}
		Arrays.sort(headerArray);  
		StringBuffer sb = new StringBuffer();
		for(int i = 0; i<headerArray.length; i++){
			String item = headerArray[i];
			sb.append(item + ";");
		}
		if(sb.length() > 0)
			sb.deleteCharAt(sb.length() - 1);
		String signedHeaders = sb.toString();
		return signedHeaders;
	}
	
	public String uriEncode(CharSequence input, boolean encodeSlash) {
        StringBuilder result = new StringBuilder();
        try {
			for (int i = 0; i < input.length(); i++) {
			    char ch = input.charAt(i);
			    if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9') || ch == '_' || ch == '-' || ch == '~' || ch == '.') {
			        result.append(ch);
			    } else if (ch == '/') {
			        result.append(encodeSlash ? "%2F" : ch);
			    } else {
			        result.append(toHexUTF8(ch));
			    }
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
        return result.toString();
    }
	private String toHexUTF8(char c){
		try {
			byte[] b = String.valueOf(c).getBytes(BceConstants.ENCODING);
			for (int j = 0; j < b.length; j++) {
                int k = b[j];
                if (k < 0)
                    k += 256;
               return "%" + Integer.toHexString(k).toUpperCase();
            }
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
        return "";    
	}
	private String sha256Hex(String signingKey, String stringToSign) {
        try {
            Mac mac = Mac.getInstance("HmacSHA256");
            mac.init(new SecretKeySpec(signingKey.getBytes(BceConstants.ENCODING), "HmacSHA256"));
            return new String(Hex.encodeHex(mac.doFinal(stringToSign.getBytes(BceConstants.ENCODING))));
        } catch (Exception e) {
        	e.printStackTrace();
        }
        return "";
    }
	
}