Android:身份证识别功能实现

说明:

此文使用华为SDK、百度SDK、百度在线API三种方式实现。

一、使用华为SDK实现身份证识别:

说明:免费,不需要联网。

1.AndroidManifest.xml添加权限:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />

2. 工程根目录build.gradle:

buildscript {
    repositories {
        //...省略之前配的其他地址
        maven { url "https://developer.huawei.com/repo/" }
    }
    dependencies {
        //...省略之前配的其他地址
        classpath 'com.huawei.agconnect:agcp:1.6.0.300'
    }
}

allprojects {
    repositories {
        //...省略之前配的其他地址
        maven { url "https://developer.huawei.com/repo/" }
    }
}
3.工程/app/build.gradle:
//...省略之前配的其他地址
apply plugin: 'com.huawei.agconnect'
android {
    //...省略之前配的其他地址
    packagingOptions {
        exclude 'lib/arm64-v8a/libmsoptimize.so'
    }
}
dependencies {
    //...省略之前配的其他地址
    implementation 'com.huawei.hms:ml-computer-card-icr-cn:2.0.3.303'
    implementation 'com.huawei.hms:ml-computer-vision-ocr:2.0.5.301'
    implementation 'com.huawei.hms:ml-computer-vision-ocr-cn-model:2.0.5.301'
    implementation 'com.huawei.hms:ml-computer-vision-ocr-jk-model:2.0.5.301'
    implementation 'com.huawei.hms:ml-computer-vision-ocr-latin-model:2.0.5.301'
    implementation 'com.huawei.hms:ml-computer-card-gcr-plugin:2.0.1.301'
}
4.调用身份证SDK:

(1)身份证识别业务类:

public class HWIDCardScanBiz {
    private static HWIDCardScanBiz I;

    public static HWIDCardScanBiz I() {
        if (I == null) {
            I = new HWIDCardScanBiz();
        }
        return I;
    }

    /**
     * 打开身份证识别页,调用之前要申请蓝牙动态权限
     */
    public void startIDCardScanActivity(Context context, IDCardScanCallback callback) {
        MLCnIcrCaptureConfig config = new MLCnIcrCaptureConfig.Factory()
                .setFront(true)
                .create();
        MLCnIcrCapture icrCapture = MLCnIcrCaptureFactory.getInstance().getIcrCapture(config);
        icrCapture.capture(new HWIDScanCallback(callback), context);
    }


    private class HWIDScanCallback implements MLCnIcrCapture.CallBack {

        private IDCardScanCallback callback;

        public HWIDScanCallback(IDCardScanCallback callback) {
            this.callback = callback;
        }

        /**
         * 识别成功回调
         */
        @Override
        public void onSuccess(MLCnIcrCaptureResult result) {
            if (result == null) {
                Toast.makeText(XApp.Companion.getContext(), "识别失败", Toast.LENGTH_SHORT);
                return;
            }
            if (callback != null) {
                IDCardInfo info = new IDCardInfo(result.name, result.sex, result.nation, result.birthday, result.address, result.idNum, result.authority, result.validDate, result.sideType);
                callback.onIDCardResult(info);
            }
        }

        @Override
        public void onCanceled() {
        }

        @Override
        public void onFailure(int retCode, Bitmap bitmap) {
            Toast.makeText(XApp.Companion.getContext(), "识别失败", Toast.LENGTH_SHORT);
        }

        @Override
        public void onDenied() {
        }
    }

    public interface IDCardScanCallback {
        void onIDCardResult(IDCardInfo result);
    }
}

(2)调用识别业务类,更新UI:

HWIDCardScanBiz.I().startIDCardScanActivity(context, new HWIDCardScanBiz.IDCardScanCallback() {
    @Override
    public void onIDCardResult(IDCardInfo result) {
        /*
result.name: 姓名
result.sex:性别
result.nation:国籍
result.birthday:生日
result.address:地址
result.idNum:身份证号
result.validDate:有效期
         */
    }
});

二、使用百度云SDK实现身份证识别:

说明:免费额度个人帐户每月1千次/企业帐户每月2千次,要联网。

1.添加配置:
(1)AndroidManifest.xml添加权限:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
(2)proguard-rules.pro添加混淆例外:
-keep class com.baidu.ocr.sdk.**{*;}
-dontwarn com.baidu.ocr.**
(3)将ocrsdk.aar放入工程\app\libs目录下。

