人脸识别1:n对比 (一)

  本项目采用了 Face++人脸识别 第三方接口,实现了自选本地手机相册图片上传人脸(faceSet中添加人脸) 和 自选本地手机相册图片寻找出集合中相似度最高的一个face,可返回比对相似度等信息。 

项目具体步骤如下:

一 、所需权限

    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

二、第三方app id app key

项目采用了Face++第三方接口,可自行注册获取

三、添加依赖和sdk

1. 将FaceppSDK.jar文件放到libs路径下。

2. gradle中添加一下依赖:

//导入sdk
compile files('libs/FaceppSDK.jar')

四、布局文件

人脸寻找1:n

主要代码:

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <ScrollView
 3     xmlns:android="http://schemas.android.com/apk/res/android"
 4     xmlns:tools="http://schemas.android.com/tools"
 5     android:layout_width="match_parent"
 6     android:layout_height="match_parent"
 7     android:paddingBottom="@dimen/activity_vertical_margin"
 8     android:paddingLeft="@dimen/activity_horizontal_margin"
 9     android:paddingRight="@dimen/activity_horizontal_margin"
10     android:paddingTop="@dimen/activity_vertical_margin"
11     tools:context="com.example.lifen.facesearchdemo.MainActivity">
12 
13     <LinearLayout
14         android:layout_width="match_parent"
15         android:layout_height="match_parent"
16         android:orientation="vertical"
17         android:weightSum="1">
18 
19         <LinearLayout
20             android:layout_width="match_parent"
21             android:layout_height="wrap_content"
22             android:orientation="horizontal">
23 
24             <ImageView
25                 android:id="@+id/img1"
26                 android:layout_width="0dp"
27                 android:layout_height="180dp"
28                 android:layout_weight="1.02"
29                 android:scaleType="centerCrop"
30                 android:src="@drawable/head"/>
31 
32             <ScrollView
33                 android:layout_weight="0.74"
34                 android:layout_width="60dp"
35                 android:layout_height="match_parent">
36                 <TextView
37                     android:id="@+id/addRresultTV"
38                     android:layout_width="match_parent"
39                     android:layout_height="match_parent"
40                     android:gravity="center"
41                     android:text="添加结果"
42                     android:textColor="@android:color/black" />
43             </ScrollView>
44 
45         </LinearLayout>
46 
47         <EditText
48             android:id="@+id/uidEt"
49             android:layout_width="match_parent"
50             android:layout_height="wrap_content"
51             android:ems="10"
52             android:hint="请输入uid(名字)"
53             android:inputType="textPersonName" />
54 
55         <Button
56             android:id="@+id/addFaceBtn"
57             android:layout_width="match_parent"
58             android:layout_height="wrap_content"
59             android:text="添加" />
60 
61         <Button
62             android:id="@+id/searchBtn"
63             android:layout_width="match_parent"
64             android:layout_height="wrap_content"
65             android:layout_marginTop="@dimen/activity_horizontal_margin"
66             android:text="寻找" />
67 
68         <TextView
69             android:id="@+id/resultBtn"
70             android:layout_width="match_parent"
71             android:layout_height="wrap_content"
72             android:layout_marginTop="@dimen/activity_horizontal_margin"
73             android:background="#eeeeee"
74             android:padding="6dp"
75             android:layout_weight="2.94" />
76 
77     </LinearLayout>
78 </ScrollView>
View Code

页面包含:

  ① ImageView 点击ImageView 可跳转手机相册,选择要使用的图片。

  ② TextView1  faceSet添加face 结果再次显示

  ③ EditText 设定face 的user_uid

  ④ button1 添加人脸按钮

  ⑤ button2 寻找相似度最高人脸按钮

  ⑥ TextView2 寻找结果展示view

 faceSet 中添加 face过程:

  1. 点击imageView 选取图片

  2. 输入uid

  3. 点击添加

 寻找相似度最高face过程:

  1.点击imageView 选取图片

  2. 点击寻找按钮

 五、页面activity

