记阿里云人脸识别集成

一、到阿里云生成Access Key和Access Key Secret。

二、添加.jar包

三、编辑页面,

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginLeft="20dp"
    android:orientation="vertical"
    tools:context="com.xdj.anew.MainActivity">

    <ImageView
        android:id="@+id/image"
        android:layout_width="80dp"
        android:layout_height="80dp"
        android:src="@mipmap/ic_launcher" />
    
    <TextView
        android:id="@+id/txt1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="上传身份证" />

    <ImageView
        android:id="@+id/image2"
        android:layout_width="80dp"
        android:layout_height="80dp"
        android:layout_marginTop="10dp"
        android:src="@mipmap/ic_launcher" />

    <TextView
        android:id="@+id/txt"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:text="人脸验证" />
    <TextView
        android:id="@+id/verify"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:text="开始验证"/>

</LinearLayout>

四、选择图片(分别选择相册)

 @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.txt://相机
//                startCamera();
                openCamera(this);
                break;
            case R.id.txt1://相册
                gallery();
                break;
            case R.id.verify:
               
                getVerify();
                break;
        }
    }
    /**
     * 从相册获取
     */
    public void gallery() {
        // 激活系统图库,选择一张图片
        Intent intent = new Intent(Intent.ACTION_PICK);
        intent.setType("image/*");
        // 开启一个带有返回值的Activity,请求码为PHOTO_REQUEST_GALLERY
        startActivityForResult(intent, RESULT_CAMERA_IMAGE);
    }

写一个相机类进行调用

public class CameraUtil {
    public static File tempFile;
    public static final int PHOTO_REQUEST_CAREMA = 3;// 拍照  
    public static final int CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE = 2;// 拍摄视频  
    public static Uri uri_;

    /**
     * 打开相机拍照 
     *
     * @param activity
     */
    public static void openCamera(Activity activity) {
        //獲取系統版本  
        int currentapiVersion = android.os.Build.VERSION.SDK_INT;
        // 激活相机  
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        // 判断存储卡是否可以用,可用进行存储  
        if (hasSdcard()) {
            SimpleDateFormat timeStampFormat = new SimpleDateFormat(
                    "yyyy_MM_dd_HH_mm_ss");
            String filename = timeStampFormat.format(new Date());
            tempFile = new File(Environment.getExternalStorageDirectory(),
                    filename + ".jpg");
            if (currentapiVersion < 24) {
                // 从文件中创建uri  
                uri_ = Uri.fromFile(tempFile);
                intent.putExtra(MediaStore.EXTRA_OUTPUT, uri_);
            } else {
                //兼容android7.0 使用共享文件的形式  
                ContentValues contentValues = new ContentValues(1);
                contentValues.put(MediaStore.Images.Media.DATA, tempFile.getAbsolutePath());
                uri_ = activity.getApplication().getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
                intent.putExtra(MediaStore.EXTRA_OUTPUT, uri_);
                Log.d("sjc", "uriuri>>>"+ uri_);
            }
        }
        // 开启一个带有返回值的Activity,请求码为PHOTO_REQUEST_CAREMA  
        activity.startActivityForResult(intent, PHOTO_REQUEST_CAREMA);
    }


    /**
     * 打开相机录像 
     */
    public static void startToVideo(Activity activity) {
        //獲取系統版本  
        int currentapiVersion = android.os.Build.VERSION.SDK_INT;
        Uri fileUri = null;
        File file = null;
        Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
        try {
            file = createMediaFile();
            if (file.exists()) {
                fileUri = Uri.fromFile(file); // create a file to save the video  
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (currentapiVersion < 24) {
            intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);  // set the image file name  
            intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1); // set the video image quality to high  
        } else {
            //兼容android7.0  
            ContentValues contentValues = new ContentValues(1);
            contentValues.put(MediaStore.Images.Media.DATA, file.getAbsolutePath());
            Uri uri = activity.getApplication().getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
            intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
        }
        // start the Video Capture Intent  
        activity.startActivityForResult(intent, CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE);
    }

    /* 
   * 判断sdcard是否被挂载 
   */
    public static boolean hasSdcard() {
        return Environment.getExternalStorageState().equals(
                Environment.MEDIA_MOUNTED);
    }

