当前位置:   article > 正文

android ocr 身份证识别_android ocr 身份证 git

android ocr 身份证 git

ocr opencv 想必做过程图像识别的同学们都对这两个词不陌生吧。

ocr (optical character recognition ,光学字符识别) 是指电子设备(例如扫描仪或数码相机)检查纸上的字符,通过检测暗,亮的模式确定其形状,然后用字符识别方法将形状翻译成计算机文字的过程。 这样就给我编程提供了接口,我们可以识别图片的文字了 (有些文档我们通过手机拍照的,直接生成word )身份证识别,银行卡识别等。

opencv 是什么呢

OpenCV的全称是:Open Source Computer Vision Library。OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉库,可以运行在Linux、Windows和Mac OS操作系统上。它轻量级而且高效——由一系列 C 函数和少量 C++ 类,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。

上面是 百度百科给出的定义说白了就是给我们编程提供的类库而已

android 如果想使用OCR  

我们可以使用google 开源的项目tesseract-ocr 

github 下载地址:https://github.com/justin/tesseract-ocr

今天我不讲如何编译 ocr 这个东西  

主要说下,识别二维码的这个项目和tesseract-ocr 整合成一个识别身份证号码的 过程

后面我会把他们编译成类库供大家使用的

ORC 识别方法已经封装成一个简单的类 OCR

 

  1. package com.dynamsoft.tessocr;
  2. import android.content.Context;
  3. import android.content.res.AssetManager;
  4. import android.graphics.Bitmap;
  5. import android.os.Environment;
  6. import com.googlecode.tesseract.android.TessBaseAPI;
  7. import java.io.File;
  8. /**
  9. * Created by CYL on 2016/3/26.
  10. * email:670654904@qq.com
  11. * 这个类 就是调用 ocr 的接口
  12. * 这个是识别过程是耗时的 操作 请放到线程 操作
  13. */
  14. public class OCR {
  15. private TessBaseAPI mTess;
  16. private boolean flag;
  17. private Context context;
  18. private AssetManager assetManager;
  19. public OCR() {
  20. // TODO Auto-generated constructor stub
  21. mTess = new TessBaseAPI();
  22. String datapath = Environment.getExternalStorageDirectory() + "/tesseract/";
  23. String language = "eng";
  24. //请将你的语言包放到这里 sd 的 tessseract 下的tessdata 下
  25. File dir = new File(datapath + "tessdata/");
  26. if (!dir.exists())
  27. dir.mkdirs();
  28. flag = mTess.init(datapath, language);
  29. }
  30. /**
  31. * 识别出来bitmap 上的文字
  32. * @param bitmap 需要识别的图片
  33. * @return
  34. */
  35. public String getOCRResult(Bitmap bitmap) {
  36. String result = "dismiss langues";
  37. if(flag){
  38. mTess.setImage(bitmap);
  39. result = mTess.getUTF8Text();
  40. }
  41. return result;
  42. }
  43. public void onDestroy() {
  44. if (mTess != null)
  45. mTess.end();
  46. }
  47. }


方法很简单 :

 

创建对象,调用getOcrResult方法就行了,注意这个识别过程是耗时,放到线程去操作。避免ANR问题

然后我们需要把识别集成到二维码扫描里面  

下面这个对二维码扫描这个项目介绍的比较详细

http://www.cnblogs.com/weixing/archive/2013/08/28/3287120.html

 

 下面给大家介绍一下,ZXing库里面主要的类以及这些类的作用:

  • CaptureActivity。这个是启动Activity 也就是扫描器。
  • CaptureActivityHandler 解码处理类,负责调用另外的线程进行解码。
  • DecodeThread 解码的线程。
  • com.google.zxing.client.android.camera 包,摄像头控制包。
  • ViewfinderView 自定义的View,就是我们看见的拍摄时中间的框框了。

 我可以简单考虑一下  图片识别,我们需要先获取图片才能识别,当识别成功以后应该将数据返回  并反馈给用户我们已经完成了识别。

第一首先 我们如何获取图像 即 bitmap 从上面主要功能的类可以看出来。

