先上一个表,分享一下我最近接触到的三个OCR引擎,其实各有各的特点,说不上最好和最坏,按需使用。
识别引擎 | python库 | 识别准确度 | 识别速度 | 特点 |
---|---|---|---|---|
tesseract | pytesseract | 较差 | 最慢 | 可二次训练,可调整识别速度,可识别复杂布局 |
paddleOCR | ppstructure | 较好 | 最快 | 表格识别准确 |
CnOCR | Pix2Text | 一般 | 一般 | 中文识别率不错,能识别公式转化为Latex |
这里需要强调一个问题,识别准确度是针对手写体、内容残缺或者噪声较多的图片,如果是清晰度高的纯文本图片,这几个引擎实测识别率都在99%以上,非常准确。至于识别速度的问题,最慢的tesseract在识别一篇20页的论文PDF(识别结果一千多行)的时候,也大概只用了2-3分钟,这个按照项目需求选用吧。
如果只有少量的图片,那就可以直接对图片下手,然后随便使用一个OCR工具即可
免费的图片分割网站:Split PDF pages in the middle using DeftPDF online for free
如果能够确定批量图片的布局情况,比如确定图片都是双栏的布局,也可以使用一个分割脚本。就是获取图片的宽高,然后将图片拆分为高度不变,宽度为原图的一半就行(如果不是均分的两栏就按照实际比例分割)这个实现代码到处都是,就不占用篇幅赘述了。
最近做了一个需求,要求用户上传论文的PDF,然后就能通过OCR获取其中的信息,关键是要做成一个web的功能,面向一般的用户,再加上论文的布局是复杂多样的,没法预设。
可是如果把双列内容不做任何处理去识别,结果往往是将左边一列的第一行和右边一列的第一行视作同一行,可真正的阅读顺序应该是将左边一列读完再读右边一列的第一行。
后来寻思让用户指出哪几页是双栏,哪几页是单栏,这样不但麻烦,而且有的页面同时有单栏和双栏(图片表格单栏,正文双栏),用户体验肯定不好,最后发现pytesseract是可以处理内容的位置信息,识别布局情况,并且可以按照正常的阅读习惯将识别的内容拼接,于是问题迎刃而解。
废话不多说,上代码,记得提前安装tesseract引擎,并下载需要的训练库。
import pytesseract
from PIL import Image
import os
import fitz
# 设置TESSDATA_PREFIX环境变量,这是你自己的训练库所在位置,训练库去官网下载
# os.environ['TESSDATA_PREFIX'] = r'D:\Program Files\Tesseract-OCR\tessdata'
# 设置Tesseract OCR引擎的路径,下载的引擎路径
pytesseract.pytesseract.tesseract_cmd = r'D:\Program Files\Tesseract-OCR\tesseract.exe'
def recognize_text_from_pdf(pdf_path, output_path, language='eng+chi_sim'):
# 打开PDF文件
pdf_document = fitz.open(pdf_path)
all_text = ""
# 将PDF的每一页转化为图片,再识别内容
for pg in range(pdf_document.page_count):
page = pdf_document[pg]
rotate = int(0)
# 清晰度在这改(设为1.33333333是1056x816像素;设为2是>1584x1224像素)
zoom_x = 2
zoom_y = 2
mat = fitz.Matrix(zoom_x, zoom_y).prerotate(rotate)
pix = page.get_pixmap(matrix=mat, alpha=False)
image = Image.frombytes("RGB", [pix.width, pix.height], pix.samples)
# 使用Tesseract OCR引擎识别图片中的文本
text = pytesseract.image_to_string(image, lang=language)
all_text += text + "\n\n"
# 关闭PDF文件
pdf_document.close()
with open(output_path+'/'+'pdf1output.txt', 'w', encoding='utf-8') as file:
file.write(all_text)
# PDF路径和输出路径
pdf_path = './data/chinese.pdf'
output_folder = './output'
recognize_text_from_pdf(pdf_path, output_folder)
测试下方这张从论文中拆分出来的图片,其中图表都是单栏,正文是双栏。识别结果完全符合读者的阅读顺序(只是图表内容可能会错位,这个方面tesseract确实不太行)
这个故事告诉我们要多尝试不同的库和引擎,尤其是需求比较偏门或者少见的时候。同一个方向不同的库所擅长的领域是不一样的。
更多OCR方面的小技巧和经验贴:各种常用OCR,分享特殊情况下的OCR解决方案
博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~