苏州小芳 發表於 2020-4-22 09:59:00

Android | 教你如何在安卓上实现通用卡证识别,一键各种卡绑定

<p></p><div class="toc"><div class="toc-container-header">目录</div><ul><li>前言</li><li>通用卡证识别的应用场景</li><li>如何使用通用卡证识别服务</li><li>集成通用卡证识别服务的关键流程</li><li>开发实战<ul><li>1 开发准备<ul><li>1.1 在项目级gradle里添加华为maven仓</li><li>1.2 在应用级的build.gradle里面加上SDK依赖</li><li>1.3 配置混淆脚本</li><li>1.4 在AndroidManifest.xml文件里面申请相机和存储权限</li></ul></li><li>2 代码开发<ul><li>2.1 启动卡证识别</li></ul></li><li>2.2 对识别后的内容做后处理,进行关键信息提取</li></ul></li><li>Demo 效果</li><li>github 源码</li></ul></div><p></p>
<h1 id="前言">前言</h1>
<p>  华为HMS MLKit提供的服务越来越多了,上期给大家介绍了银行卡识别的功能,从上期的介绍中我们可以了解到使用专用的银行卡识别接口,几行代码就可以完成银行卡卡号的识别,那么有的小伙伴可能会问,我想识别的卡不是银行卡,会员卡可以识别吗,或者某一类证件号识别?也没有问题~但因为不同商家的卡号位置,版面样式各异,所以无法像银行卡识别那样使用专用的银行卡识别API,这个时候我们可以选用通用卡证识别的能力,通用卡证识别可以给大家提供一个标准的通用卡证对准框,大家只需要拉起这个对准框,就可以获取对准框内识别到的卡证全部内容,这个时候再针对这些内容按照一定的规则做关键信息提取,即可获取到自己想要的内容,比如连续的8位数字即为卡号,或者在某些特殊字母后的内容即为卡号内容。</p>
<h1 id="通用卡证识别的应用场景">通用卡证识别的应用场景</h1>
<p>  通用卡证识别,顾名思义,是各种卡证的识别,能识别的范围很广,常用的应用场景:</p>
<ul>
<li>旅游绑证<br>
旅游类APP需要对身份证等信息进行绑定,用于购票、酒店预订等场景,通过对此类证件进行拍照自动识别,可以避免手动输入证件号容易出错的问题。</li>
</ul>
<p><img src="https://img-blog.csdnimg.cn/20200422090113482.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDcwODI0MA==,size_16,color_FFFFFF,t_70#pic_center"></p>
<ul>
<li>购物绑卡<br>
购物类APP,通过拍照识别快速绑定会员卡、购物卡、打折卡。</li>
</ul>
<p><img src="https://img-blog.csdnimg.cn/20200422090425620.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDcwODI0MA==,size_16,color_FFFFFF,t_70#pic_center"></p>
<blockquote>
<p>银行卡、中国二代身份证号码识别虽然可以也可以使用通用卡证识别来完成,但推荐使用华为ML Kit的专有的银行卡识别、身份证识别的API,专有卡证识别针对银行卡、身份证识别做了特别的优化,准确率更高,可以直接返回处理好以后的卡号数据,小编后续可以详细介绍下专有卡证和通用卡证识别的区别。</p>
</blockquote>
<h1 id="如何使用通用卡证识别服务">如何使用通用卡证识别服务</h1>
<p><img src="https://img-blog.csdnimg.cn/20200422091000816.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDcwODI0MA==,size_16,color_FFFFFF,t_70#pic_center"><br>
  给大家画了个简单的流程图,可以看到只需要把图片、拍照、视频流传给ML Kit,即可获取到对应的识别内容,针对识别内容做一定后处理即可提取出要识别的卡证号内容。</p>
<h1 id="集成通用卡证识别服务的关键流程">集成通用卡证识别服务的关键流程</h1>
<p><img src="https://img-blog.csdnimg.cn/20200422091228739.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDcwODI0MA==,size_16,color_FFFFFF,t_70#pic_center"><br>
  可以看到开发流程也非常的简单,只需要启动卡证识别Activity,获取Activity识别到的内容,然后对内容做简单后处理提取关键信息就可以完成代码开发了。</p>
