人臉識別(二)呼叫face++api實現人臉對比
上次部落格簡單講了一下呼叫face++的api來檢測人臉。當然,生產環境中要實現複雜的需求光靠這麼簡單的呼叫一下api肯定是不行的。這次先來講一講face++中實現人臉對比的api並實現一些相對較為複雜的需求。
首先來看一看呼叫的人臉對比的api需要的東西:
face++呼叫人臉對比api的網址:
呼叫方法使用POST呼叫,需要傳的主要的引數如下:
從官方給出的傳參列表可以看出,api_key和api_secret無疑是必需要傳的,接下來的必傳的兩個引數是兩張圖片。上傳圖片一共有三種方式:你可以選擇上傳圖片的url,或者上傳圖片的二進位制流,還可以上傳以base64編碼的圖片資料。或者你假如不想上傳圖片,可以使用以前上傳的圖片直接比對。這時你只要提交以前上傳圖片後得到的face_token就行了。在之前我講呼叫人臉檢測的介面時,只要你上傳成功,返回值裡面就會帶著face_token這個引數。這裡值得一提的是,我們通過呼叫人臉檢測上傳的圖片只會被face++官方儲存一段時間然後刪除,若我們想要將我們上傳的照片長期儲存在face++官方的庫中,則需要呼叫FaceSet這個api,相當於在face++建立一個我們自己的圖片倉庫,將我們上傳的圖片存到裡面。
這裡先演示一個簡單的例子:我先呼叫face++的人臉檢測api(具體怎麼呼叫的可以看我上一篇部落格:
圖片是我從網上隨便找的(侵刪)。上傳之後得到兩個face_token:72fc859abb56f7dc2c7d6e0700d251f8和90f86917d51c58dffc21c173fdfb7c7d,接著,我呼叫人臉對比的api,程式碼如下:
package com.example.demo;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpEntity;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient ;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
public class Compare {
public static void main(String[] args) throws Exception {
// 設定網址
String url = "https://api-cn.faceplusplus.com/facepp/v3/compare";
// 建立引數佇列
List<BasicNameValuePair> formparams = new ArrayList<>();
formparams.add(new BasicNameValuePair("api_key", "your api key"));
formparams.add(new BasicNameValuePair("api_secret", "your api secret"));
formparams.add(new BasicNameValuePair("face_token1", "72fc859abb56f7dc2c7d6e0700d251f8"));
formparams.add(new BasicNameValuePair("face_token2", "90f86917d51c58dffc21c173fdfb7c7d"));
// 傳送請求
post(formparams,url);
}
/**
* 傳送 post請求訪問本地應用並根據傳遞引數不同返回不同結果
*/
public static void post(List<BasicNameValuePair> formparams,String url) {
// 建立預設的httpClient例項.
CloseableHttpClient httpclient = HttpClients.createDefault();
// 建立httppost
HttpPost httppost = new HttpPost(url);
UrlEncodedFormEntity uefEntity;
try {
uefEntity = new UrlEncodedFormEntity(formparams, "UTF-8");
httppost.setEntity(uefEntity);
System.out.println("executing request " + httppost.getURI());
CloseableHttpResponse response = httpclient.execute(httppost);
try {
HttpEntity entity = response.getEntity();
if (entity != null) {
System.out.println("--------------------------------------");
System.out.println("Response content: " + EntityUtils.toString(entity, "UTF-8"));
System.out.println("--------------------------------------");
}
} finally {
response.close();
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
// 關閉連線,釋放資源
try {
httpclient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
這裡用java發了個http請求傳入了api_key,api_secret,face_token1,face_token2四個引數。呼叫成功後返回結果如下:
--------------------------------------
16:14:04.347 [main] DEBUG org.apache.http.impl.conn.PoolingHttpClientConnectionManager - Connection [id: 0][route: {s}->https://api-cn.faceplusplus.com:443] can be kept alive indefinitely
16:14:04.347 [main] DEBUG org.apache.http.impl.conn.PoolingHttpClientConnectionManager - Connection released: [id: 0][route: {s}->https://api-cn.faceplusplus.com:443][total kept alive: 1; route allocated: 1 of 2; total allocated: 1 of 20]
Response content: {"confidence": 67.485, "request_id": "1514708045,f3e7b3bd-015c-4189-a47c-88b32ef3a91a", "time_used": 585, "thresholds": {"1e-3": 62.327, "1e-5": 73.975, "1e-4": 69.101}}
--------------------------------------
看看response content裡面返回的引數:
- confidence:67.485。
含義:比對結果置信度,範圍 [0,100],小數點後3位有效數字,數字越大表示兩個人臉越可能是同一個人。如果傳入圖片但圖片中未檢測到人臉,則無法進行比對,本欄位不返回。
- “request_id”: “1514708045,f3e7b3bd-015c-4189-a47c-88b32ef3a91a”
用於區分每一次請求的唯一的字串。
- “time_used”: 585
整個請求所花費的時間,單位為毫秒。
- “thresholds”: {“1e-3”: 62.327, “1e-5”: 73.975, “1e-4”: 69.101}
一組用於參考的置信度閾值,包含以下三個欄位。每個欄位的值為一個 [0,100] 的浮點數,小數點後 3 位有效數字。
- 1e-3:誤識率為千分之一的置信度閾值;
- 1e-4:誤識率為萬分之一的置信度閾值;
- 1e-5:誤識率為十萬分之一的置信度閾值;
如果置信值低於“千分之一”閾值則不建議認為是同一個人;如果置信值超過“十萬分之一”閾值,則是同一個人的機率非常高。請注意:閾值不是靜態的,每次比對返回的閾值不保證相同,所以沒有持久化儲存閾值的必要,更不要將當前呼叫返回的 confidence 與之前呼叫返回的閾值比較。如果傳入圖片但圖片中未檢測到人臉,則無法進行比對,本欄位不返回。
用置信度閾值和置信度做對比我們可以得出這樣的結果:置信度(67.485)達到了千分之一(62.327),但並未達到萬分之一(69.101)和十萬分之一(73.975)的閾值。所以可以認為兩張照片有可能是同一個人,但可能性不高。
因為之前上傳的圖片不能永久儲存,我先建立一個FaceSet,讓後將這兩張照片新增到faceset中去。建立faceset程式碼如下:
package com.example.demo;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpEntity;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
public class Compare {
public static void main(String[] args) throws Exception {
// 設定網址
String url = "https://api-cn.faceplusplus.com/facepp/v3/faceset/create";
// 建立引數佇列
List<BasicNameValuePair> formparams = new ArrayList<>();
formparams.add(new BasicNameValuePair("api_key", "your api key"));
formparams.add(new BasicNameValuePair("api_secret", "your api secret"));
formparams.add(new BasicNameValuePair("outer_id", "myface_1"));
// 傳送請求
post(formparams,url);
}
/**
* 傳送 post請求訪問本地應用並根據傳遞引數不同返回不同結果
*/
public static void post(List<BasicNameValuePair> formparams,String url) {
// 建立預設的httpClient例項.
CloseableHttpClient httpclient = HttpClients.createDefault();
// 建立httppost
HttpPost httppost = new HttpPost(url);
UrlEncodedFormEntity uefEntity;
try {
uefEntity = new UrlEncodedFormEntity(formparams, "UTF-8");
httppost.setEntity(uefEntity);
System.out.println("executing request " + httppost.getURI());
CloseableHttpResponse response = httpclient.execute(httppost);
try {
HttpEntity entity = response.getEntity();
if (entity != null) {
System.out.println("--------------------------------------");
System.out.println("Response content: " + EntityUtils.toString(entity, "UTF-8"));
System.out.println("--------------------------------------");
}
} finally {
response.close();
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
// 關閉連線,釋放資源
try {
httpclient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
這裡我只是將上面的程式碼修改了傳入的引數,將url改為:https://api-cn.faceplusplus.com/facepp/v3/faceset/create。除了一直要傳入的api_key和api_secret外,還傳入了outer_id這個引數,用來指定我的faceset的唯一標識,因為face++允許我們建立多個faceset,隨意還是加一個唯一標識好點。返回引數如下:
--------------------------------------
17:18:04.581 [main] DEBUG org.apache.http.impl.conn.PoolingHttpClientConnectionManager - Connection [id: 0][route: {s}->https://api-cn.faceplusplus.com:443] can be kept alive indefinitely
17:18:04.581 [main] DEBUG org.apache.http.impl.conn.PoolingHttpClientConnectionManager - Connection released: [id: 0][route: {s}->https://api-cn.faceplusplus.com:443][total kept alive: 1; route allocated: 1 of 2; total allocated: 1 of 20]
Response content: {"faceset_token": "9cb520b964d58b3484565f6788ac750a", "time_used": 110, "face_count": 0, "face_added": 0, "request_id": "1514711886,953de53f-9c22-4aca-904f-2ffff88761a1", "outer_id": "myface_1", "failure_detail": []}
--------------------------------------
看到返回引數中faceset_token有值,就知道操作成功了。接下來我們把之前上傳的圖片加到faceset中,改變引數如下:
public static void main(String[] args) throws Exception {
// 設定網址
String url = "https://api-cn.faceplusplus.com/facepp/v3/faceset/addface";
// 建立引數佇列
List<BasicNameValuePair> formparams = new ArrayList<>();
formparams.add(new BasicNameValuePair("api_key", "your api key"));
formparams.add(new BasicNameValuePair("api_secret", "your api secret"));
formparams.add(new BasicNameValuePair("outer_id", "myface_1"));
formparams.add(new BasicNameValuePair("face_tokens", "72fc859abb56f7dc2c7d6e0700d251f8"));
// 傳送請求
post(formparams,url);
}
將之前我新增的faceset的識別符號myface_id傳入,同時傳入之前上傳圖片的face_token,請求完成得到一下引數:
Response content: {"faceset_token": "9cb520b964d58b3484565f6788ac750a", "time_used": 627, "face_count": 1, "face_added": 1, "request_id": "1514720178,9c0c43af-9923-461c-952e-f83f64f8f3e8", "outer_id": "myface_1", "failure_detail": []}
看到face_count為1代表當前這個faceset的存放照片個數,face_added為1表示成功添加了一個。至此,上傳的照片就已經永久儲存在了face++官方伺服器上。
至此,生產環境需要的主要的api我已經講的差不多了。本來計劃講一講具體的業務的實現的,但由於時間有限,決定留到下次部落格再講,這裡先把需要實現的業務給出來:
下次部落格的時候就將這個需求實現一下。