我应该去captureactivityhandler 解码处理处理中去找,不管识别二维码还是图片,身份证啊。最终都是识别bitmap 

所以我们这里可以找到相机捕捉到的图像;

 

DecodeHandler

 

  1. /*
  2. * Copyright (C) 2010 ZXing authors
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package com.sj.app.decoding;
  17. import android.graphics.Bitmap;
  18. import android.os.Bundle;
  19. import android.os.Handler;
  20. import android.os.Looper;
  21. import android.os.Message;
  22. import android.util.Log;
  23. import com.dynamsoft.tessocr.OCR;
  24. import com.google.zxing.BinaryBitmap;
  25. import com.google.zxing.DecodeHintType;
  26. import com.google.zxing.MultiFormatReader;
  27. import com.google.zxing.ReaderException;
  28. import com.google.zxing.Result;
  29. import com.google.zxing.common.HybridBinarizer;
  30. import com.sj.app.camera.CameraManager;
  31. import com.sj.app.camera.PlanarYUVLuminanceSource;
  32. import com.sj.app.utils.IdMatch;
  33. import com.sj.erweima.MipcaActivityCapture;
  34. import com.sj.erweima.R;
  35. import java.util.Hashtable;
  36. import java.util.List;
  37. final class DecodeHandler extends Handler {
  38. private static final String TAG = DecodeHandler.class.getSimpleName();
  39. private final MipcaActivityCapture activity;
  40. private final MultiFormatReader multiFormatReader;
  41. DecodeHandler(MipcaActivityCapture activity,
  42. Hashtable<DecodeHintType, Object> hints) {
  43. multiFormatReader = new MultiFormatReader();
  44. multiFormatReader.setHints(hints);
  45. this.activity = activity;
  46. }
  47. @Override
  48. public void handleMessage(Message message) {
  49. switch (message.what) {
  50. case R.id.decode:
  51. // Log.d(TAG, "Got decode message");
  52. decode((byte[]) message.obj, message.arg1, message.arg2);
  53. break;
  54. case R.id.quit:
  55. Looper.myLooper().quit();
  56. break;
  57. }
  58. }
  59. /**
  60. * Decode the data within the viewfinder rectangle, and time how long it
  61. * took. For efficiency, reuse the same reader objects from one decode to
  62. * the next.
  63. *
  64. * @param data
  65. * The YUV preview frame.
  66. * @param width
  67. * The width of the preview frame.
  68. * @param height
  69. * The height of the preview frame.
  70. */
  71. private void decode(byte[] data, int width, int height) {
  72. long start = System.currentTimeMillis();
  73. Result rawResult = null;
  74. // modify here
  75. byte[] rotatedData = new byte[data.length];
  76. for (int y = 0; y < height; y++) {
  77. for (int x = 0; x < width; x++)
  78. rotatedData[x * height + height - y - 1] = data[x + y * width];
  79. }
  80. int tmp = width; // Here we are swapping, that's the difference to #11
  81. width = height;
  82. height = tmp;
  83. PlanarYUVLuminanceSource source = CameraManager.get()
  84. .buildLuminanceSource(rotatedData, width, height);
  85. BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
  86. try {
  87. //相机中捕捉到的
  88. Bitmap image = source.renderCroppedGreyscaleBitmap();
  89. doorc(source);
  90. rawResult = multiFormatReader.decodeWithState(bitmap);
  91. } catch (ReaderException re) {
  92. // continue
  93. } finally {
  94. multiFormatReader.reset();
  95. }
  96. if (rawResult != null) {
  97. long end = System.currentTimeMillis();
  98. Log.d(TAG, "Found barcode (" + (end - start) + " ms):\n"
  99. + rawResult.toString());
  100. Message message = Message.obtain(activity.getHandler(),
  101. R.id.decode_succeeded, rawResult);
  102. Bundle bundle = new Bundle();
  103. bundle.putParcelable(DecodeThread.BARCODE_BITMAP,
  104. source.renderCroppedGreyscaleBitmap());
  105. message.setData(bundle);
  106. // Log.d(TAG, "Sending decode succeeded message...");
  107. message.sendToTarget();
  108. } else {
  109. Message message = Message.obtain(activity.getHandler(),
  110. R.id.decode_failed);
  111. message.sendToTarget();
  112. }
  113. }
  114. private Handler handler = new Handler(){
  115. public void handleMessage(Message msg) {
  116. CardId cardId = (CardId) msg.obj;
  117. if(cardId != null){
  118. Message message = Message.obtain(activity.getHandler(),
  119. R.id.decode_succeeded, cardId.id);
  120. Bundle bundle = new Bundle();
  121. bundle.putParcelable(DecodeThread.BARCODE_BITMAP,
  122. cardId.bitmap);
  123. message.setData(bundle);
  124. // Log.d(TAG, "Sending decode succeeded message...");
  125. message.sendToTarget();
  126. }
  127. };
  128. };
  129. private void doorc(final PlanarYUVLuminanceSource source) {
  130. new Thread(new Runnable() {
  131. @Override
  132. public void run() {
  133. Bitmap bitmap = source.renderCroppedGreyscaleBitmap();
  134. String id = new OCR().getOCRResult(bitmap);
  135. if(id != null){
  136. List<String> list = IdMatch.machId(id);
  137. if(list!= null && list.size()>0){
  138. String cardId = list.get(0);
  139. if(cardId != null){
  140. Message msg = Message.obtain();
  141. CardId cardId2 = new CardId(cardId, bitmap);
  142. msg.obj = cardId2;
  143. handler.sendMessage(msg);
  144. }
  145. }
  146. }
  147. }
  148. }).start();
  149. }
  150. public class CardId{
  151. private String id;
  152. private Bitmap bitmap;
  153. public CardId(String id, Bitmap bitmap) {
  154. super();
  155. this.id = id;
  156. this.bitmap = bitmap;
  157. }
  158. public String getId() {
  159. return id;
  160. }
  161. public void setId(String id) {
  162. this.id = id;
  163. }
  164. public Bitmap getBitmap() {
  165. return bitmap;
  166. }
  167. public void setBitmap(Bitmap bitmap) {
  168. this.bitmap = bitmap;
  169. }
  170. }
  171. }

 

 

 

