如何基于Python代码实现高精度免费OCR工具


Posted in Python onJune 18, 2020

近期Github开源了一款基于Python开发、名为Textshot的截图工具,刚开源不到半个月已经500+Star。

这两天抽空看了一下Textshot的源码,的确是一个值得介绍的项目。

相对于大多数OCR工具复杂工程、差强人意的效果,Textshot具有明显的优势,

  • 项目简单
  • 技术点丰富

项目简单

Textshot整个项目只有1个Python文件、139行代码,没有复杂的第三方库应用,也不涉及过多后端算法的调用。

技术点丰富

Textshot这个项目虽然只有短短的139行代码,但是,却涉及Python中多个方面的知识应用,

  • UI开发
  • 截图工具开发
  • 后端引擎调用

通过这短短的项目,你不仅可以了解如何利用PyQt5实现一个用户界面,还可以学会如何使用pyscreenshot开发一款自己的截图工具。此外,还能够学会后端tesseract的调用。

换句话说,这短短的139行代码囊括了前端至后端的整个流程,而且涉及到截图和OCR两款工具的衔接。因此,Textshot虽然工程不大,却是一个非常完备、值得学习的项目。

本文就来剖析这个项目的源代码,教你一步一步实现自用且永久免费的截图&OCR工具!

tesseract

目前OCR工具数不胜数,但是大多数都是在相同的后端算法上面进行了不同的封装而已。而真正在OCR核心做的较好、值得大书特书的,那么一定非tesseract莫属

tesseract早在1985就已经开始由HP实验室开始研发,而在1995年更是被评为最为准确的3款OCR工具之一。此后,tesseract被开源,经过Google对其不断的进行优化和升级,它目前已经成为OCR方面一款标杆性的工具。很多开源或者付费的OCR工具,都是直接调用tesseract或者对其进行稍许优化。

而今天介绍的Textshot就是直接调用tesseract后端引擎进行OCR识别。因此,Textshot只是实现了一款截图工具,起到前后端的串联作用,在OCR识别算法方面并没有做任何工作。

tesseract安装

由于Textshot的OCR识别需要调用tesseract后端引擎,所以,首先需要安装tesseract。

Windows版安装可以直接访问下载链接[1].

Mac下可以使用Homebrew进行安装,

brew install tesseract 

Textshot

Textshot是一款截图识别文字的OCR工具,因此,它主要涉及2个环境,

截图

OCR识别

Textshot首先通过截图获取需要进行文字识别的图像,然后对这副图像进行OCR文字识别,输出识别结果。

前面已经介绍了,Textshot的OCR识别阶段调用的是tesseract,所以只需要1行代码即可完成。

因此,Textshot的工作主要是围绕前端窗口和截图工具的实现方面。

截图工具

截图工具是我们经常会用到的一种工具,如何实现一款截图工具?

很多人会把它想的非常复杂,其实,Python中有很多可以实现截图的库或者函数,例如,pyscreenshot或者pillow中的ImageGrab函数,它的调用方式如下,

shot = ImageGrab.grab(bbox=(x1, y1, x2, y2))

也就是说,我们只需要把鼠标框选的起点和终点坐标传给grab方法就可以实现截图功能。

那么,现在问题就转化为如何获取鼠标框选的起点和终点?

Textshot通过调用PyQt5并继承QWidget来实现鼠标框选过程中的一些方法来获取框选的起点和终点。

Textshot继承和重写QWidget方法主要包括如下几个,

  • keyPressEvent(self, event):键盘响应函数
  • paintEvent(self, event):UI绘制函数
  • mousePressEvent(self, event):鼠标点击事件
  • mouseMoveEvent(self, event):鼠标移动事件
  • mouseReleaseEvent(self, event):鼠标释放事件

可以看出,上面重写的方法以及囊括了截图过程中涉及的各个动作,

  • 点击鼠标
  • 拖动、绘制截图框
  • 释放鼠标
class Snipper(QtWidgets.QWidget):
  def __init__(self, parent=None, flags=Qt.WindowFlags()):
    super().__init__(parent=parent, flags=flags)
 
    self.setWindowTitle("TextShot")
    self.setWindowFlags(
      Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint | Qt.Dialog
    )
 
    self.is_macos = sys.platform.startswith("darwin")
    if self.is_macos:
      self.setWindowState(self.windowState() | Qt.WindowMaximized)
    else:
      self.setWindowState(self.windowState() | Qt.WindowFullScreen)
 
    self.setStyleSheet("background-color: black")
    self.setWindowOpacity(0.5)
 
    QtWidgets.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.CrossCursor))
 
    self.start, self.end = QtCore.QPoint(), QtCore.QPoint()
 
  def keyPressEvent(self, event):
    if event.key() == Qt.Key_Escape:
      QtWidgets.QApplication.quit()
 
    return super().keyPressEvent(event)
 
  def paintEvent(self, event):
    if self.start == self.end:
      return super().paintEvent(event)
 
    painter = QtGui.QPainter(self)
    painter.setPen(QtGui.QPen(QtGui.QColor(255, 255, 255), 3))
    painter.setBrush(QtGui.QColor(255, 255, 255, 100))
 
    if self.is_macos:
      start, end = (self.mapFromGlobal(self.start), self.mapFromGlobal(self.end))
    else:
      start, end = self.start, self.end
 
    painter.drawRect(QtCore.QRect(start, end))
    return super().paintEvent(event)
 
  def mousePressEvent(self, event):
    self.start = self.end = QtGui.QCursor.pos()
    self.update()
    return super().mousePressEvent(event)
 
  def mouseMoveEvent(self, event):
    self.end = QtGui.QCursor.pos()
    self.update()
    return super().mousePressEvent(event)
 
  def mouseReleaseEvent(self, event):
    if self.start == self.end:
      return super().mouseReleaseEvent(event)
 
    x1, x2 = sorted((self.start.x(), self.end.x()))
    y1, y2 = sorted((self.start.y(), self.end.y()))