(4)从以下地址(控制台-公有云-应用列表-进入某个应用详情页)下载aip-ocr.license放入工程\app\src\main\assets下:
https://console.bce.baidu.com/ai/#/ai/ocr/app/detail~appId=4571869
(5)将ocr_ui模块工程放入工程根目录下,在settings.gradle中添加导入模块工程的配置:
include ':app', 'ocrsdk', 'ocr_ui'
(6)工程/app/build.gradle,导入ocrsdk.aar与ocr_ui模块工程:
//...省略之前配的其他地址
repositories {
    flatDir {
        dirs 'libs'
    }
}
dependencies {
    //...省略之前配的其他地址
    implementation(name: 'ocrsdk', ext: 'aar')
    implementation project(path: ':ocr_ui')
}
2.调用代码实现身份证识别:
第1步:调用SDK方法获取token;
第2步:调用SDK方法打开身份证识别界面;
第3步,在调用的Activity的onActivityResult中调用SDK识别图片中的身份信息。

身份证SDK业务类:
public class IDCardScanBiz {
    public static final int REQUEST_CODE_CAMERA = 100;
    private boolean mHasGotToken;
    private static IDCardScanBiz I;


    public static IDCardScanBiz I() {
        if (I == null) {
            I = new IDCardScanBiz();
        }
        return I;
    }

    /**
     * 第1步,调用此方法获取token
     */
    public void initToken() {
        OCR.getInstance(ExampleApplication.Companion.getContext()).initAccessTokenWithAkSk(new OnResultListener() {
            @Override
            public void onResult(Object o) {
                Log.i("BDIDCard", "getAccessToken onResult >>> o: " + o.toString());
                mHasGotToken = true;
                init();
            }

            @Override
            public void onError(OCRError error) {
                Log.i("BDIDCard", "getAccessToken onError >>> error: " + error.toString());
                // 调用失败,返回OCRError子类SDKError对象
            }
        }, ExampleApplication.Companion.getContext(), "gPxzwMwJVfENiggqd6csyE85", "hcTVlJYj8sKGEgWngy8Qmp83mNxVqp8O");
    }


    /**
     * 初始化本地质量控制模型
     */
    private void init() {
        Context context = ExampleApplication.Companion.getContext();
        CameraNativeHelper.init(context, OCR.getInstance(context).getLicense(), (errorCode, e) -> Log.i("BDIDCard", "init onError >>> errorCode: " + errorCode));
    }

    /**
     * 第2步:调用此方法打开身份证识别界面
     */
    public void startIDCardScanActivity(Activity act) {
        if (!mHasGotToken) return;
        Intent intent = new Intent(act, CameraActivity.class);
        intent.putExtra(CameraActivity.KEY_OUTPUT_FILE_PATH, getSaveFile().getAbsolutePath());
        intent.putExtra(CameraActivity.KEY_NATIVE_ENABLE, true);
        intent.putExtra(CameraActivity.KEY_NATIVE_MANUAL, true);
        intent.putExtra(CameraActivity.KEY_CONTENT_TYPE, CameraActivity.CONTENT_TYPE_ID_CARD_FRONT);
        act.startActivityForResult(intent, REQUEST_CODE_CAMERA);
    }

    /**
     * 第3步,在onActivityResult中调此方法,调用百度云API获取照片中的身份证信息
     */
    public void readIDCard() {
        if (!mHasGotToken) return;
        String filePath = getSaveFile().getAbsolutePath();
        IDCardParams param = new IDCardParams();
        param.setImageFile(new File(filePath));
        // 设置身份证正反面
        param.setIdCardSide(IDCardParams.ID_CARD_SIDE_FRONT);
        // 设置方向检测
        param.setDetectDirection(true);
        // 设置图像参数压缩质量0-100, 越大图像质量越好但是请求时间越长。 不设置则默认值为20
        param.setImageQuality(20);
        param.setDetectRisk(true);
        OCR.getInstance(ExampleApplication.Companion.getContext()).recognizeIDCard(param, new OnResultListener<IDCardResult>() {
            @Override
            public void onResult(IDCardResult result) {
                Log.i("BDIDCard", "recIDCard result >>> result: " + result.toString());
                if (result != null) {//获取身份信息
                }
            }

            @Override
            public void onError(OCRError error) {
                Log.i("BDIDCard", "recIDCard result >>> error: " + error.toString());
            }
        });
    }

    public static File getSaveFile() {
        File file = new File(ExampleApplication.Companion.getContext().getFilesDir(), "pic.jpg");
        return file;
    }
}

