关键词:
前言
OCR 是 Optical Character Recognition 的缩写,翻译为光学字符识别,指的是针对印刷体字符,采用光学的方式将纸质文档中的文字转换成为黑白点阵的图像文件,通过识别软件将图像中的文字转换成文本格式,供文字处理软件进一步编辑加工的技术(好吧,这是我查来的)。简单的来说,OCR技术就是可以把图片上的文字识别出来,并以文本格式的形式提取出来。
这个技术的应用方面很广泛,比如说把纸质书籍的内容转化为电子书,之前都需要人手打,但是现在只要扫描一下,将扫描出来的图片通过OCR技术转化成文本格式,效率和成本不知提升了多少倍。
有人可能会想,这个技术听起来好高端,不懂计算机图形学,模式识别,机器学习巴拉巴拉东西的人,是不是无法接触到这样的技术,实现这样的功能,(好像是的,emmm...),不过,虽然咱们自己实现不了,但是有人把轮子造好了呀,我们只要使用人家造好的轮子,就能实现图片文字识别的功能。
先来看一下我实现的效果吧,随手拿了办公桌上有字的东西(拿了枸杞茶和菊花茶的包装...),用自己写的demo拍了照识别了一下
界面下方显示的图片是手机拍的照片,界面上方显示的是从照片中识别出来的文字信息。可以看出识别的正确率还是挺高的。
我这边用的轮子是 百度文字识别 。下面我将介绍一下我是如何实现上述的文字识别功能。
请求模块定义
百度其实有提供图片识别Android的SDK,就像其他的SDK一样,只要导入一系列包之后就可以调用识别。寻求快速开发的小伙伴可以了解一下,我看了一下文档,实现还是十分容易的。
但是,我在demo中使用的并非是SDK,而是使用另外一种方法——以网络api的方式来进行识别。涉及到的技术有 retrofit+rxjava 进行网络请求(在之前的一篇博客中有介绍如何使用 retrofit+rxjava ,贴一下链接),Android应用动态权限的申请,FileProvider,图片的base64转码,以及热门的MVP框架。
先看一下项目结构
module目录下存放的是MVP架构的三个模块,bean目录下存放的是网络请求返回的数据类型,apiservice中存放的是retrofit有关网络请求的接口。
我们定义出如下的接口方法。
/**
* 通过图片URL的形式,获取图片内的文字信息
* @param accessToken 通过API Key和Secret Key获取的access_token
* @param url 图片的url
* @return observable对象用于rxjava,从RecognitionResultBean中可以获得图片文字识别的信息
*/
在第一个方法中,我们需要传入两个参数,一个是access_token,需申请百度文字识别的开发者资格,得到API key和Secret Key后获取,还有一个参数是图片的网络地址url,可以直接通过这个url直接访问到图片。
第二个方法中,第一个参数也是同上的access_token,第二个参数则是String类型,这个参数是在本地将图片base64转码之后生成。
因为我们要实现的功能是用手机拍照,然后将照片信息传递给服务器,因此我们之后调用的是第二个方法(第一个方法只是我按照api说明随手写了一下),这些参数我们以POST的形式发送,按照百度OCRapi 的要求,需要加上@FormUrlEncode注释,我们使用@Field的方式将参数加入请求体。可以看到Observable中的是RecognitionResultBean类型,我们可以从里面拿到服务器返回的文字识别信息。
定义好这两个方法之后,我们便可以构造retrofit对象进行调用
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://aip.baidubce.com/")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
baiduOCRService = retrofit.create(BaiduOCRService.class);
我们来看一下 rxjava+retrofit 在接口方法中的具体实现
@Override
public void getRecognitionResultByImage(Bitmap bitmap)
String encodeResult = bitmapToString(bitmap);
baiduOCRService.getRecognitionResultByImage(ACCESS_TOKEN,encodeResult)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<RecognitionResultBean>()
@Override
public void onSubscribe(Disposable d)
@Override
public void onNext(RecognitionResultBean recognitionResultBean)
Log.e("onnext",recognitionResultBean.toString());
StringBuilder s = new StringBuilder();
List<RecognitionResultBean.WordsResultBean> wordsResult = recognitionResultBean.getWords_result();
for (RecognitionResultBean.WordsResultBean words:wordsResult)
s.append(words.getWords());
mView.updateUI(s.toString());
@Override
public void onError(Throwable e)
Log.e("onerror",e.toString());
@Override
public void onComplete()
);
可以看到传入了一个Bitmap类型的图片参数,这个参数经过 String encodeResult = bitmapToString(bitmap); 方法转成了String类型。是因为接口要求的参数数据为String类型,所以我们对图片进行了base64转码,具体的转码方法如下:
private String bitmapToString(Bitmap bitmap)
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] bytes = baos.toByteArray();
return Base64.encodeToString(bytes, Base64.DEFAULT);
调用此方法,便可以把图片类型转化成字符串类型,之后的操作便是对网路接口调用之后的回调方法进行定义,我们在调用成功后的onNext操作中,拿到了RecognitionResultBean类型参数,这个参数里含有图片所包含文字的信息,我们将所有的文字一一取出,用StringBuilder连接成一个字符串,返回给View层,调用View层的updateUI进行UI界面的更新,对于这个字符串我们在之后还可以进行进一步的分析操作。
以上,百度OCR接口请求模块定义部分便已完成,接下来,我们要做的就是调用系统的相机功能,拍照得到照片,将照片传递给我们上面定义的请求接口,进行文字识别。
相机功能调用
首先,由于要对相机功能进行调用,我们需要在AndroidManifest清单文件中写明我们需要用到的权限
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.CAMERA"/>
分别是网络请求权限,数据的读存取权限,以及相机权限。在Android 6.0 之前应用的权限在安装时全部授予,也就是说只要在AndroidManifest中申请过的权限,都会给予。而在 Android 6.0 或更高版本之后,对权限的管理作出了改变,对某些涉及到用户隐私的权限可在运行时根据用户的需要动态授予,也就是说,在AndroidManifest中申请的权限,在用户使用的过程中还得询问用户是否给予,用户给予权限了,应用才能进行相关的权限操作。因此我们需在代码中增加动态权限申请的模块(对用户安全性友好了,但是对开发者增加了不友好度....),以下是动态权限申请部分的代码:
private boolean hasPermission()
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
|| ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
|| ContextCompat.checkSelfPermission(this,Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED)
ActivityCompat.requestPermissions(this, new String[]Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.CAMERA, PERMISSIONS_REQUEST_CODE);
return false;
else
return true;
代码的主要逻辑是,在程序运行的时候,检查是否有相应的权限,如果有权限,则可以进行相关操作,如果没有权限,就调用申请权限的方法。在完成这部分代码的编写之后还需重写onRequestPermissionsResult方法,对申请权限的结果进行反应。
接下来是调用相机功能的代码
private void takePhoto()
if (!hasPermission())
return;
Intent intent = new Intent();
intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/img";
if (new File(path).exists())
try
new File(path).createNewFile();
catch (IOException e)
e.printStackTrace();
String filename = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
mTmpFile = new File(path, filename + ".jpg");
mTmpFile.getParentFile().mkdirs();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
String authority = getPackageName() + ".provider";
imageUri = FileProvider.getUriForFile(this, authority, mTmpFile);
else
imageUri = Uri.fromFile(mTmpFile);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
startActivityForResult(intent, CAMERA_REQUEST_CODE);
需要提到的是,在Android 7.0之后,如果你使用Intent携带这样的上面的imageUri去打开相机拍照,会抛出FileUriExposedException异常。这时候就需要用到google官方的解决方案——FileProvider。使用的方法可以参照 Android 7.0适配-应用之间共享文件
调用相机之后我们需要重写onActivityResult方法,对返回拍照结果进行处理,
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
if (requestCode == CAMERA_REQUEST_CODE)
if (requestCode == RESULT_OK)
Bitmap photo = BitmapFactory.decodeFile(mTmpFile.getAbsolutePath());
mPresenter.getRecognitionResultByImage(photo);
imageView.setImageBitmap(photo);
如果拍照成功,我们就把照片作为参数传递给之前定义好的接口方法,调用进行图片文字识别。可以看到我还把照片放入imageview中方便与识别结果进行对比。等服务器成功返回识别结构之后,就会调用VIew层的updateUI,更新textview显示识别结果。
至此,我们就完成了从拍照到拿到识别结果的全部功能。再来识别一下公交卡
嗯,不错。
最后
这个demo实现了单纯的图片文字识别,就是把图片上的字读取了出来,在此之上我们可以进一步做很多有意思的事,比如用正则表达式把字符串里的一些字提取出来进行操作,像食品的营养成分表啊,发票单子啊,都可以拿来识别,将里面的有用信息提取出来,进行分析处理操作,将功能进一步扩展。
当然,在实现这些功能之后,我们最后还是得感谢为我们提供轮子的大佬,哈哈。
贴上本项目的github地址 reggie1996/CharacterRecognition
作者:reggie1996
链接:https://www.jianshu.com/p/0ed2c5656035
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
基于百度ocr提取图像中的文本(代码片段)
从图片或者扫描版的pdf文件中提取出文本信息的需求在日常工作和学习中经常遇到。扫描版的pdf文件可以使用adobeacrobat将文本数据提取出来,不过adobeacrobat安装文件较大且收费。部分网站也提供在线OCR服务,这些网站在不注册的... 查看详情
基于百度ocr提取图像中的文本(代码片段)
从图片或者扫描版的pdf文件中提取出文本信息的需求在日常工作和学习中经常遇到。扫描版的pdf文件可以使用adobeacrobat将文本数据提取出来,不过adobeacrobat安装文件较大且收费。部分网站也提供在线OCR服务,这些网站在不注册的... 查看详情
百度ocr文字识别接口使用(代码片段)
最近有个需求需要识别图片中的文字,所以就用到了百度的ocr接口,结果在测试的过程中被图片格式搞的有点晕,试了好久终于成功了,在此记录一下。附ocr接口文档地址:https://cloud.baidu.com/doc/OCR/OCR-API.html#.E8.BF.94.E5.9B.9E.E8.AF.B4... 查看详情
借助百度ocr,实现一键识别图片中文字,就是这么酷!
...百度提供的OCR接口,实现了一个有趣的小应用:一键识别图片中文字经过一个小时的反复测试,没想到识别确实很高,而且,居然还可以识别稍微复杂的验证码比如: 主要为了方便了自己,也顺便方便了大家娱乐,直接就将... 查看详情
基于paddlelite的ocr识别身份证号码应用
...工程PaddleLiteOCRGitHub源码链接我们今天主要是做Android的 查看详情
ocr软件是文字识别软件,怎么样用在百度文件中?
什么意思?是说百度文库中吗?ORC是识别图片中的文字的,对图片也有一定的要求,不同软件不一样的参考技术AOCR仅能把图像上的文字有条件的识别; 参考技术B用汉王文豪7600(图形OCR识别成WORD或EXCEL),支持图形、照片、屏... 查看详情
一款android图文识别与扫描软件
OCR图文识别App是一款准确高效的OCR文字识别与扫描软件,识别准确度高,速度快,扫描文件清晰,可导出TXT、Excel。免费使用。技术基于百度在业界领先的人工智能与深度学习技术,提供对身份证、银行卡、营业执照等常用卡片... 查看详情
研发干货丨基于ok3399-c平台android系统下实现图像识别
首先我们了解下android系统常用的图像识别框架 一:调用一些不开源库进行识别旷视的图像识别及OCR文字识别库,及其他厂家如阿里,百度,华为,腾讯的OCR文字识别库等。 二:调用一些开源库进行识别... 查看详情
图片识别ocr:
使用Python制作一个简易的OCR图片文字识别工具:键盘上的PrtScr按键+画图工具+百度AI图片识别(账户,调用接口)+python常见的OCR工具:1.MicrosoftOnenote实在是找不到那个右键-->copyastext2.GoogleOneDrive对中文的效果不好,另外境内访问... 查看详情
tesseract-ocr-03-图片文字识别
Tesseract-OCR-03-图片文字识别本篇介绍使用Tesseract-OCR做图片文字识别,识别手写文字的时候,正确率能达到90%,当训练后正确率是极高的。这里介绍的图片文字识别,可以识别英文,数字和中文等Tesseract-OCR图片文字识别Tesseract:... 查看详情
调用百度ai接口实现图片文字识别技术demo(代码片段)
一、第一步,到https://console.bce.baidu.com/二、创建应用三、pom.xml里面加入依赖org.jsonjson20160810<!--https://mvnrepository.com/artifact/log4j/log4j--><dependency><groupId>log4j</groupId>&l 查看详情
ocr文字识别—基于ctc/attention/ace的三大解码算法
本文全面梳理一下OCR文字识别三种解码算法,先介绍一下什么是OCR文字识别,然后介绍一下常用的特征提取方法CRNN,最后介绍3种常用的解码算法CTC/Attention/ACE。什么是OCR文字识别?一般来说,文字识别之前需... 查看详情
将图片局部文字提取出来的小技巧
如何对图片中的文字内容进行识别提取呢?当图片中的文字需要编辑需改时,又该如何去操作呢?通常情况下,对于图片局部提取文字方面,我们都是借助相关OCR文字识别请添加链接描述工具来实现,下面就是具体的操作方法,... 查看详情
怎么在迅捷ocr文字识别软件中将图片文字识别出来
工作中我们经常会遇到从图片中识别文字的问题,如果我们一个字一个字打出来,太浪费时间了,这时候就需要使用借助到文字识别软件来帮助实现图片文字识别的问题了,具体要怎样去操作呢?一起来看看下面的方法。 解... 查看详情
在迅捷ocr文字识别软件中怎么进行图片局部识别
怎么进行图片局部识别呢?我们在观看一些图片的时候,有些图片上的文字我们会需要将局部文字识别提取出来,但是如何去识别呢,借助图片文字识别软件就可以帮助实现了,下面为大家讲解下具体的操作方法。 使用工具... 查看详情
快速实现图片文字识别的步骤
进行图片文字识别,相信大家都知道,在工作中我们经常会收到上级给我们的文件,其中肯定是有图片文件的,面对整理图片信息大家的方法是什么呢?下面小编就给大家介绍一个简单图片文字识别的步骤,以后再实现图片文字... 查看详情
如何在迅捷ocr文字识别软件中进行图片局部识别
...信很多朋友都知道OCR文字识别,通过OCR识别可以快速的将图片文件中的文字识别出来转换成文字格式,那如果是图片局部识别的话又该如何去操作呢,下面就来为大家讲解一下。 使用工具:迅捷OCR文字识别软件。 第一步... 查看详情
利用python识别出图片中的文字
参考技术Afromkkb_ocrimportocr_wordurl='https://xiaoke-asset-prod.kaikeba.com/python_ai/demos/demo1.jpg'ocr_word(url) 查看详情