本工具基于Github上的开源项目Textshot实现,Textshot中使用了tesseract作为OCR引擎,但是其对于中文的识别效果差强人意。因此,在本工具中,选用了cnocr引擎,对原工具中的tesseract引擎进行替换,达到了良好的中英文识别效果。
工具效果演示
Textshot
Testshot是Github上一款基于Python开发的截图工具,其优势如下:
- 项目简单
- 技术点丰富
其Github地址为Textshot,其详细介绍见100行Python代码实现一款高精度免费OCR工具。
cnocr
cnocr是用来做中文OCR的Python 3包。cnocr自带了训练好的识别模型,所以安装后即可直接使用。
目前使用的识别模型是crnn,识别准确度约为 98.7%。
其详细介绍见cnocr: 极简的中文OCR Python包。
项目准备
首先,从Github中下载Textshot,并参照上文中引用的教程安装所有Python依赖库;
其次,在Python中安装cnocr:
pip install cnocr
注意:请使用Python3以后版本
使用cnocr替换tesseract
完成上述准备工作后,接下来详细讲解如何在Textshot项目中,使用cnocr替换tesseract。
- 使用文本编辑器打开textshot-master文件夹中的textshot.py,找到第7行
import pytesseract
此处使用的是tesseract的python库,我们将其改为为cnocr
from cnocr import Cnocr
- 找到textshot.py第78行,processImage()函数
def processImage(img):
buffer = QtCore.QBuffer()
buffer.open(QtCore.QBuffer.ReadWrite)
img.save(buffer, "PNG")
pil_img = Image.open(io.BytesIO(buffer.data()))
buffer.close()
try:
result = pytesseract.image_to_string(
pil_img, timeout=5, lang=(sys.arvg[1] if len(sys.argv) > 1 else none)
).strip()
此处即为Textshot中进行OCR处理的核心代码,将从屏幕中截取的图片保存至pil_img中,然后调用image_to_string对pil_img进行文字识别,输出的结果为字符串,保存在result中。
对此段代码进行修改如下:
def processImage(img):
buffer = QtCore.QBuffer()
buffer.open(QtCore.QBuffer.ReadWrite)
img.save(buffer, "PNG")
pil_img = Image.open(io.BytesIO(buffer.data()))
img_name_str = 'test_img.png'
pil_img.save(img_name_str)
buffer.close()
try:
tmp_res = CnOcr().ocr(img_name_sr)
result = "".join(tmp_res[0][0])
上述代码中,我们使用了CnOcr().ocr来对图片中的文字进行识别,即
tmp_res = CnOcr().ocr(img_name_sr)
result = "".join(tmp_res[0][0])
CnOcr().ocr与image_to_string同样为OCR识别的处理函数,其功能都是对图片中的文字进行识别,但其输入和输出参数有所不同。在使用CnOcr().orc进行替换后,我们同样还要保证函数最终输出的参数与之前项目一致,从而确保后续代码对于识别结果处理的一致性。因此,采用了tmp_res来存储CnOcr().orc处理后的临时结果,再使用"".join(tmp_res[0][0])将其转换为字符串。
同样的,为了让输入参数能够适配CnOcr().ocr函数,代码中做了如下处理
img_name_str = 'test_img.png'
pil_img.save(img_name_str)
将截屏后的图片保存为’test_img.png’,作为CnOcr().ocr的入参。
- 最后,在testshot.py的第120行,找到如下代码
try:
pytesseract.get_tesseract_version()
except EnvironmentError:
notify(
"Tesseract is either not installed or cannot be reached.\n"
"Have you installed it and added the install directory to your system path?"
)
print(
"ERROR: Tesseract is either not installed or cannot be reached.\n"
"Have you installed it and added the install directory to your system path?"
)
sys.exit()
此段是对于Tesseract库是否进行了正确配置的检查,因为我们已经不再使用Tesseract,因此此段代码可以直接删除。感兴趣的朋友可以自己尝试将其替换为对cnocr的检查函数。
- 经过上述修改后,我们已经完成了在Textshot项目中,使用cnocr对tesseract进行换的工作,接下来可以直接执行程序,进行测试。在命令行中执行如下命令:
python .\textshot.py
使用鼠标在屏幕中选取需要识别的文字位置,即可对该区域的文字进行识别并自动复制到剪切板中。
在cnocr2.0.1版本中,程序执行时会提示warning:
[WARNING 2021-11-10 13:27:53,593 _showwarnmsg:109] C:\Program Files\Python38\lib\site-packages\cnocr\models\ocr_model.py:186: UserWarning: floordiv is deprecated, and its behavior will change in a future version of pytorch. It currently rounds toward 0 (like the ‘trunc’ function NOT ‘floor’). This results in incorrect rounding for negative values. To keep the current behavior, use torch.div(a, b, rounding_mode=‘trunc’), or for actual floor division, use torch.div(a, b, rounding_mode=‘floor’).
input_lengths = input_lengths // self.encoder.compress_ratio
其原因是在cnocr的源码中floordiv的使用可能无法达到预期结果,消除warning的方式如下:
打开\Python38\lib\site-packages\cnocr\models\ocr_model.py文件,找到第186行,将如下代码
input_lengths = input_lengths // self.encoder.compress_ratio
修改为
input_lengths = torch.div(input_lengths, self.encoder.compress_ratio, rounding_mode='trunc')
即可消除warning。
总结
本文通过使用cnocr,对开源项目Textshot的文字识别算法进行替换,提高了工具对于中文的识别效率,达到了良好的效果。
为了方便演示,本文只实现了对单行文字识别处理,实际上cnocr是可以对多行文字进行同时识别的,调用CnOcr().ocr返回的结果,实际上是一个多维的列表,本文中使用了tmp_res[0][0],感兴趣的朋友可以自行尝试完成多行文字的识别和输出。
本文使用的cnocr版本为2.0.1,在本文编写的过程中,cnocr已经发布了2.1.0版本,详见cnocr Release Notes,其安装需要依赖Microsoft Visual C++ 14.0,否则安装过程中会报错。如果您对新版本的功能没有需求,可以继续使用cnocr2.0.1完成本文所描述的修改,cnocr2.0.1版的安装方式为
pip install cnocr==2.0.1
如果您对于文中描述内容的有任何问题,欢迎留言讨论,感谢您的阅读。