<p><strong>核心提示,端侧能力全免费,全终端覆盖!非华为手机也可以使用</strong></p>
<h1 id="开发实战">开发实战</h1>
<p>  本次的开发实战中实现了对港澳通行证、回乡证、香港居民身份证的处理,大家伙可参考实现。</p>
<h2 id="1-开发准备">1 开发准备</h2>
<p>详细的准备步骤可以参考华为开发者联盟:<br>
https://developer.huawei.com/consumer/cn/doc/development/HMS-Guides/ml-process-4</p>
<p>这里列举关键的开发步骤。</p>
<h3 id="11-在项目级gradle里添加华为maven仓">1.1 在项目级gradle里添加华为maven仓</h3>
<p>  打开AndroidStudio项目级build.gradle文件,增量添加如下maven地址:</p>
<pre><code class="language-java">buildscript {
    repositories {      
      maven {url 'http://developer.huawei.com/repo/'}
    }    }allprojects {
    repositories {      
      maven { url 'http://developer.huawei.com/repo/'}
    }}
</code></pre>
<h3 id="12-在应用级的buildgradle里面加上sdk依赖">1.2 在应用级的build.gradle里面加上SDK依赖</h3>
<pre><code class="language-java">dependencies{
// 引入基础SDK
implementation 'com.huawei.hms:ml-computer-vision-ocr:1.0.3.300'
// 引入拉丁语文字识别模型包
implementation 'com.huawei.hms:ml-computer-vision-ocr-latin-model:1.0.3.300'
// 引入银行卡识别plugin包
implementation 'com.huawei.hms:ml-computer-card-gcr-plugin:1.0.3.300' }
</code></pre>
<p>  将以下语句添加到AndroidManifest.xml文件中:</p>
<pre><code class="language-java">&lt;manifest
    ...
    &lt;meta-data            
      android:name="com.huawei.hms.ml.DEPENDENCY"   
      android:value= "ocr"/&gt;
    ... &lt;/manifest&gt;
</code></pre>
<h3 id="13-配置混淆脚本">1.3 配置混淆脚本</h3>
<p>按照官网操作指导来就行了:<br>
https://developer.huawei.com/consumer/cn/doc/development/HMS-Guides/ml-configuringobfuscation-scripts-4</p>
<h3 id="14-在androidmanifestxml文件里面申请相机和存储权限">1.4 在AndroidManifest.xml文件里面申请相机和存储权限</h3>
<p>都是些基本操作,废话也不多说,按照官网指导来操作:<br>
https://developer.huawei.com/consumer/cn/doc/development/HMS-Guides/ml-assigning-permissions-4</p>
<h2 id="2-代码开发">2 代码开发</h2>
<h3 id="21-启动卡证识别">2.1 启动卡证识别</h3>
<pre><code class="language-java">@Override
public void onClick(View v) {
    switch (v.getId()) {
      // 相册图片检测按钮。
      case R.id.detect_picture:
            this.startLocalImageActivity(cardImage, null, callback);
            break;
      // 视频流检测按钮。
      case R.id.detect_video:
            this.startCaptureActivity(null, callback);
            break;
      // 拍照检测按钮。
      case R.id.detect_take_photo:
            this.startTakePhotoActivity(null, callback);
            break;
      default:
            break;
      } }
