基于Python的离线OCR图片文字识别(一)——命令行方式对图像文件处理生成同名txt文件

应用背景:在正式开始文章之前,先阐述一下项目的应用背景——项目需要对已有的电子档案数据进行“大数据”处理和呈现,但是由于之前进行档案电子化时都是以扫描文件的图像格式存储在硬盘上(准确来说是电子化的档案,不是数字化的档案),且文档的命名是00100001.jpg等完全与档案内容无关的数字格式。为了对这些档案文件进行数字化,首先就需要对档案内容进行OCR识别,这样才能为将来的档案大数据处理奠定基础,例如基于内容的检索、分词和词频统计、添加标签、档案数据的可视化呈现等操作。同时,由于档案的敏感性和保密性原因,不能利用百度或腾讯之类的在线上传类OCR应用,只能选择不联网的离线实现的OCR方式。另外,为了与现有的大数据系统便于集成,需要将上述的OCR功能做成命令行的方式;最后,现有的大数据系统是基于centOS7系统,所以需要基于Linux平台实现OCR功能。

言归正传,经过简单的调研,发现基于Python可以实现上述目标,共有3种途径:一个是大名鼎鼎Google的tesseract-ocr(资源我都放在百度网盘上了,需要的可以自取,链接:https://pan.baidu.com/s/1Z2Lq2nEfqIrNjvfn4ziB3A?pwd=7777 ),但是很不幸,与Google的声名在外相比,tesseract的中文OCR识别效果在我测试的几种开源库中是最差的,基本上相当于是Adobe Acrobat上面自带的OCR那种水平,而且需要先安装tesseract-ocr-w64-setup-v5.0.0.20211201.exe,然后再pip install pytesseract才能使用,而项目需要在Linux平台上实现,所以Pass!另一个是百度的飞桨PaddleOCR,百度的人工智能做的不错,飞桨的OCR功能也很强大,但是感觉相对于一个简单的OCR文字识别来说,百度的飞桨系统好像太大了(其实就是我有点儿懒不想预热太久而想快速上手),有点儿杀鸡用牛刀的感觉。最终我还是选择了一个在GitHub上星星最多的easyOCR(资源我都放在百度网盘上了,需要的可以自取,链接:百度网盘 请输入提取码 ),简约而不简单,上手极快,大约只花了半个小时就可以快速实现自己的离线OCR识别了!很快就写出了第一个版本的OCR命令行式程序,也就是下面的第一个版本,包括注释在内仅三十多行:

#!/home/super/miniconda3/bin/python
#encoding=utf-8

#命令行模式下全文ocr识别,命令格式为:python imgs2txts.py 文件1.jpg 文件2.jpg 文件3.jpg ... ---> 文件.txt
#语言库目录为home下的固定目录: /home/langdata
import sys
import os
import easyocr

ocrreader=easyocr.Reader(['ch_sim', 'en'], model_storage_directory=r'/home/langdata')#Linux
#ocrreader=easyocr.Reader(['ch_sim', 'en'], model_storage_directory=r'E:\WorkDir\ocr\EasyOCR\langdata')#Windows

threshold=0.1#默认阈值
for i in range(1,len(sys.argv)):#获取命令行参数:argv[0]表示可执行文件本身
	imgfile=sys.argv[i]#待识别文件名
	imgfilext=os.path.splitext(imgfile)[-1]#文件后缀名
	if imgfilext.upper() not in ['.JPG','.JPEG','.PNG','.BMP']:#转换为大写后再比对
		print('\t', imgfile, ' 不是有效图片格式(jpg/jpeg/png/bmp)!')
		continue
	result = ocrreader.readtext(imgfile)
	paper=''
	for w in result:
		if w[2]>threshold:#设置一定的置信度阈值
			paper = paper+w[1]
	paper.replace(' ','').replace('_','').replace('^','').replace('~','').replace('`','').replace('&','')#删除无效数据

	#记录当前文件的识别结果,保存为同名的txt文件
	newfname=os.path.splitext(imgfile)[0]+'.txt'#与原文件同名的txt文件(包括目录)
	#newfname=os.path.splitext(imgfile)[0].split('/')[-1].split('\\')[-1]+'.txt'#与原文件同名的txt文件(不包括目录,仅文件名)
	try:
		with open(newfname, 'w') as txtfile:
			txtfile.write(paper)
	except(Exception) as e:
		print('\t', newfname, ' OCR Error: ', e)#输出异常错误
		continue

简单说明一下:

第1行的

#!/home/super/miniconda3/bin/python

不是注释,而是在Linux系统中起作用的命令行,有了这一句,在命令行中运行这个OCR时就可以省略掉python这个“单词”!假如把上述的python程序存储为img2txt.py文件,而待识别的图片为001.jpg和002.jpg,那么就可以在命令行中输入:

python ./img2txt.py 001.jpg 002.jpg

即可在同目录下得到001.txt和002.txt文件了。在第1句添加#!开头的那句话以后,在命令行中仅仅输入:

./img2txt.py 001.jpg 002.jpg

即可达到相同的效果!注意:img2txt.py文件前面表述路径的./不可省略,不然,系统会提示img2txt.py不是系统命令而出错。

当然,在利用conda产生多个虚拟python环境后,系统中可能存在多个python,甚至版本各不相同,这时就要输入正确的python解释器路径了,可以利用

whereis python

命令来查看所有的python解释器供参考!

第2行是编码声明,再后面就是导入包和导入语言包,语言包如果没有利用model_storage_directory选项显式的给出其路径,将会进行联网查询,由于我这里需要实现的是离线的OCR识别,所以需要事先将语言包下载下来,下载语言包还比较困难,我都在百度网盘链接中给出了,可供直接下载使用;这里我采用固定路径的方式,将语言包放在home根目录下的langdata文件夹下,拷贝时需要sudo权限,大家也可以放在其他路径下。

可以看见,目前这个版本十分的简单,也基本实现了所需的功能!但是,后面我还是进行了四五个版本的升级改进,下一个版本就是命令行中支持文件夹,当判断是文件夹后就对文件夹中的文件进行遍历,当是图像类型文件时就进行OCR识别,预知后事如何,且看下回分解!

你可能感兴趣的:(Python数据处理,python环境配置,python,自然语言处理)