Android实现扫一扫识别数字功能
1.准备工作
- 首先实现识别数字等字符,我们要知道需要采用ocr (optical character recognition,光学字符识别)来实现。而tesseract是非常不错的开源ocr工具,但是要在android中直接使用可能要费点功夫。不过不用担心,tess-two拯救了我们。
- 其次是扫一扫识别,那么很快联想到的就是常见的二维码扫描这类的项目。通过扫一扫实时拿到图像,来做识别。
- 接下来在github上找到了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); tessbaseapi.init(path, "eng"); //eng为识别语言 tessbaseapi.setvariable(tessbaseapi.var_char_whitelist, "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz0123456789"); // 识别白名单 tessbaseapi.setvariable(tessbaseapi.var_char_blacklist, "!@#$%^&*()_+=-[]}{;:'\"\\|~`,./<>?"); // 识别黑名单 tessbaseapi.setpagesegmode(tessbaseapi.pagesegmode.psm_auto_osd);//设置识别模式 tessbaseapi.setimage(bitmap); //设置需要识别图片的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) { bf.deletecharat(len - 1); } return bf.tostring(); }
修改后如下:(同时支持多个号码)
当然本项目也保留了扫码功能(可在decodehandler中自己添加条码格式):
细心的同学可以从图中看到扫描框的大小都不一样,这里我是改成了可以手动调节大小的扫描框。毕竟扫码模式下,框大一点还是比较好识别(将二维码放入框中有时就费时间)。扫数字这些文字时,框小一点会好识别。具体可以下载自行体验。
最后我将代码已经上传至github:tesseract-ocr-scanner
总结
以上所述是小编给大家介绍的android实现扫一扫识别数字功能,希望对大家有所帮助