zoukankan      html  css  js  c++  java
  • 人脸识别1:n对比 (二)

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

    目前百度向个人开发者提供了免费人脸识别接口,QPS限制为2,企业认证后并发数可增至 5,个人测试还是没问题的。

    项目具体步骤如下:

    一 、所需权限

        <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

    项目采用了百度AI 第三方接口,可自行注册获取

    三、添加依赖和sdk

    1. http 工具类
       View Code
    2. Base64 工具类
       View Code

      以上是实现的Base64的加密算法,使用自带 Base64.encodeToString(); 方法也可以。

      Base64原理可参考这篇博文:http://www.cnblogs.com/jxust-jiege666/p/8590116.html

    四、获取token

    主要代码:

     View Code

    注意:access_token的有效期为30天,切记需要每30天进行定期更换,或者每次请求都拉取新token;

    五、添加人脸

      在1:n 对比搜索前,首先要向创建的face组内添加face (另外百度也提供了后台添加加人脸,可登录控制台创建组和添加人脸),主要代码如下:

     1 public static String identify(byte[] imgData,byte[] imgData2,String groupid,String accessToken) {
     2         // 请求url
     3         String url = "https://aip.baidubce.com/rest/2.0/face/v2/identify";
     4         try {
     5             // 本地文件路径
     6             String imgStr = Base64Util.encode(imgData);
     7             String imgParam = URLEncoder.encode(imgStr, "UTF-8");
     8 
     9             String imgStr2 = Base64Util.encode(imgData2);
    10             String imgParam2 = URLEncoder.encode(imgStr2, "UTF-8");
    11 
    12             String param = "group_id=" + groupid + "&user_top_num=" + "1" + "&face_top_num=" + "1" + "&images=" + imgParam + "," + imgParam2;
    13 
    14             // 注意这里仅为了简化编码每一次请求都去获取access_token,线上环境access_token有过期时间, 客户端可自行缓存,过期后重新获取。
    15 
    16             String result = HttpUtil.post(url, accessToken, param);
    17             System.out.println(result);
    18             return result;
    19         } catch (Exception e) {
    20             e.printStackTrace();
    21         }
    22         return null;
    23     }
    24 }
    View Code

    其中groupid是你之前创建的组的id,user_top_num 是要返回相似度最高的人的个数,face_top_num是返回相似度最高人的face个数。一个人可以添加多个face,该项目为每个人添加了两个face。

    六、寻找人脸

    主要代码:

     1 /**
     2  * 人脸查找——识别
     3  */
     4 public class Identify {
     5 
     6     /**
     7      * 重要提示代码中所需工具类
     8      * FileUtil,Base64Util,HttpUtil,GsonUtils请从
     9      * https://ai.baidu.com/file/658A35ABAB2D404FBF903F64D47C1F72
    10      * https://ai.baidu.com/file/C8D81F3301E24D2892968F09AE1AD6E2
    11      * https://ai.baidu.com/file/544D677F5D4E4F17B4122FBD60DB82B3
    12      * https://ai.baidu.com/file/470B3ACCA3FE43788B5A963BF0B625F3
    13      * 下载
    14      */
    15     public static String identify(byte[] imgData,byte[] imgData2,String groupid,String accessToken) {
    16         // 请求url
    17         String url = "https://aip.baidubce.com/rest/2.0/face/v2/identify";
    18         try {
    19      
    20             String imgStr = Base64Util.encode(imgData);
    21             String imgParam = URLEncoder.encode(imgStr, "UTF-8");
    22 
    23             String imgStr2 = Base64Util.encode(imgData2);
    24             String imgParam2 = URLEncoder.encode(imgStr2, "UTF-8");
    25 
    26             String param = "group_id=" + groupid + "&user_top_num=" + "1" + "&face_top_num=" + "1" + "&images=" + imgParam + "," + imgParam2;
    27 
    28             // 注意这里仅为了简化编码每一次请求都去获取access_token,线上环境access_token有过期时间, 客户端可自行缓存,过期后重新获取。
    29 
    30             String result = HttpUtil.post(url, accessToken, param);
    31             System.out.println(result);
    32             return result;
    33         } catch (Exception e) {
    34             e.printStackTrace();
    35         }
    36         return null;
    37     }
    38 }
    View Code

    七、页面activity

    主要代码:

      1 import android.content.ContentResolver;
      2 import android.content.Intent;
      3 import android.graphics.Bitmap;
      4 import android.graphics.BitmapFactory;
      5 import android.net.Uri;
      6 import android.os.Bundle;
      7 import android.os.Handler;
      8 import android.os.Message;
      9 import android.support.v7.app.AlertDialog;
     10 import android.support.v7.app.AppCompatActivity;
     11 import android.text.TextUtils;
     12 import android.util.Log;
     13 import android.view.View;
     14 import android.widget.Button;
     15 import android.widget.EditText;
     16 import android.widget.ImageView;
     17 import android.widget.TextView;
     18 import android.widget.Toast;
     19 
     20 import com.example.lifen.baidufacesearchdemo.utils.AuthService;
     21 import com.example.lifen.baidufacesearchdemo.utils.Base64Util;
     22 import com.example.lifen.baidufacesearchdemo.utils.FaceAdd;
     23 import com.example.lifen.baidufacesearchdemo.utils.Identify;
     24 
     25 import java.io.ByteArrayOutputStream;
     26 import java.io.FileNotFoundException;
     27 
     28 /**
     29  * 人脸寻找 fase集合中寻找最相似(1 或 多)的face
     30  *
     31  * @author LiFen
     32  */
     33 public class MainActivity extends AppCompatActivity {
     34     private static final String TAG = "MainActivity";
     35     private static final int REQUEST_CODE1 = 11;
     36     ImageView mImageView1;
     37     Button mSearchBtn;
     38     private Button mAddFaceBtn;
     39     TextView mResultText;
     40     private TextView mAddResultText;
     41     private byte[] mImg1;
     42     private EditText uidEidtText;
     43     private EditText mInforEidtText;
     44     String key = "";//api_key
     45     String secret ="";//api_secret
     46     private final static int i = 100;
     47     private final static int j = 200;
     48     private final static int s = 300;
     49     private Handler handler = new Handler(){
     50         @Override
     51         public void handleMessage(Message msg) {
     52             if(msg.what == i){
     53                 mAddResultText.setText((String)msg.obj);
     54             }
     55             if(msg.what == j){
     56                 mAddResultText.append((String)msg.obj);
     57             }
     58             if(msg.what == s){
     59                 mResultText.setText((String)msg.obj);
     60             }
     61         }
     62     };
     63 
     64     @Override
     65     protected void onCreate(Bundle savedInstanceState) {
     66         super.onCreate(savedInstanceState);
     67         setContentView(R.layout.activity_main);
     68 
     69         mImageView1 = (ImageView) findViewById(R.id.img1);
     70         mSearchBtn = (Button) findViewById(R.id.searchBtn);
     71         mAddFaceBtn = (Button)findViewById(R.id.addFaceBtn);
     72         mResultText = (TextView) findViewById(R.id.resultBtn);
     73         mAddResultText = (TextView)findViewById(R.id.addRresultTV);
     74         uidEidtText = (EditText)findViewById(R.id.uidEt);
     75         mInforEidtText = (EditText)findViewById(R.id.inforEt);
     76         if(TextUtils.isEmpty(key) || TextUtils.isEmpty(secret)){
     77             AlertDialog.Builder builder = new AlertDialog.Builder(this);
     78             builder.setMessage("please enter key and secret");
     79             builder.setTitle("");
     80             builder.show();
     81             return;
     82         }
     83         mImageView1.setOnClickListener(new View.OnClickListener() {
     84             @Override
     85             public void onClick(View v) {
     86                 startAlbumActivity(REQUEST_CODE1);
     87             }
     88         });
     89         mAddFaceBtn.setOnClickListener(new View.OnClickListener() {
     90             @Override
     91             public void onClick(View v) {
     92                 addFace();
     93             }
     94         });
     95         mSearchBtn.setOnClickListener(new View.OnClickListener() {
     96             @Override
     97             public void onClick(View v) {
     98                 startSearch();
     99             }
    100         });
    101     }
    102 
    103     private void addFace(){
    104         if ("".equals(mImg1) || mImg1 == null) {
    105             Toast.makeText(this, "请选择图片再添加", Toast.LENGTH_SHORT).show();
    106             return;
    107         }
    108         if(uidEidtText.getText().toString().equals("")){
    109             Toast.makeText(this,"请输入uid(名字)",Toast.LENGTH_SHORT).show();
    110             return;
    111         }
    112         mAddResultText.setText("人脸添加中...");
    113         new Thread(new Runnable() {
    114             @Override
    115             public void run() {
    116                 String accessToken = AuthService.getAuth(key, secret);
    117                 Log.i(TAG, "accessToken:" + accessToken);
    118                 Message msg1 = new Message();
    119                 msg1.what = i;
    120                 msg1.obj = accessToken;
    121                 handler.sendMessage(msg1);
    122 
    123                 String uid = uidEidtText.getText().toString();
    124                 String infor = mInforEidtText.getText().toString();
    125                 String encode = Base64Util.encode(infor.getBytes());
    126                 Log.i(TAG, "infor: " + encode);
    127                 /*String inforUtf = new String(Base64.decode(encode, Base64.DEFAULT));
    128                 Log.i(TAG, "infor: " + inforUtf);*/
    129                 String add = FaceAdd.add(mImg1, mImg1, uid,encode,"test",accessToken);
    130                 Log.i(TAG, "addFace: " + add);
    131                 Message msg2 = new Message();
    132                 msg2.what = j;
    133                 msg2.obj = add;
    134                 handler.sendMessage(msg2);
    135             }
    136         }).start();
    137     }
    138 
    139     private void startSearch() {
    140         if ("".equals(mImg1) || mImg1 == null) {
    141             Toast.makeText(this, "请选择图片再寻找", Toast.LENGTH_SHORT).show();
    142             return;
    143         }
    144         mResultText.setText("搜索比对中...");
    145         new Thread(new Runnable() {
    146             @Override
    147             public void run() {
    148                 String accessToken = AuthService.getAuth(key, secret);
    149                 Log.i(TAG, "accessToken:" + accessToken);
    150                 String result = Identify.identify(mImg1, mImg1, "test", accessToken);
    151                 Log.i(TAG, "result" + result);
    152                 Message msg3 = new Message();
    153                 msg3.what = s;
    154                 msg3.obj = result;
    155                 handler.sendMessage(msg3);
    156             }
    157         }).start();
    158     }
    159 
    160     private void startAlbumActivity(int requestCode) {
    161         Intent intent = new Intent();
    162         intent.setType("image/*");
    163         intent.setAction(Intent.ACTION_GET_CONTENT);
    164         startActivityForResult(intent, requestCode);
    165     }
    166 
    167     @Override
    168     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    169         if (data == null)
    170             return;
    171         Uri uri = data.getData();
    172         Log.e("uri", uri.toString());
    173         ContentResolver cr = this.getContentResolver();
    174         Bitmap bitmap = null;
    175         try {
    176             bitmap = BitmapFactory.decodeStream(cr.openInputStream(uri));
    177                 /* 将Bitmap设定到ImageView */
    178         } catch (FileNotFoundException e) {
    179             Log.e("Exception", e.getMessage(), e);
    180         }
    181         if (resultCode == RESULT_OK && requestCode == REQUEST_CODE1) {
    182             mImageView1.setImageBitmap(bitmap);
    183             ByteArrayOutputStream baos = new ByteArrayOutputStream();
    184             bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
    185             byte[] datas = baos.toByteArray();
    186             mImg1 = datas;
    187         }
    188         super.onActivityResult(requestCode, resultCode, data);
    189     }
    190 }
    View Code

    八、布局文件

    1:n 寻找

    页面包含:

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

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

      ③ EditText 设定face 的user_uid

      ④ button1 添加人脸按钮

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

      ⑥ TextView2 寻找结果展示view

     faceSet 中添加 face过程:

      1. 点击imageView 选取图片

      2. 输入uid

      3. 添加face关联的信息(这里我Base64编码后上传的服务器,使用时可自行解码)

      4. 点击添加按钮添加

     寻找相似度最高face过程:

      1.点击imageView 选取图片

      2. 点击寻找按钮

     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.baidufacesearchdemo.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="textCapCharacters" />
    54 
    55         <EditText
    56             android:id="@+id/inforEt"
    57             android:layout_width="match_parent"
    58             android:layout_height="wrap_content"
    59             android:ems="10"
    60             android:hint="人脸关联的其他信息"
    61             android:inputType="textPersonName" />
    62 
    63         <Button
    64             android:id="@+id/addFaceBtn"
    65             android:layout_width="match_parent"
    66             android:layout_height="wrap_content"
    67             android:text="添加" />
    68 
    69         <Button
    70             android:id="@+id/searchBtn"
    71             android:layout_width="match_parent"
    72             android:layout_height="wrap_content"
    73             android:layout_marginTop="@dimen/activity_horizontal_margin"
    74             android:text="寻找" />
    75 
    76         <TextView
    77             android:id="@+id/resultBtn"
    78             android:layout_width="match_parent"
    79             android:layout_height="wrap_content"
    80             android:layout_marginTop="@dimen/activity_horizontal_margin"
    81             android:background="#eeeeee"
    82             android:padding="6dp"
    83             android:layout_weight="2.94" />
    84 
    85     </LinearLayout>
    86 </ScrollView>
    View Code

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

  • 相关阅读:
    Camel routes in Spring config file
    Construct a basic automation test framework
    Java custom annotations
    Java Abstract Class
    Hibernate之mappedBy
    hibernate FetchType理解
    hibernate 双向 OneToOne fetchType lazy 问题
    日常总结
    hibernate二级缓存
    sql子查询和嵌套查询
  • 原文地址:https://www.cnblogs.com/jxust-jiege666/p/8602325.html
Copyright © 2011-2022 走看看