调用业务类的Activity:

class MainActivity : Activity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        var ps = arrayOf(Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE)
        ActivityCompat.requestPermissions(this, ps, 100);
        IDCardScanBiz.I().initToken()
    }

    fun onScanClick(v: View) {
        IDCardScanBiz.I().startIDCardScanActivity(this)
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == IDCardScanBiz.REQUEST_CODE_CAMERA && resultCode == RESULT_OK) {
            IDCardScanBiz.I().readIDCard()
        }
    }

}

三、使用百度云API实现身份证识别:

说明:免费额度个人帐户每月1千次/企业帐户每月2千次,要联网。

1.AndroidManifest.xml添加权限:

同上面两种

2.调用代码实现身份证识别:
第1步,调用百度API获取token:

public static String getToken() {
        String url = "https://aip.baidubce.com/oauth/2.0/token?client_id=" + Config.CLIENT_ID + "&client_secret=" + Config.CLIENT_SECRET + "&grant_type=client_credentials";
        if (!NetHelp.getCurConnectStatus()) {
            return null;
        }
        Response response = null;
        try {
            Request request = new Request.Builder().url(url).get().build();
            LogUtils.d("getToken request url :" + url);
            response = httpClient.newCall(request).execute();
        } catch (IOException e) {
            LogUtils.d("getToken request exception: " + e.getMessage());
            e.printStackTrace();
            return null;
        }
        LogUtils.d("getToken response isSuccessful: " + response.isSuccessful());
        if (response != null && response.isSuccessful()) {
            try {
                String strRecData = response.body().string();
                LogUtils.d("getToken response body: " + strRecData);
                if (strRecData != null && strRecData.length() > 2) {
                    JSONObject jsonObj = new JSONObject(strRecData);
                    if (jsonObj != null && !jsonObj.isNull("access_token")) {
                        return jsonObj.getString("access_token");
                    }
                }
                return response.body().string();
            } catch (Exception e) {
                LogUtils.d("getToken response parse exception: " + e.getMessage());
                e.printStackTrace();
                return null;
            }
        }
        return null;
    }

第2步,调用系统相机拍身份证照片(可以自已实现带身份证头像框的拍照功能,界面更加美观):

    /**
     * 调起系统相机进行拍照,此步可以自已实现拍照功能,界面更美观
     */
    public void startIDCardScanActivity(Activity act) {
        Log.i("IDCard", "IDCard startIDCardScanActivity >>>");
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        if (intent.resolveActivity(act.getPackageManager()) != null) {
            act.startActivityForResult(intent, REQUEST_CODE_CAMERA);
        }
    }