    /**
     * 创建保存录制得到的视频文件 
     *
     * @return
     * @throws IOException
     */
    public static File createMediaFile() throws IOException {
        if (hasSdcard()) {
            File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
                    Environment.DIRECTORY_MOVIES), "CameraVideos");
            if (!mediaStorageDir.exists()) {
                if (!mediaStorageDir.mkdirs()) {
                    return null;
                }
            }
            // Create an image file name  
            String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
            String imageFileName = "VID_" + timeStamp;
            String suffix = ".mp4";
            File mediaFile = new File(mediaStorageDir + File.separator + imageFileName + suffix);
            return mediaFile;
        }
        return null;
    }
}  

五、在activity进行图片回调接收,并显示

 @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode != RESULT_OK) {
            return;
        }
       
        if (requestCode == RESULT_CAMERA_IMAGE) {
            // 从相册返回的数据
            if (data != null) {
                // 得到图片的全路径
                uri = data.getData();
                image.setImageURI(uri);
            }
        }
         if (requestCode == PHOTO_REQUEST_CAREMA) {
            //照的相片
             try {
                 //图片解析成Bitmap对象
                 mBitmap = BitmapFactory.decodeStream(
                         getContentResolver().openInputStream(uri_));
                 image2.setImageBitmap(mBitmap);

             } catch (FileNotFoundException e) {
                 e.printStackTrace();
             }
        }
    }

