Android使用阿里云接口实现身份证识别功能

前言

现如今,许多app需要智能识别用户提供的身份证图片上的信息来完成一些工作,阿里云刚好提供了这个接口,下面我们实现一个小的demo来和大家学习一下。

效果图:

随便在网上找了两张身份证图片,识别并得到结果,num为空因为这个身份证号码是不存在的,真实身份证是可以得到想要的结果的。

该项目的githup地址为:https://github.com/gumaoqi/ALiYunDemo

你可以去将项目clone下来,然后查看或更改来达到自己的需求。

我的另一篇人脸检测博客地址:https://blog.csdn.net/gumaoqi861469629/article/details/82964050,也是通过阿里云的接口。有兴趣的可以去看一看

申请KEY

这里我在完成了功能后将appcode修改了,你需要自行申请购买才能正常运行,下面先介绍如何申请key。

如下图:

打开阿里云首页---产品---人工智能---点击"通用型卡证类"进入下一个页面---身份证识别模块点击"立即购买"进入下一个页面---如果没有购买点击"立即购买"(阿里云提供了0元500次免费的次数);如果已经购买滑动到下方点击"API简单身份认证调用方法"进入下一个页面---点击"查看我的appcode值"就可以查看想要的信息了。

上代码前先吐槽一下,阿里云给的java的示例代码用的是pom.xml管理依赖,而我们经常使用的是as作为开发工具,用build.gradle管理依赖。且示例代码使用的网络请求方式org.apache.http.httpResponse在Android的版本大于22就不支持了(好像是这样,因为这个原因我根据阿里云的demo改了很久都没能成功),然后我去网上搜索其他人的项目,居然没有一个下载下来是可以用的(可能是我能力不够,配置不来环境),于是决定自己动手写一下,最后我选择了使用retrofit网络请求框架来完成。

代码:


build.gradle

    implementation 'com.squareup.retrofit2:retrofit:2.0.2'//添加retrofit依赖
    implementation 'com.squareup.okhttp3:okhttp:3.1.2'//由于retrofit依赖okhttp,所以需要添加okhttp依赖
    implementation 'com.squareup.retrofit2:converter-gson:2.0.2'
    //由于retrofit网络识别的返回结果的处理需要用到gson,添加依赖

使用retrofit网络请求框架请添加上述三个依赖


AndroidMainfest.xml

<!-- 添加使用网络的权限 -->
<uses-permission android:name="android.permission.INTERNET" />

由于需要网络请求,添加网络权限


activity_main_xml

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

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:id="@+id/activity_main_bt_one"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="检测第一张" />

        <Button
            android:id="@+id/activity_main_bt_two"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="检测第二张" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <ImageView
            android:id="@+id/activity_main_iv_one"
            android:layout_width="240dp"
            android:layout_height="160dp"
            android:src="@mipmap/id" />

        <ImageView
            android:id="@+id/activity_main_iv_two"
            android:layout_width="240dp"
            android:layout_height="160dp"
            android:src="@mipmap/id2" />
    </LinearLayout>


    <TextView
        android:id="@+id/activity_main_tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="我是用来显示识别结果的" />

</LinearLayout>

布局很简单,两个button用于点击,两个imageview用于展示图片,一个textview用于显示识别结果。


MainActivity.java

 

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Base64;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import com.google.gson.Gson;

import java.io.ByteArrayOutputStream;
import java.io.IOException;

import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.http.Body;
import retrofit2.http.Header;
import retrofit2.http.POST;

public class MainActivity extends AppCompatActivity {
    Button buttonOne;
    Button buttonTwo;
    TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        buttonOne = findViewById(R.id.activity_main_bt_one);
        buttonTwo = findViewById(R.id.activity_main_bt_two);
        textView = findViewById(R.id.activity_main_tv);
        buttonOne.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.id);
                idCardRecognition(bitmap);
            }
        });
        buttonTwo.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.id2);
                idCardRecognition(bitmap);
            }
        });
    }

    public void idCardRecognition(Bitmap bitmap) {
        String appcode = "f785099e36b442aa983a79259735917d";
        String body = "{\n" +
                "\t\"image\":  \"" + base64ToNoHeaderBase64(bitmapToBase64(bitmap)) + "\",\n" +
                "\t\"configure\": \"{\\\"side\\\":\\\"face\\\"}\" \n" +
                "}";
        final RequestBody requestBody = RequestBody.create(okhttp3.MediaType.parse("application/json;charset=UTF-8"), body);
        Retrofit retrofit = new Retrofit.Builder()
                .addConverterFactory(GsonConverterFactory.create(new Gson()))
                .baseUrl("http://dm-51.data.aliyun.com/")//接口的默认地址
                .build();
        IdTestService idTestService = retrofit.create(IdTestService.class);
        Call<ResponseBody> call = idTestService.getTestResult(requestBody, "APPCODE " + appcode);
        call.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                try {
                    textView.setText(response.body().string());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {
                Log.i("123", t.getMessage());
            }
        });

    }

    /**
     * 将Bitmap转换成Base64字符串
     *
     * @param bitmap
     * @return
     */
    public static String bitmapToBase64(Bitmap bitmap) {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.JPEG, 40, bos);//参数100表示不压缩
        byte[] bytes = bos.toByteArray();
        //转换来的base64码需要加前缀,必须是NO_WRAP参数,表示没有空格。
        return "data:image/jpeg;base64," + Base64.encodeToString(bytes, Base64.NO_WRAP);
    }

    /**
     * 将base64的头去掉
     *
     * @param base64
     * @return
     */
    public static String base64ToNoHeaderBase64(String base64) {
        return base64.replace("data:image/jpeg;base64,", "");
    }

    public interface IdTestService {
        @POST("rest/160601/ocr/ocr_idcard.json")
            //接口字段
        Call<ResponseBody> getTestResult(@Body RequestBody body,
                                         @Header("Authorization") String authorization
        );
    }
}

idCardRecognition方法,识别身份证的具体方法,方法内包含了如何构造retrofit的body,如何创建请求。

bitmapToBase64方法和base64ToNoHeaderBase64方法,将bitmap转换成没有头的base64数据。

IdTestService接口,retrofit使用到的接口。@POST标签表示使用post方法请求,后面跟请求的具体地址;@Body标签,请求体,用于携带需要识别的图片的数据;@Header请求头,用于携带appcode。


至此,已成功利用阿里云的接口实现了身份证识别的内容,检测了两张程序中的身份证图片,具体应用时,图片可以来自摄像头、图库和网络,通过人身份证识别达到不同的功能。

博主水平有限,如有指正错误和其他建议请在评论区留言。

后记

可以结合阿里云身份证识别和人脸对比功能,来判断用户上传的头像和身份证是否为同一个人,然后通过活体检测功能判断是否为一个真人(即非图片和视频的人);由于活体检测费用昂贵(1次/1元)且公司的app中没有需求,所以博主没有仔细去研究。有兴趣的朋友可以自己去研究一下,接下来可能会写一篇两张图片人脸对比、身份证图片和人脸图片对比的文章。

身份证识别

  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值