主要代码:

  1 package com.example.lifen.facesearchdemo;
  2 
  3 import android.content.ContentResolver;
  4 import android.content.Intent;
  5 import android.graphics.Bitmap;
  6 import android.graphics.BitmapFactory;
  7 import android.net.Uri;
  8 import android.os.Bundle;
  9 import android.os.Handler;
 10 import android.os.Message;
 11 import android.support.v7.app.AlertDialog;
 12 import android.support.v7.app.AppCompatActivity;
 13 import android.text.TextUtils;
 14 import android.util.Base64;
 15 import android.util.Log;
 16 import android.view.View;
 17 import android.widget.Button;
 18 import android.widget.EditText;
 19 import android.widget.ImageView;
 20 import android.widget.TextView;
 21 import android.widget.Toast;
 22 
 23 import com.megvii.cloud.http.CommonOperate;
 24 import com.megvii.cloud.http.FaceOperate;
 25 import com.megvii.cloud.http.FaceSetOperate;
 26 import com.megvii.cloud.http.Response;
 27 
 28 import org.json.JSONException;
 29 import org.json.JSONObject;
 30 
 31 import java.io.ByteArrayOutputStream;
 32 import java.io.FileNotFoundException;
 33 import java.util.ArrayList;
 34 
 35 /**
 36  * 人脸对比 1:1
 37  *
 38  * @author LiFen
 39  */
 40 public class MainActivity extends AppCompatActivity {
 41     private static final String TAG = "MainActivity";
 42     private static final int REQUEST_CODE1 = 11;
 43     ImageView mImageView1;
 44     Button mSearchBtn;
 45     private Button mAddFaceBtn;
 46     TextView mResultText;
 47     private TextView mAddResultText;
 48     private String mImgBase641;
 49     private EditText uidEidtText;
 50     ArrayList<String> faces = new ArrayList<>();
 51     String key = "";//api_key
 52     String secret = "";//api_secret
 53     private final static int i = 100;
 54     private final static int j = 200;
 55     private final static int s = 300;
 56     private Handler handler = new Handler(){
 57         @Override
 58         public void handleMessage(Message msg) {
 59             if(msg.what == i){
 60                 mAddResultText.setText((String)msg.obj);
 61             }
 62             if(msg.what == j){
 63                 mAddResultText.append((String)msg.obj);
 64             }
 65             if(msg.what == s){
 66                 mResultText.setText((String)msg.obj);
 67             }
 68         }
 69     };
 70 
 71     @Override
 72     protected void onCreate(Bundle savedInstanceState) {
 73         super.onCreate(savedInstanceState);
 74         setContentView(R.layout.activity_main);
 75 
 76         mImageView1 = (ImageView) findViewById(R.id.img1);
 77         mSearchBtn = (Button) findViewById(R.id.searchBtn);
 78         mAddFaceBtn = (Button)findViewById(R.id.addFaceBtn);
 79         mResultText = (TextView) findViewById(R.id.resultBtn);
 80         mAddResultText = (TextView)findViewById(R.id.addRresultTV);
 81         uidEidtText = (EditText)findViewById(R.id.uidEt);
 82         if(TextUtils.isEmpty(key) || TextUtils.isEmpty(secret)){
 83             AlertDialog.Builder builder = new AlertDialog.Builder(this);
 84             builder.setMessage("please enter key and secret");
 85             builder.setTitle("");
 86             builder.show();
 87             return;
 88         }
 89         mImageView1.setOnClickListener(new View.OnClickListener() {
 90             @Override
 91             public void onClick(View v) {
 92                 startAlbumActivity(REQUEST_CODE1);
 93             }
 94         });
 95         mAddFaceBtn.setOnClickListener(new View.OnClickListener() {
 96             @Override
 97             public void onClick(View v) {
 98                 addFace();
 99             }
100         });
101         mSearchBtn.setOnClickListener(new View.OnClickListener() {
102             @Override
103             public void onClick(View v) {
104                 startSearch();
105             }
106         });
107     }
108 
109     private void addFace(){
110         if ("".equals(mImgBase641) || mImgBase641 == null) {
111             Toast.makeText(this, "请选择图片再添加", Toast.LENGTH_SHORT).show();
112             return;
113         }
114         if(uidEidtText.getText().toString().equals("")){
115             Toast.makeText(this,"请输入uid(名字)",Toast.LENGTH_SHORT).show();
116             return;
117         }
118         mResultText.setText("人脸添加中...");
119         new Thread(new Runnable() {
120             @Override
121             public void run() {
122                 CommonOperate commonOperate = new CommonOperate(key, secret, false);
123                 try{
124                     //获取faceToken
125                     Response response = commonOperate.detectBase64(mImgBase641, 0, null);
126                     FaceOperate faceOperate = new FaceOperate(key,secret,false);
127                     String faceToken = getFaceToken(response);
128                     String uid = uidEidtText.getText().toString();
129                     Log.i(TAG, "run: " + uid);
130                     faceOperate.faceSetUserId(faceToken, uid);
131                     faces.add(faceToken);
132                     Message msg = new Message();
133                     msg.what = i;
134                     msg.obj = faceToken;
135                     handler.sendMessage(msg);
136                     //faceSet中添加faceToken
137                     FaceSetOperate FaceSet = new FaceSetOperate(key, secret, false);
138                     String faceTokens = creatFaceTokens(faces);
139                     Response faceSet = FaceSet.addFaceByFaceToken(faceTokens, "469e42d27947506b44cee9a8dba2eb4f");
140                     String result = new String(faceSet.getContent());
141                     msg.what = j;
142                     msg.obj = result;
143                     handler.sendMessage(msg);
144                 }catch (Exception e){
145                     Log.i(TAG, "addFace: " +e.toString());
146                 }
147             }
148         }).start();
149     }
150 
151     private void startSearch() {
152         if ("".equals(mImgBase641) || mImgBase641 == null) {
153             Toast.makeText(this, "请选择图片再寻找", Toast.LENGTH_SHORT).show();
154             return;
155         }
156         mResultText.setText("搜索比对中...");
157         new Thread(new Runnable() {
158             @Override
159             public void run() {
160                 Log.i(TAG, "run() called");
161                 CommonOperate commonOperate = new CommonOperate(key, secret, false);
162                 //获取faceToken
163                 Response response = null;
164                 try {
165                     response = commonOperate.detectBase64(mImgBase641, 0, null);
166                     String faceToken = getFaceToken(response);
167                     Response searchByOuterId = commonOperate.searchByOuterId(faceToken, null, null, "test", 1);
168                     Message msg = new Message();
169                     msg.what = s;
170                     String result = new String(searchByOuterId.getContent());
171                     msg.obj = result;
172                     handler.sendMessage(msg);
173                 } catch (Exception e) {
174                     e.printStackTrace();
175                 }
176             }
177         }).start();
178     }
179 
180     private void startAlbumActivity(int requestCode) {
181         Intent intent = new Intent();
182         intent.setType("image/*");
183         intent.setAction(Intent.ACTION_GET_CONTENT);
184         startActivityForResult(intent, requestCode);
185     }
186 
187     @Override
188     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
189         if (data == null)
190             return;
191         Uri uri = data.getData();
192         Log.e("uri", uri.toString());
193         ContentResolver cr = this.getContentResolver();
194         Bitmap bitmap = null;
195         try {
196             bitmap = BitmapFactory.decodeStream(cr.openInputStream(uri));
197                 /* 将Bitmap设定到ImageView */
198         } catch (FileNotFoundException e) {
199             Log.e("Exception", e.getMessage(), e);
200         }
201         if (resultCode == RESULT_OK && requestCode == REQUEST_CODE1) {
202             mImageView1.setImageBitmap(bitmap);
203             mImgBase641 = bitmapToBase64(bitmap);
204         }
205         super.onActivityResult(requestCode, resultCode, data);
206     }
207 
208     private String bitmapToBase64(Bitmap bitmap) {
209         ByteArrayOutputStream bStream = new ByteArrayOutputStream();
210         bitmap.compress(Bitmap.CompressFormat.JPEG, 80, bStream);
211         return Base64.encodeToString(bStream.toByteArray(), 0);
212     }
213 
214     private String getFaceToken(Response response) throws JSONException {
215         if(response.getStatus() != 200){
216             return new String(response.getContent());
217         }
218         String res = new String(response.getContent());
219         Log.e("response", res);
220         JSONObject json = new JSONObject(res);
221         String faceToken = json.optJSONArray("faces").optJSONObject(0).optString("face_token");
222         return faceToken;
223     }
224 
225     private String creatFaceTokens(ArrayList<String> faceTokens){
226         if(faceTokens == null || faceTokens.size() == 0){
227             return "";
228         }
229         StringBuffer face = new StringBuffer();
230         for (int i = 0; i < faceTokens.size(); i++){
231             if(i == 0){
232                 face.append(faceTokens.get(i));
233             }else{
234                 face.append(",");
235                 face.append(faceTokens.get(i));
236             }
237         }
238         return face.toString();
239     }
240 }
View Code

其中key 和 secret 可自行注册填入。本项目之前已经创建了faceSet,创建过程可参考:https://download.csdn.net/download/qq_36726507/10293566

注意:uid 不超过255个字符,不能包括^@,&=*'",不可使用中文(用中文挂掉好几次)。

 项目地址:https://download.csdn.net/download/qq_36726507/10293600

原文地址:https://www.cnblogs.com/jxust-jiege666/p/8595483.html