六、抄下官方写好的请求头微笑

  1. public class AESDecode {
  2. /*
  3. * 计算MD5+BASE64
  4. */
  5. public static String MD5Base64(String s) {
  6. if (s == null)
  7. return null;
  8. String encodeStr = "";
  9. byte[] utfBytes = s.getBytes();
  10. MessageDigest mdTemp;
  11. try {
  12. mdTemp = MessageDigest.getInstance("MD5");
  13. mdTemp.update(utfBytes);
  14. byte[] md5Bytes = mdTemp.digest();
  15. BASE64Encoder b64Encoder = new BASE64Encoder();
  16. encodeStr = b64Encoder.encode(md5Bytes);
  17. } catch (Exception e) {
  18. throw new Error("Failed to generate MD5 : " + e.getMessage());
  19. }
  20. return encodeStr;
  21. }
  22.  
  23. /*
  24. * 计算 HMAC-SHA1
  25. */
  26. public static String HMACSha1(String data, String key) {
  27. String result;
  28. try {
  29.  
  30. SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(), "HmacSHA1");
  31. Mac mac = Mac.getInstance("HmacSHA1");
  32. mac.init(signingKey);
  33. byte[] rawHmac = mac.doFinal(data.getBytes());
  34. result = (new BASE64Encoder()).encode(rawHmac);
  35. } catch (Exception e) {
  36. throw new Error("Failed to generate HMAC : " + e.getMessage());
  37. }
  38. return result;
  39. }
  40.  
  41. /*
  42. * 等同于javaScript中的 new Date().toUTCString();
  43. */
  44. public static String toGMTString(Date date) {
  45. SimpleDateFormat df = new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss z", Locale.UK);
  46. df.setTimeZone(new java.util.SimpleTimeZone(0, "GMT"));
  47. return df.format(date);
  48. }
  49.  
  50. /*
  51. * 发送POST请求
  52. */
  53. public static String sendPost(String url, String body, String ak_id, String ak_secret) throws Exception {
  54. PrintWriter out = null;
  55. BufferedReader in = null;
  56. String result = "";
  57. int statusCode = 200;
  58. try {
  59. URL realUrl = new URL(url);
  60.  
  61. /*
  62. * http header 参数
  63. */
  64. String method = "POST";
  65. String accept = "application/json";
  66. String content_type = "application/json";
  67. String path = realUrl.getFile();
  68. String date = toGMTString(new Date());
  69.  
  70. // 1.对body做MD5+BASE64加密
  71. String bodyMd5 = MD5Base64(body);
  72. String stringToSign = method + "\n" + accept + "\n" + bodyMd5 + "\n" + content_type + "\n" + date + "\n"
  73. + path;
  74. // 2.计算 HMAC-SHA1
  75. String signature = HMACSha1(stringToSign, ak_secret);
  76. // 3.得到 authorization header
  77. String authHeader = "Dataplus " + ak_id + ":" + signature;
  78.  
  79. // 打开和URL之间的连接
  80. URLConnection conn = realUrl.openConnection();
  81. // 设置通用的请求属性
  82. conn.setRequestProperty("accept", accept);
  83. conn.setRequestProperty("content-type", content_type);
  84. conn.setRequestProperty("date", date);
  85. conn.setRequestProperty("Authorization", authHeader);
  86.  
  87. // 发送POST请求必须设置如下两行
  88. conn.setDoOutput(true);
  89. conn.setDoInput(true);
  90. // 获取URLConnection对象对应的输出流
  91. out = new PrintWriter(conn.getOutputStream());
  92. // 发送请求参数
  93. out.print(body);
  94. // flush输出流的缓冲
  95. out.flush();
  96.  
  97. // 定义BufferedReader输入流来读取URL的响应
  98. statusCode = ((HttpURLConnection)conn).getResponseCode();
  99. if(statusCode != 200) {
  100. in = new BufferedReader(new InputStreamReader(((HttpURLConnection)conn).getErrorStream()));
  101. } else {
  102. in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
  103. }
  104. String line;
  105. while ((line = in.readLine()) != null) {
  106. result += line;
  107. }
  108. } catch (Exception e) {
  109. e.printStackTrace();
  110. } finally {
  111. try {
  112. if (out != null) {
  113. out.close();
  114. }
  115. if (in != null) {
  116. in.close();
  117. }
  118. } catch (IOException ex) {
  119. ex.printStackTrace();
  120. }
  121. }
  122.  
  123. if (statusCode != 200) {
  124. throw new IOException("\nHttp StatusCode: "+ statusCode + "\nErrorMessage: " + result);
  125. }
  126. return result;
  127. }
  128.  
  129. /*
  130. * GET请求
  131. */
  132. public static String sendGet(String url, String ak_id, String ak_secret) throws Exception {
  133. String result = "";
  134. BufferedReader in = null;
  135. int statusCode = 200;
  136. try {
  137. URL realUrl = new URL(url);
  138. /*
  139. * http header 参数
  140. */
  141. String method = "GET";
  142. String accept = "application/json";
  143. String content_type = "application/json";
  144. String path = realUrl.getFile();
  145. String date = toGMTString(new Date());
  146. // 1.对body做MD5+BASE64加密
  147. // String bodyMd5 = MD5Base64(body);
  148. String stringToSign = method + "\n" + accept + "\n" + "" + "\n" + content_type + "\n" + date + "\n" + path;
  149. // 2.计算 HMAC-SHA1
  150. String signature = HMACSha1(stringToSign, ak_secret);
  151. // 3.得到 authorization header
  152. String authHeader = "Dataplus " + ak_id + ":" + signature;
  153. // 打开和URL之间的连接
  154. URLConnection connection = realUrl.openConnection();
  155. // 设置通用的请求属性
  156. connection.setRequestProperty("accept", accept);
  157. connection.setRequestProperty("content-type", content_type);
  158. connection.setRequestProperty("date", date);
  159. connection.setRequestProperty("Authorization", authHeader);
  160. connection.setRequestProperty("Connection", "keep-alive");
  161. // 建立实际的连接
  162. connection.connect();
  163.  
  164. // 定义 BufferedReader输入流来读取URL的响应
  165. statusCode = ((HttpURLConnection)connection).getResponseCode();
  166. if(statusCode != 200) {
  167. in = new BufferedReader(new InputStreamReader(((HttpURLConnection)connection).getErrorStream()));
  168. } else {
  169. in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
  170. }
  171. String line;
  172. while ((line = in.readLine()) != null) {
  173. result += line;
  174. }
  175. } catch (Exception e) {
  176. e.printStackTrace();
  177. } finally {
  178. try {
  179. if (in != null) {
  180. in.close();
  181. }
  182. } catch (Exception e) {
  183. e.printStackTrace();
  184. }
  185. }
  186.  
  187. if (statusCode != 200) {
  188. throw new IOException("\nHttp StatusCode: "+ statusCode + "\nErrorMessage: " + result);
  189. }
  190. return result;
  191. }
  192.  
  193. public static void main(String[] args) throws Exception {
  194. // 发送POST请求示例
  195. String ak_id1 = "NMV.............5jv"; //用户ak
  196. String ak_secret1 = "Fgs...............3zu"; // 用户ak_secret
  197.         //根据需求修改为https://dtplus-cn-shanghai.data.aliyuncs.com/face/verify(人脸对比)
  198. String url = "https://shujuapi.aliyun.com/org_code/service_code/api_name";
  199.         
     
    //  String body = "{\"type\":1,\"content_1\": \"" + photo1 + "\", \"content_2\":\"" + photo2 + "\"}";
      //photo1 为图片base64格式
  200.         String body = "{\"param1\": \"xxx\", \"param2\":\"xxx\"}";
  201. System.out.println("response body:" + sendPost(url, body, ak_id, ak_secret));
  202.  
  203. // 发送GET请求
  204. String ak_id1 = "NMV.............5jv"; //用户ak
  205. String ak_secret1 = "Fgs...............3zu"; // 用户ak_secret
  206. String url1 = "https://shujuapi.aliyun.com/org_code/service_code/api_name?param1=xxx&param2=xxx";
  207. System.out.println("response body:" + sendGet(url1, ak_id1, ak_secret1));
  208. }
  209. }
  210.  