</code></pre>
<p>视频流识别</p>
<pre><code class="language-java">private void startCaptureActivity(Object object, MLGcrCapture.Callback callback) {
    // 创建通用卡证识别配置器。
    MLGcrCaptureConfig cardConfig = new MLGcrCaptureConfig.Factory().create();
    // 创建通用卡证识别界面配置器。
    MLGcrCaptureUIConfig uiConfig = new MLGcrCaptureUIConfig.Factory()      
      // 设置扫描框颜色。
      .setScanBoxCornerColor(Color.GREEN)
      // 设置扫描框中的提示文字,建议少于30个字符。
      .setTipText("Recognizing, align edges")
      // 设置识别界面横竖屏,支持三种模式:
      // MLGcrCaptureUIConfig.ORIENTATION_AUTO:自动模式,由物理感应器决定显示方向。
      // MLGcrCaptureUIConfig.ORIENTATION_LANDSCAPE:横屏模式。
      // MLGcrCaptureUIConfig.ORIENTATION_PORTRAIT:竖屏模式。
      .setOrientation(MLGcrCaptureUIConfig.ORIENTATION_AUTO)
      .create();
    // 方式一:根据自定义的卡证识别界面配置器,创建通用卡证识别处理器。
    MLGcrCapture ocrManager = MLGcrCaptureFactory.getInstance().getGcrCapture(cardConfig, uiConfig);
    // 方式二:使用默认界面,创建通用卡证识别处理器。
    MLGcrCapture ocrManager = MLGcrCaptureFactory.getInstance().getGcrCapture(cardConfig);
    // 绑定通用卡证识别处理器和处理结果回调函数。
    ocrManager.capturePreview(this, object, callback); }
</code></pre>
<p>拍照识别</p>
<pre><code class="language-java">private void startTakePhotoActivity(Object object, MLGcrCapture.Callback callback) {
    // 创建通用卡证识别配置器。
    MLGcrCaptureConfig cardConfig = new MLGcrCaptureConfig.Factory().create();
    // 创建通用卡证识别界面配置器。
    MLGcrCaptureUIConfig uiConfig = new MLGcrCaptureUIConfig.Factory()
      // 设置扫描框颜色。
      .setScanBoxCornerColor(Color.BLUE)
      // 设置扫描框中的提示文字,建议少于30个字符。
      .setTipText("Taking picture, align edges")
      // 设置界面横竖屏,支持三种模式:
      // MLGcrCaptureUIConfig.ORIENTATION_AUTO:自动模式,由物理感应器决定显示方向。
      // MLGcrCaptureUIConfig.ORIENTATION_LANDSCAPE:横屏模式。
      // MLGcrCaptureUIConfig.ORIENTATION_PORTRAIT:竖屏模式。
      .setOrientation(MLGcrCaptureUIConfig.ORIENTATION_AUTO)
      .create();
    // 方式一:根据自定义的卡证识别界面配置器,创建通用卡证识别处理器。
    MLGcrCapture ocrManager = MLGcrCaptureFactory.getInstance().getGcrCapture(cardConfig, uiConfig);
    // 方式二:使用默认界面,创建通用卡证识别处理器。
    MLGcrCapture ocrManager = MLGcrCaptureFactory.getInstance().getGcrCapture(cardConfig);
    // 绑定通用卡证识别处理器和处理结果回调函数。
    ocrManager.capturePhoto(this, object, callback); }
</code></pre>
<p>相册图片识别</p>
<pre><code class="language-java">private void startLocalImageActivity(Bitmap bitmap, Object object, MLGcrCapture.Callback callback) {
    // 创建通用卡证识别配置器。
    MLGcrCaptureConfig config = new MLGcrCaptureConfig.Factory().create();
    MLGcrCapture ocrManager = MLGcrCaptureFactory.getInstance().getGcrCapture(config);
    // bitmap 为需要识别的Bitmap类型卡证图像,支持的图片格式包括:jpg/jpeg/png/bmp。
    ocrManager.captureImage(bitmap, object, callback); }