然后启动截图界面,

QtCore.QCoreApplication.setAttribute(Qt.AA_DisableHighDpiScaling)
app = QtWidgets.QApplication(sys.argv)
window = QtWidgets.QMainWindow()
snipper = Snipper(window)
snipper.show()

用户拖动、框选窗口,会获取窗口的起点和终点的坐标,这时候可以调用下面语句进行截图,获取需要OCR识别的文本图像,

shot = ImageGrab.grab(bbox=(x1, y1, x2, y2))

OCR文字识别

通过ImageGrab.grab截取到文本图像shot,下一步就是要把图像内容输入给后端的tesseract引擎,让它把图像转化为字符串

result = pytesseract.image_to_string(img, timeout=2, lang=(sys.argv[1] if len(sys.argv) > 1 else None))

到这里,就实现了一款准确度高、永久免费的OCR工具。

回顾一下Textshot的项目,我们会发现截图坐标范围内的图像、OCR识别只需要2行代码,大多数都是在围绕获取窗口起点和终点坐标在开发。换句话说,Textshot这个项目对OCR核心部分并没有做任何更改,只是在产品包装方面做了一些巧妙的工作。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
django接入新浪微博OAuth的方法
Jun 29 Python
Python使用Tkinter实现机器人走迷宫
Jan 22 Python
Python cookbook(数据结构与算法)在字典中将键映射到多个值上的方法
Feb 18 Python
对python3中, print横向输出的方法详解
Jan 28 Python
python rsync服务器之间文件夹同步脚本
Aug 29 Python
Python list与NumPy array 区分详解
Nov 06 Python
Python多线程模块Threading用法示例小结
Nov 09 Python
关于numpy数组轴的使用详解
Dec 05 Python
python 已知平行四边形三个点,求第四个点的案例
Apr 12 Python
Python中如何添加自定义模块
Jun 09 Python
Jupyter notebook 更改文件打开的默认路径操作
May 21 Python
Python 数据可视化之Bokeh详解
Nov 02 Python
python软件都是免费的吗
Jun 18 #Python
python中return如何写
Jun 18 #Python
python对一个数向上取整的实例方法
Jun 18 #Python
Python基于time模块表示时间常用方法
Jun 18 #Python
numpy 矩阵形状调整:拉伸、变成一位数组的实例
Jun 18 #Python
Numpy 多维数据数组的实现
Jun 18 #Python
python读取图像矩阵文件并转换为向量实例
Jun 18 #Python
You might like
PHP的cURL库功能简介 抓取网页、POST数据及其他
2011/04/07 PHP
PHP图像识别技术原理与实现
2016/10/27 PHP
在服务端(Page.Write)调用自定义的JS方法详解
2013/08/09 Javascript
细说javascript函数从函数的构成开始
2013/08/29 Javascript
对JavaScript的全文搜索实现相关度评分的功能的方法
2015/06/24 Javascript
javascript实现控制的多级下拉菜单
2015/07/05 Javascript
Javascript函数的参数
2015/07/16 Javascript
Bootstrap开关(switch)控件学习笔记分享
2016/05/30 Javascript
JavaScript学习笔记整理_关于表达式和语句
2016/09/19 Javascript
AngularJS基于provider实现全局变量的读取和赋值方法
2017/06/28 Javascript
JS自定义滚动条效果简单实现代码
2020/10/27 Javascript
jquery获取transform里的值实现方法
2017/12/12 jQuery
nodejs 日志模块winston的使用方法
2018/05/02 NodeJs
vue实现新闻展示页的步骤详解
2019/04/11 Javascript
详解vue 2.6 中 slot 的新用法
2019/07/09 Javascript
JavaScript实现移动端带transition动画的轮播效果
2020/03/24 Javascript
[02:00]DOTA2英雄COSPLAY闹市街头巡游助威2015国际邀请赛
2015/08/02 DOTA
[58:29]DOTA2-DPC中国联赛 正赛 Phoenix vs XG BO3 第一场 1月31日
2021/03/11 DOTA
python的三目运算符和not in运算符使用示例
2014/03/03 Python
django 在原有表格添加或删除字段的实例
2018/05/27 Python
浅谈python实现Google翻译PDF,解决换行的问题
2018/11/28 Python
selenium使用chrome浏览器测试(附chromedriver与chrome的对应关系表)
2018/11/29 Python
Python机器学习之scikit-learn库中KNN算法的封装与使用方法
2018/12/14 Python
Python爬取知乎图片代码实现解析
2019/09/17 Python
python使用pip安装模块出现ReadTimeoutError: HTTPSConnectionPool的解决方法
2019/10/04 Python
使用Matplotlib 绘制精美的数学图形例子
2019/12/13 Python
Python3监控windows,linux系统的CPU、硬盘、内存使用率和各个端口的开启情况详细代码实例
2020/03/18 Python
Java中的类包括什么内容?设计时要注意哪些方面
2012/05/23 面试题
税务干部鉴定材料
2014/02/11 职场文书
应届毕业生如何写求职信
2014/02/16 职场文书
供电工程专业求职信
2014/08/09 职场文书
实名检举信范文
2015/03/02 职场文书
庆七一主持词
2015/06/29 职场文书
2015年工会工作总结范文
2015/07/23 职场文书
班组长如何制订适合本班组的工作计划?
2019/07/10 职场文书
写作技巧:如何撰写商业计划书
2019/08/08 职场文书