七、请求网络对面相似度

ps:图片uri转base64:

photo1 = ImageUtils.bitmapToString(getPath(uri));
photo2 = ImageUtils.bitmapToString(getPath(uri_));
public class ImageUtils {
    // 根据路径获得图片并压缩,返回bitmap用于显示
    public static Bitmap getSmallBitmap(String filePath) {
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(filePath, options);

        // Calculate inSampleSize
        options.inSampleSize = calculateInSampleSize(options, 480, 800);

        // Decode bitmap with inSampleSize set
        options.inJustDecodeBounds = false;

        return BitmapFactory.decodeFile(filePath, options);
    }

    //计算图片的缩放值
    public static int calculateInSampleSize(BitmapFactory.Options options,int reqWidth, int reqHeight) {
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;

        if (height > reqHeight || width > reqWidth) {
            final int heightRatio = Math.round((float) height/ (float) reqHeight);
            final int widthRatio = Math.round((float) width / (float) reqWidth);
            inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
        }
        return inSampleSize;
    }

    //把bitmap转换成String
    public static String bitmapToString(String filePath) {
        Bitmap bm = getSmallBitmap(filePath);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        //1.5M的压缩后在100Kb以内,测试得值,压缩后的大小=94486字节,压缩后的大小=74473字节
        //这里的JPEG 如果换成PNG,那么压缩的就有600kB这样
        bm.compress(Bitmap.CompressFormat.JPEG, 40, baos);
        byte[] b = baos.toByteArray();
        Log.d("d", "压缩后的大小=" + b.length);
        return Base64.encodeToString(b, Base64.DEFAULT);
    }


}
private String getPath(Uri uri) {
    String[] projection = {MediaStore.Video.Media.DATA};
    Cursor cursor = managedQuery(uri, projection, null, null, null);
    int column_index = cursor
            .getColumnIndexOrThrow(MediaStore.Audio.Media.DATA);
    cursor.moveToFirst();
    return cursor.getString(column_index);
}

请求网络进行图片对比

private boolean getVerify() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    photo1 = ImageUtils.bitmapToString(getPath(uri));
                    photo2 = ImageUtils.bitmapToString(getPath(uri_));
                    String body = "{\"type\":1,\"content_1\": \"" + photo1 + "\", \"content_2\":\"" + photo2 + "\"}";
                    final String s = sendPost(url, body, ak_id, ak_secret);
                    //解析result
                     final Bean jsonObject = JSON.parseObject(s, Bean.class);
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            if (jsonObject.getConfidence() > 80){
                                Toast.makeText(MainActivity.this,"验证成功",Toast.LENGTH_SHORT).show();
                            }else {
                                Toast.makeText(MainActivity.this,"验证失败",Toast.LENGTH_SHORT).show();
                            }
                        }
                    });

                } catch (final Exception e) {
                    e.printStackTrace();
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            Log.v("sjc——", e.toString());
                            Toast.makeText(MainActivity.this, "对比失败>"+e, Toast.LENGTH_SHORT).show();
                        }
                    });

                }
            }
        }).start();
        return true;
    }

解析 返回数据可以用 FastJson 方便好用。

八、    注意 相机的请求权限,直接使用uri是不行的,经网上各种查阅,可以使用provider,在manifest 中注册provider

<provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="包名.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true"
            >
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths"
                />
        </provider>

res目录下新建xml文件夹,并新建文件file_paths(文件名可以随便取),主要是里边的配置

file_paths文件内容如下

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path path="pasth" name="camera_photos" />
    <external-path name="my_images" path="Android/data/com.example.wmz.network/files/Pictures/" />
    <external-path name="images" path="Pictures/" />
    <external-path name="dcim" path="DCIM/" />
</paths>

本次项目用jar包:

猜你喜欢

转载自blog.csdn.net/weixin_41771564/article/details/80353018