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;}/*** 识别成功回调*/@Overridepublic 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);}}@Overridepublic void onCanceled() {}@Overridepublic void onFailure(int retCode, Bitmap bitmap) {Toast.makeText(XApp.Companion.getContext(), "识别失败", Toast.LENGTH_SHORT);}@Overridepublic void onDenied() {}}public interface IDCardScanCallback {void onIDCardResult(IDCardInfo result);}
}
(2)调用识别业务类,更新UI:
HWIDCardScanBiz.I().startIDCardScanActivity(context, new HWIDCardScanBiz.IDCardScanCallback() {@Overridepublic 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)将ocr_ui模块工程放入工程根目录下,在settings.gradle中添加导入模块工程的配置:
include ':app', 'ocrsdk', 'ocr_ui'
(5)工程/app/build.gradle,导入ocrsdk.aar与ocr_ui模块工程:
//...省略之前配的其他地址
dependencies {//...省略之前配的其他地址implementation(name: 'ocrsdk', ext: 'aar')implementation project(path: ':ocr_ui')
}
2.调用代码实现身份证识别: 第1步:调用SDK方法获取token; 第2步:调用SDK方法打开身份证识别界面; 第3步,在调用的Activity的onActivityResult中调用SDK识别图片中的身份信息。调用身份证SDK业务类:
public class BDIDCardScanBiz {public static final int REQUEST_CODE_CAMERA = 100;private boolean mHasGotToken;private static BDIDCardScanBiz I;public static BDIDCardScanBiz I() {if (I == null) {I = new BDIDCardScanBiz();}return I;}/*** 第1步:调用此方法获取token*/public void getAccessToken() {OCR.getInstance(App.getContext()).initAccessTokenWithAkSk(new OnResultListener() {@Overridepublic void onResult(Object o) {AccessToken accessToken = (AccessToken) o;String token = accessToken.getAccessToken();mHasGotToken = true;}@Overridepublic void onError(OCRError error) {// 调用失败,返回OCRError子类SDKError对象}}, App.getContext(), "Zxuz7GjLGsjBna44UjOQPVJv", "teLf4S7EjI5fjIshagZoovRSKlZSfPwM");}/*** 第2步:调用此方法打开身份证识别界面*/public void startIDCardScanActivity(Activity act) {if (!PermissionUtil.checkCameraPermission(act)) return;Intent intent = new Intent(act, CameraActivity.class);intent.putExtra(CameraActivity.KEY_OUTPUT_FILE_PATH,FileUtils.getSaveFile(App.getContext()).getAbsolutePath());intent.putExtra(CameraActivity.KEY_CONTENT_TYPE, CameraActivity.CONTENT_TYPE_ID_CARD_FRONT);act.startActivityForResult(intent, REQUEST_CODE_CAMERA);}/*** 第3步,在onActivityResult中调此方法,获取身份证信息*/public void handlerData(String contentType) {if (TextUtils.isEmpty(contentType)) return;String filePath = FileUtils.getSaveFile(App.getContext()).getAbsolutePath();if (CameraActivity.CONTENT_TYPE_ID_CARD_FRONT.equals(contentType)) {recIDCard(IDCardParams.ID_CARD_SIDE_FRONT, filePath);} else if (CameraActivity.CONTENT_TYPE_ID_CARD_BACK.equals(contentType)) {recIDCard(IDCardParams.ID_CARD_SIDE_BACK, filePath);}}private void recIDCard(String idCardSide, String filePath) {IDCardParams param = new IDCardParams();param.setImageFile(new File(filePath));// 设置身份证正反面param.setIdCardSide(idCardSide);// 设置方向检测param.setDetectDirection(true);// 设置图像参数压缩质量0-100, 越大图像质量越好但是请求时间越长。 不设置则默认值为20param.setImageQuality(20);param.setDetectRisk(true);OCR.getInstance(App.getContext()).recognizeIDCard(param, new OnResultListener<IDCardResult>() {@Overridepublic void onResult(IDCardResult result) {if (result != null) {//获取身份信息}}@Overridepublic void onError(OCRError error) {}});}
}
三、使用百度云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() {@Overridepublic 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;}相关文章:
Android:身份证识别功能实现
说明: 此文使用华为SDK、百度SDK、百度在线API三种方式实现。 一、使用华为SDK实现身份证识别: 说明:免费,不需要联网。 1.AndroidManifest.xml添加权限:<uses-permission android:name"android.permissio…...
MacOS安装Homebrew教程
安装 Homebrew 是在 macOS 上管理软件包的一种简便方法。以下是安装 Homebrew 的步骤: 打开终端:你可以通过在 Spotlight 搜索栏中输入“终端”并按下回车键来打开 macOS 的终端应用程序。 执行安装命令:在终端中粘贴以下命令并按下回车键执…...
laravel如何通过DB获取一条数据并转成数组
在 Laravel 中,你可以使用原生数据库查询构建器(DB facade)来获取一条数据,并将其转换为数组。这可以通过在查询链的末尾调用 first() 方法后,使用 toArray() 方法来实现。first() 方法会返回一个 StdClass 对象&#…...
ENSP USG防火墙接入虚拟机;开启Web访问;
1.添加防火墙及云,启动防火墙; 2.配置桥接网卡; 默认账户:admin 默认密码:Admin123 #第一次登陆需修改密码; 默认G0/0/0口为管理口,而在模拟器中进入防火墙的web需如下配置: 配置 …...
数据结构算法题(力扣)——链表
以下题目建议大家先自己动手练习,再看题解代码。这里只提供一种做法,可能不是最优解。 1. 移除链表元素(OJ链接) 题目描述:给一个链表的头节点 head 和一个整数 val ,删除链表中所有满足值等于 val 的节点…...
LeetCode---391周赛
题目列表 3099. 哈沙德数 3100. 换水问题 II 3101. 交替子数组计数 3102. 最小化曼哈顿距离 一、哈沙德数 简单的模拟题,代码如下 class Solution { public:int sumOfTheDigitsOfHarshadNumber(int x) {int s 0, tmp x;while(tmp){stmp%10;tmp/10;}return x…...
微信小程序的页面交互2
一、自定义属性 (1)定义: 微信小程序中的自定义属性实际上是由data-前缀加上一个自定义属性名组成。 (2)如何获取自定义属性的值? 用到target或currentTarget对象的dataset属性可以获取数据 ÿ…...
【VSCode】修改插件地址
不想放在原始C盘下面C:\Users\{用户}\.vscode\extensions为了后续存储空间考虑,想通过添加环境变量创建名为VSCODE_EXTENSIONS的环境变量,内容指向vs Code扩展所在目录即可 直接配置环境变量,不要在有空格的文件夹下面 变量名称:…...
自然语言处理NLP概述
大家好,自然语言处理(NLP)是计算机科学领域与人工智能领域中的一个重要方向,其研究能实现人与计算机之间用自然语言进行有效通信的各种理论和方法。本文将从自然语言处理的本质、原理和应用三个方面,对其进行概述。 一、NLP的本质 NLP是一种…...
计算机网络——37认证
认证 目标:Bob需要Alice证明他的身份 Protocol ap1.0:Alice说"A am Alice" 可能出现的问题: 在网络上Bob看不到Alice,因此Trudy可以简单的声称他是Alice 认证:重新尝试 Protocol ap2.0:Alice…...
Java中利用BitMap位图实现海量级数据去重
🏷️个人主页:牵着猫散步的鼠鼠 🏷️系列专栏:Java全栈-专栏 🏷️个人学习笔记,若有缺误,欢迎评论区指正 目录 前言 什么是BitMap?有什么用? 基本概念 位图的优势 …...
Linux知识点记录
Linux知识点记录 1. 后台运行应用程序方法一:&方法二:nohup & 2. 一个shell脚本中执行多个应用程序3. 2>&14. shell脚本清除日志5. 通过grep查找匹配字符串 1. 后台运行应用程序 参考文章:https://blog.csdn.net/Pan_peter/…...
js的check函数
在JavaScript中,并没有一个内置的名为check的函数。然而,你可以根据需求自定义一个check函数,用于执行各种验证和检查任务。这个check函数的具体作用完全取决于你如何定义和实现它。 以下是一个简单的示例,展示了如何定义一个che…...
赛尼格磁电科技邀您到场参观2024第13届生物发酵展
参展企业介绍 北京赛尼格磁电科技有限公司是一家中加合资的专业永磁组件生产商,2001年成立于中国北京。公司专业从事磁性材料的应用及各类磁系统的设计、开发及制造,公司产品广泛应用于汽车行业、建筑行业、电子行业、航海领域、医学领域、教育领域等。 …...
gpt国内怎么用?最新版本来了
claude 3 opus面世后,这几天已经有许多应用,而其精确以及从不偷懒(截止到2024年3月11日还没有偷懒)的个性,也使得我们可以用它来首次完成各种需要多轮对话的尝试。 今天我们想要进行的一项尝试就是—— 如何从一个不知…...
Vim脚本语言入门:打造你的编辑器
简介 Vim脚本语言是Vim编辑器内置的一种脚本语言,它赋予用户高度的定制和自动化编辑任务的能力。通过编写Vim脚本,用户可以根据自己的需求来扩展和改进Vim编辑器的功能,从而提高编辑效率和舒适度。 在Vim中,脚本语言被广泛用于创…...
myweb项目资料集
项目要求 前后端分离后端采用 flask 框架前端采用 vue3 框架 后端部分 Flask 3 框架: https://dormousehole.readthedocs.io/en/latest/quickstart.html Session: https://blog.csdn.net/zhangvalue/article/details/93892241 MySQL 操作…...
Kubernetes(k8s):部署、使用 metrics-server
Kubernetes(k8s):部署、使用 metrics-server 一、metrics-server简介二、部署metrics-server2.1、 下载 Metrics Server 部署文件2.2、修改metrics-server.yaml 文件2.3、 部署 Metrics Server2.4、 检查 Metrics Server 三、使用 Metrics Se…...
为什么建议你学习Spring底层原理?
1.根因 Java诞生以来,一直是业界的主流语言和平台,而Spring则是Java开发的平台。与其说是用Java编程,不如说是在Spring框架上编程。即便最近几年比较火的Spring Boot、Spring Cloud,其底层内核仍然是Spring。因此,作为…...
post请求搜索功能爬虫
<!--爬虫仅支持1.8版本的jdk--> <!-- 爬虫需要的依赖--> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.2</version> </dependency>…...
北京大学钟亦武老师招收博士生、实习生
点击下方卡片,关注“CVer”公众号AI/CV重磅干货,第一时间送达冲刺今年春招、秋招和实习!大家快加入2026年AI校招群!赠送今年最大的80元优惠券,大家扫码下方二维码即可加群学习!北京大学智能学院介绍&#x…...
w3x2lni技术指南:魔兽地图跨版本转换的实现与实践
w3x2lni技术指南:魔兽地图跨版本转换的实现与实践 【免费下载链接】w3x2lni 魔兽地图格式转换工具 项目地址: https://gitcode.com/gh_mirrors/w3/w3x2lni 技术原理:跨版本转换的底层架构 w3x2lni作为魔兽地图格式转换的专业工具,其核…...
【实战】Ubuntu20.04硬盘挂载与权限管理全攻略(从分区合并到ext4格式化)
1. 从Windows迁移到Ubuntu的硬盘处理痛点 刚接触Ubuntu的Windows用户经常会遇到一个头疼问题:原先在Windows下分好区的机械硬盘,在Ubuntu系统里居然"消失"了。这不是硬盘真的不见了,而是Linux系统对NTFS分区的识别机制不同。我去年…...
Gemma-3-12b-it实战教程:极简UI背后隐藏的12B模型内存映射优化策略
Gemma-3-12b-it实战教程:极简UI背后隐藏的12B模型内存映射优化策略 1. 项目概述 Gemma-3-12b-it是一款基于Google Gemma-3-12b-it大模型开发的本地多模态交互工具。这款工具针对12B大模型进行了全维度的CUDA性能优化,支持图片上传和文本提问的流式生成…...
学术PDF处理神器:OpenClaw+GLM-4.7-Flash自动提取关键结论
学术PDF处理神器:OpenClawGLM-4.7-Flash自动提取关键结论 1. 为什么需要自动化文献处理? 作为一名经常需要阅读大量学术文献的研究者,我发现自己花费在整理文献上的时间甚至超过了实际阅读时间。每次下载几十篇PDF后,手动提取目…...
WordPress主题开发实战:从零开始搭建你的第一个自定义主题(2024最新版)
WordPress主题开发实战:从零开始搭建你的第一个自定义主题(2024最新版) 如果你正准备踏入WordPress主题开发的世界,这篇文章将带你从零开始构建一个完整的自定义主题。不同于简单的仿制或修改现有主题,我们将深入探讨如…...
vLLM-v0.17.1在专利分析系统中的应用:权利要求生成与比对
vLLM-v0.17.1在专利分析系统中的应用:权利要求生成与比对 1. 技术背景与需求分析 专利分析是知识产权领域的重要工作,其中权利要求书的生成与比对是核心环节。传统方法依赖人工撰写和比对,效率低下且一致性难以保证。随着大语言模型技术的发…...
告别性能瓶颈:如何用NVIDIA Profile Inspector释放显卡90%潜能?
告别性能瓶颈:如何用NVIDIA Profile Inspector释放显卡90%潜能? 【免费下载链接】nvidiaProfileInspector 项目地址: https://gitcode.com/gh_mirrors/nv/nvidiaProfileInspector 为什么官方显卡控制面板永远像个"锁着的工具箱"&#…...
网页在线编辑 Office 实现|软航控件集成入门实战①
在 OA、ERP、管理系统开发中,网页在线编辑 Office、在线预览 Word/Excel/PPT/PDF是高频刚需。自己从零开发兼容性差、周期长,集成成熟控件是最快、最稳的方案。本文以软航 Office 文档控件为例,从零到一教你完成 Windows 端集成,新…...
5分钟解锁WeMod专业版:开源工具让你的游戏修改体验全面升级
5分钟解锁WeMod专业版:开源工具让你的游戏修改体验全面升级 【免费下载链接】Wemod-Patcher WeMod patcher allows you to get some WeMod Pro features absolutely free 项目地址: https://gitcode.com/gh_mirrors/we/Wemod-Patcher 还在为WeMod专业版的订阅…...