第3步,在onActivityResult中,将图片上传百度API获取身份证信息:

    /**
     * 解析身份证图片,获取身份信息
     */
    public void handlerData(Activity act, Intent data, IDCardScanCallback callback) {
        new Thread() {
            @Override
            public void run() {
                Bundle bundle = data.getExtras();
                Log.i("IDCard", "IDCard handlerData bundle >>> : " + bundle);
                if (bundle == null) return;
                Bitmap bitmap = (Bitmap) bundle.get("data");
                Log.i("IDCard", "IDCard handlerData bitmap >>> : " + bitmap);
                if (bitmap == null) return;
                File file = new File(App.getContext().getCacheDir(), System.currentTimeMillis() + ".jpeg");
                if (!file.getParentFile().exists()) file.mkdirs();
                try {
                    FileOutputStream out = new FileOutputStream(file);
                    bitmap.compress(Bitmap.CompressFormat.JPEG, 80, out);
                    out.flush();
                    out.close();
                    Log.i("IDCard", "IDCard saveBitmap  filePath: " + file.getAbsolutePath() + "  fileLen: " + file.length());
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
                String filePath = file.getAbsolutePath();
                Log.i("IDCard", "IDCard parseImage >>>  filePath: " + filePath);
                final IDCardInfo info = HttpHelp.getIDCard(new File(filePath));
                if (info != null && callback != null) {
                    act.runOnUiThread(() -> callback.onIDCardResult(info));
                }
            }
        }.start();
    }

    public static IDCardInfo getIDCard(File file){
        if (!NetHelp.getCurConnectStatus() || file == null || file.length() <= 0){
            return null;
        }
        String accessToken = getToken();
        if (TextUtils.isEmpty(accessToken)) return null;
        String url = "https://aip.baidubce.com/rest/2.0/ocr/v1/idcard?access_token=" + accessToken;
        String img = null;
        try {
            img = FileUtils.base64File(file);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (TextUtils.isEmpty(img)) return null;
        Response response = null;
        try {
            FormBody.Builder builder = new FormBody.Builder()
                    .add("id_card_side", "front")
                    .add("image", img);
            Request request = new Request.Builder()
                    .url(url)
                    .post(builder.build())
                    .build();
            LogUtils.d("getIDCard request url :" + url + "   img: " + img);
            response = httpClient.newCall(request).execute();
        } catch (IOException e) {
            LogUtils.d("getIDCard request exception: " + e.getMessage());
            e.printStackTrace();
            return null;
        }
        LogUtils.d("getIDCard response isSuccessful: " + response.isSuccessful());
        if (response != null && response.isSuccessful()) {
            try {
                String strRecData = response.body().string();
                LogUtils.d("getIDCard response body: " + strRecData);
                if (strRecData != null && strRecData.length() > 2) {
                    JSONObject rootObj = new JSONObject(strRecData);
                    if (rootObj != null && !rootObj.isNull("words_result")) {
                        JSONObject wordObj = rootObj.getJSONObject("words_result");
                        IDCardInfo info = new IDCardInfo();
                        if (!wordObj.isNull("姓名") && !wordObj.getJSONObject("姓名").isNull("words")) {
                            info.name = wordObj.getJSONObject("姓名").getString("words");
                        }
                        if (wordObj != null && !wordObj.isNull("民族") && !wordObj.getJSONObject("民族").isNull("words")) {
                            info.nation = wordObj.getJSONObject("民族").getString("words");
                        }
                        if (wordObj != null && !wordObj.isNull("住址") && !wordObj.getJSONObject("住址").isNull("words")) {
                            info.address = wordObj.getJSONObject("住址").getString("words");
                        }
                        if (wordObj != null && !wordObj.isNull("公民身份号码") && !wordObj.getJSONObject("公民身份号码").isNull("words")) {
                            info.idNum = wordObj.getJSONObject("公民身份号码").getString("words");
                        }
                        if (wordObj != null && !wordObj.isNull("出生") && !wordObj.getJSONObject("出生").isNull("words")) {
                            info.birthday = wordObj.getJSONObject("出生").getString("words");
                        }
                        if (wordObj != null && !wordObj.isNull("性别") && !wordObj.getJSONObject("性别").isNull("words")) {
                            info.sex = wordObj.getJSONObject("性别").getString("words");
                        }
                        LogUtils.d("getIDCard response parse IDCardInfo: " + info.toString());
                        return info;
                    }
                }
            } catch (Exception e) {
                LogUtils.d("getIDCard response parse exception: " + e.getMessage());
                e.printStackTrace();
                return null;
            }
        }
        return null;
    }
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Android Studio中实现代码识别身份证信息需要借助OCR技术和相关的图像处理库。首先,我们可以通过使用Android提供的Camera API来获取身份证图片,然后将其传入OCR引擎进行处理。 在Android Studio中,我们可以引入开源OCR库,例如Tesseract-OCR或者百度OCR等。这些库可以识别图像中的文字,并返回识别结果。我们可以根据OCR库的文档和示例代码来实现身份证信息的识别。 一般来说,OCR库提供了一些API来实现图像的预处理和文字识别。我们可以使用这些API来识别身份证图片中的各项信息,例如姓名、性别、民族、出生日期、住址等。 具体的实现步骤如下: 1. 在Android项目中引入OCR库的依赖,使用Gradle或者Maven配置。 2. 在布局文件中放置一个CameraView,用于预览身份证的图片。 3. 使用Camera API来获取身份证图片,并将其传给OCR引擎进行处理。可以通过设置拍照按钮或者自动拍照进行图片的获取。 4. 对获取到的图片进行预处理,例如图像增强、灰度化、二值化等操作,以便提高识别的准确性。 5. 将预处理后的图片传给OCR引擎进行文字识别,获取识别结果。 6. 分析识别结果,提取身份证信息。可以使用正则表达式或者字符串处理方法来匹配和抽取需要的信息字段。 7. 将提取到的身份证信息展示在界面上,或者其他进一步的处理,例如保存到数据库或者上传到服务器。 需要注意的是,实现身份证信息的识别是相对复杂的,涉及到图像处理和文字识别的算法。因此,建议在实际开发过程中,参考OCR库的官方文档和示例代码,根据具体需求做相应的调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值