如何基于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 相关文章推荐
python操作CouchDB的方法
Oct 08 Python
Python实现抓取城市的PM2.5浓度和排名
Mar 19 Python
Python+matplotlib实现计算两个信号的交叉谱密度实例
Jan 08 Python
python如何去除字符串中不想要的字符
Jul 05 Python
python用pandas数据加载、存储与文件格式的实例
Dec 07 Python
python代码实现逻辑回归logistic原理
Aug 07 Python
python文件绝对路径写法介绍(windows)
Dec 25 Python
python 的numpy库中的mean()函数用法介绍
Mar 03 Python
python实现Oracle查询分组的方法示例
Apr 30 Python
Python爬虫实例——爬取美团美食数据
Jul 15 Python
Python3爬虫关于识别检验滑动验证码的实例
Jul 30 Python
python实现登录与注册系统
Nov 30 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下载远程文件类(支持断点续传)
2008/11/14 PHP
php编程实现获取excel文档内容的代码实例
2011/06/28 PHP
基于php伪静态的实现详细介绍
2013/04/28 PHP
深入掌握include_once与require_once的区别
2013/06/17 PHP
thinkphp实现多语言功能(语言包)
2014/03/04 PHP
Yii调试SQL的常用方法
2014/07/09 PHP
服务器上配置PHP运行环境教程
2015/02/12 PHP
Yii2框架中日志的使用方法分析
2017/05/22 PHP
yii2.0整合阿里云oss删除单个文件的方法
2017/09/19 PHP
Laravel框架基础语法与知识点整理【模板变量、输出、include引入子视图等】
2019/12/03 PHP
Google Map Api和GOOGLE Search Api整合实现代码
2009/07/18 Javascript
JS实现选中当前菜单后高亮显示的导航条效果
2015/10/15 Javascript
详谈innerHTML innerText的使用和区别
2017/08/18 Javascript
vue中接口域名配置为全局变量的实现方法
2018/09/20 Javascript
vue组件从开发到发布的实现步骤
2018/11/11 Javascript
详解基于electron制作一个node压缩图片的桌面应用
2019/01/29 Javascript
微信小程序地图绘制线段并且测量(实例代码)
2020/01/02 Javascript
nuxt 自定义 auth 中间件实现令牌的持久化操作
2020/11/05 Javascript
pycharm中连接mysql数据库的步骤详解
2017/05/02 Python
Pandas之ReIndex重新索引的实现
2019/06/25 Python
pyqt5 键盘监听按下enter 就登陆的实例
2019/06/25 Python
用vue.js组件模拟v-model指令实例方法
2019/07/05 Python
Python列表(list)所有元素的同一操作解析
2019/08/01 Python
PyCharm 2019.3发布增加了新功能一览
2019/12/08 Python
用Python写一个for循环的例子
2016/07/19 面试题
技校毕业生自荐信
2014/06/03 职场文书
三分钟自我介绍演讲稿
2014/08/21 职场文书
卫校毕业生自我鉴定
2014/09/28 职场文书
工作态度不端正检讨书
2014/10/04 职场文书
2014年教师个人工作总结
2014/11/10 职场文书
感谢信格式范文
2015/01/22 职场文书
大学生求职意向书
2015/05/11 职场文书
幸福来敲门观后感
2015/06/04 职场文书
党务工作者主要事迹材料
2015/11/03 职场文书
MySQL学习总结-基础架构概述
2021/04/05 MySQL
MySQL 百万级数据的4种查询优化方式
2021/06/07 MySQL