专栏名称: 鸿洋
你好,欢迎关注鸿洋的公众号,每天为您推送高质量文章,让你每天都能涨知识。点击历史消息,查看所有已推送的文章,喜欢可以置顶本公众号。此外,本公众号支持投稿,如果你有原创的文章,希望通过本公众号发布,欢迎投稿。
目录
相关文章推荐
开发者全社区  ·  大佬与梁文锋第一次的接触 ·  17 小时前  
开发者全社区  ·  某上市公司90后美女投关进去了 ·  昨天  
郭霖  ·  你所不知道的Android ... ·  4 天前  
开发者全社区  ·  中年男人「失去性欲」的标志 ·  2 天前  
开发者全社区  ·  爽子做三了? ·  3 天前  
51好读  ›  专栏  ›  鸿洋

Android 拍照自动识别手机号 | OCR

鸿洋  · 公众号  · android  · 2017-10-23 07:30

正文

本文作者


作者: 唯鹿

链接:

http://blog.csdn.net/qq_17766199/article/details/77963278

本文由作者投稿推送。


与作者沟通发现了一些注意事项: 篇文章demo中做了扫描结果正则校验,所以在运行demo时,要保证扫描的数字为手机号(如果需要扫描其他类型数字,记得修改代码);此外,扫描框可以手动调整大小,越小越容易扫描。


公司业务需求,需要做手机号码的识别。所以有了此篇文章,现在就将实现过程分享给大家。


1
准备工作



1. 首先实现识别数字等字符,我们要知道需要采用OCR (Optical Character Recognition,光学字符识别)来实现。而tesseract是非常不错的开源OCR工具,但是要在Android中直接使用可能要费点功夫。不过不用担心,tess-two拯救了我们。


  • https://github.com/tesseract-ocr/tesseract

  • https://github.com/rmtheis/tess-two


2. 其次是扫一扫识别,那么很快联想到的就是常见的二维码扫描这类的项目。通过扫一扫实时拿到图像,来做识别。


3. 接下来在Github上找到了QrCodeScanner项目,作者通过一定的优化,使得识别的效率有所提升。那么我们用它来扫描数字,也会有效率上的提升。


  • https://github.com/iluhcm/QrCodeScanner


2
实现细节



1.首先是tess-two的用法。


app下的build.gradle的配置如下


android {
   defaultConfig {
      ....
       ndk {
           abiFilters 'armeabi' //自行选择添加
       }
   }
}
dependencies {
   compile 'com.rmtheis:tess-two:8.0.0'
}


识别方法:


public String detectText(Bitmap bitmap) {
   TessBaseAPI tessBaseAPI = new TessBaseAPI();
   //训练数据路径
   String path = "";
   tessBaseAPI.setDebug(true);
   //eng为识别语言
   tessBaseAPI.init(path, "eng");
   // 识别白名单
   tessBaseAPI.setVariable(
       TessBaseAPI.VAR_CHAR_WHITELIST,
       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
   // 识别黑名单
   tessBaseAPI.setVariable(
       TessBaseAPI.VAR_CHAR_BLACKLIST,
           "!@#$%^&*()_+=-[]}{;:'\"\\|~`,./<>?");
   //设置识别模式
   tessBaseAPI.setPageSegMode(
       TessBaseAPI.PageSegMode.PSM_AUTO_OSD);
   //设置需要识别图片的bitmap
   tessBaseAPI.setImage(bitmap);
   String inspection = tessBaseAPI.getHOCRText(0);
   tessBaseAPI.end();
   return inspection ;
}


训练数据可以在tessdata下载,里面包含各种语言。当然你自己也可以训练它,有兴趣的可以学习一下相关内容。


2.从tess-two的用法可以知道,我们最终需要的是识别图片的Bitmap。在扫码项目中我们找到在DecodeHandler类的decode方法中,我们会得到一个PlanarYUVLuminanceSource类的实例。在使用HybridBinarizer算法解析数据源,最终采用MultiFormatReader解析图像出结果。


代码大致如下:


Result rawResult = null;
MultiFormatReader mMultiFormatReade = new MultiFormatReader();
try {
   PlanarYUVLuminanceSource source =
               new PlanarYUVLuminanceSource(```, false);
   BinaryBitmap bitmap =
       new BinaryBitmap(new HybridBinarizer(source));
   rawResult = mMultiFormatReader.decode(bitmap, mHints);
} catch (ReaderException ignored) {
} finally {
   mMultiFormatReader.reset();
}



看完后懵逼了,没有Bitmap。经过一番查找,找到了在旧版的zxing中PlanarYUVLuminanceSource类有renderCroppedGreyscaleBitmap方法,不知为何去除了。。。


3.之后修改了一些相机的参数信息,适配了部分设备的预览效果。基本的页面修改了一下。这里就不赘述了。


走一波,如下效果:



可以发现除了数字以外,它将中文识别为了字母。


其实问题首先是我们使用了英文的训练数据,同时白名单设置了a~z的字母。当然你也不能将字母设置为黑名单,那样只会让识别不出的字符识别为乱七八糟的数字。


这里我给出的建议是利用正则去筛选,这样你可以识别你想要的各种格式数据。 我这里只是做了手机号的简单识别 ,大家可以举一反三去处理。


public static String getTelNum(String sParam){
   if(TextUtils.isEmpty(sParam)){
       return "";
   }
   Pattern pattern =
       Pattern.compile("(1|861)(3|5|7|8)\\d{9}$*");
   Matcher matcher = pattern.matcher(sParam);
   StringBuilder bf = new StringBuilder();
   while (matcher.find()) {
       bf.append(matcher.group()).append(",");
   }
   int len = bf.length();
   if (len > 0






请到「今天看啥」查看全文