</code></pre>
<h2 id="22-对识别后的内容做后处理进行关键信息提取">2.2 对识别后的内容做后处理,进行关键信息提取</h2>
<p>  重载onResult, onCanceled, onFailure, onDenied四个方法;onResult表示返回了结果,MLGcrCaptureResult为卡证识别返回的结果,onCanceled 表示用户取消,onFailure 表示识别失败,onDenied 表示相机不可用等场景。</p>
<pre><code class="language-java">private MLGcrCapture.Callback callback = new MLGcrCapture.Callback() {
      @Override
      public int onResult(MLGcrCaptureResult result, Object object) {
            Log.i(TAG, "callback onRecSuccess");
            if (result == null) {
                Log.e(TAG, "callback onRecSuccess result is null");
                return MLGcrCaptureResult.CAPTURE_CONTINUE;
            }

            GeneralCardProcessor idCard = null;
            GeneralCardResult cardResult = null;
            /*港澳台通行证处理*/            
            if (cardTypeEnum == CardType.PASSCARD) {
                idCard = new PassCardProcessor(result.text);
            /*香港身份证处理*/
            } else if (cardTypeEnum == CardType.HKIDCARD) {
                idCard = new HKIdCardProcessor(result.text);
            /*回乡证处理*/
            } else if (cardTypeEnum == CardType.COMEHOMECARD) {
                idCard = new HomeCardProcessor(result.text);
            }
            if (idCard != null) {
                /*获取处理后的结果*/
                cardResult = idCard.getResult();
            }

            showFrontImage(result.cardBitmap);
            displayResult(cardResult);

            // If the results don't match
            if (cardResult == null || cardResult.valid.isEmpty() || cardResult.number.isEmpty()) {
                return MLGcrCaptureResult.CAPTURE_CONTINUE;
            }

            displayResult(cardResult);
            return MLGcrCaptureResult.CAPTURE_STOP;
      }      
    };}   
};
</code></pre>
<p>  具体的卡号提取处理逻辑可以通过重写GeneralCardProcessor 类中的getResult()方法来完成,以港澳台通行证举例,更加详细的处理可以看github上的源码:</p>
<pre><code class="language-java">public class PassCardProcessor implements GeneralCardProcessor {
    private static final String TAG = "PassCardProcessor";

    private final MLText text;

    public PassCardProcessor(MLText text) {
      this.text = text;
    }
    @Override
    public GeneralCardResult getResult() {
      List&lt;MLText.Block&gt; blocks = text.getBlocks();
      if (blocks.isEmpty()) {
            Log.i(TAG, "Result blocks is empty");
            return null;
      }
      ArrayList&lt;BlockItem&gt; originItems = getOriginItems(blocks);
      String valid = "";
      String number = "";
      boolean validFlag = false;
      boolean numberFlag = false;
      for (BlockItem item : originItems) {
            String tempStr = item.text;
            if (!validFlag) {
                String result = tryGetValidDate(tempStr);
                if (!result.isEmpty()) {
                  valid = result;
                  validFlag = true;
                }
            }
            if (!numberFlag) {
                String result = tryGetCardNumber(tempStr);
                if (!result.isEmpty()) {
                  number = result;
                  numberFlag = true;
                }
            }
      }      
      return new GeneralCardResult(valid, number);
    } }
</code></pre>
<h1 id="demo-效果">Demo 效果</h1>
<p>看下Demo效果如何,是不是还不错!<br>
<img src="https://img-blog.csdnimg.cn/20200422092443429.gif#pic_center"></p>
<h1 id="github-源码">github 源码</h1>
<p>源码已经上传github,大家也可以在github上一起完善该功能。<br>
github源码地址:https://github.com/HMS-MLKit/HUAWEI-HMS-MLKit-Sample</p>
<p>通用卡证识别demo代码路径:<br>
MLKit-Sample\module-text\src\main\java\com\mlkit\sample\activity\GeneralCardRecognitionActivity.java</p>
<p><strong>更详细的开发指南参考华为开发者联盟官网</strong><br>
华为开发者联盟机器学习服务开发指南</p>
<hr>
<p>往期链接:Android | 教你如何在安卓上实现二代身份证识别,一键实名认证<br>
内容来源:https://developer.huawei.com/consumer/cn/forum/topicview?tid=0201226181206630022&amp;fid=18<br>
原作者:AI_talking</p><br><br>
来源:https://www.cnblogs.com/developer-huawei/p/12750086.html
頁: [1]
查看完整版本: Android | 教你如何在安卓上实现通用卡证识别,一键各种卡绑定