当解析成功的时候就将结果通过handler 返回到UI 线程中去了,对于 扫描框我们可以响应调节。

CameraManager 这个类 控制扫描框的大小。
 
  1. public Rect getFramingRect() {
  2. Point screenResolution = configManager.getScreenResolution();
  3. if (framingRect == null) {
  4. if (camera == null) {
  5. return null;
  6. }
  7. int width = screenResolution.x * 7 / 8;
  8. if (width < MIN_FRAME_WIDTH) {
  9. width = MIN_FRAME_WIDTH;
  10. } else if (width > MAX_FRAME_WIDTH) {
  11. // width = MAX_FRAME_WIDTH;
  12. }
  13. int height = screenResolution.y * 3 / 4;
  14. if (height < MIN_FRAME_HEIGHT) {
  15. height = MIN_FRAME_HEIGHT;
  16. } else if (height > MAX_FRAME_HEIGHT) {
  17. height = MAX_FRAME_HEIGHT;
  18. }
  19. int leftOffset = (screenResolution.x - width) / 2;
  20. int topOffset = (screenResolution.y - height) / 2;
  21. framingRect = new Rect(leftOffset, topOffset, leftOffset + width, topOffset + height);
  22. Log.d(TAG, "Calculated framing rect: " + framingRect);
  23. }
  24. return framingRect;
  25. }


改变这个方法就可以改变这个扫描框的大小了。

demo 地址
链接: https://pan.baidu.com/s/1uPekNyHVUV2QFX7AAZ1QvQ 密码: xxiz   《百度云盘》
上面的找个地址对应应用源码文案可是二维码,给大家造成了很大的误会,今天特意更新一下地址基本逻辑没有变化
只是更新代码文案。。。 在这里也恳请大家原谅以前的粗心
需要提示的是 如果您的手机是android 6.0以上 请查看 sd卡根目录是否存在tesseract/tessdata目录 以及下面的文件  如果没有存在说明 应用没有获取到存储权限。
 
 

 

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/683077
推荐阅读
相关标签
  

闽ICP备14008679号