使用Pytesseract进行光学字符识别
概述
本文,我们将使用计算机视觉技术从图像中提取文本。提取文本后,我们将在该文本上应用 OpenCV 的一些基本功能来增强它并获得更准确的结果。这个项目将非常有用,因为它可以节省从图像打字的时间和精力。
范围
· 对于将从图像中获取文本的大型组织而言,此应用程序可能会节省时间。
· 它可以打开“无纸化文档”的世界,这也有助于升级存储。
· 它还可以帮助自动化过程,因为它可以从图像本身中获取文本。
我们将导入requests库以获取 git 文件和图像的 URL 。
#import requests to install tesseract
import requests
注意:现在要下载 tesseract 文件,只需转到我将在函数中作为参数提供的链接,但我只是提供另一种下载 tesseract 文件的方法。
# Downloading tesseract-ocr file
r = requests.get("https://raw.githubusercontent.com/tesseract-ocr/tessdata/4.00/ind.traineddata", stream = True)
将数据写入文件以避免路径问题
with open("ind.traineddata", "wb") as file:
for block in r.iter_content(chunk_size = 1024):
if block:
file.write(block)
我们现在将下载Pytesseract 库运行所需的tesseract,并将文件保存在open() 函数的路径中。
!pip install pytesseract
如果你想将其安装在笔记本中,此命令将安装 Pytesseract 模块
Requirement already satisfied: pytesseract in c:programdataanaconda3libsite-packages (0.3.8)
Requirement already satisfied: Pillow in c:programdataanaconda3libsite-packages (from pytesseract) (8.0.1)
在这一步中,我们将安装 OCR 所需的库,我们还将导入 IPython 函数以清除不需要的函数。
安装光学字符识别所需的库
! apt install tesseract-ocr libtesseract-dev libmagickwand-dev
导入 IPython 以清除不重要的输出
from IPython.display import HTML, clear_output
clear_output()
现在,我们将安装Pytesseract 和 OpenCV库,它们是我们文本识别的灵魂
安装Pytesseract 和 OpenCV!
pip install pytesseract wand opencv-python
clear_output()
导入所需的库
# Import libraries
from PIL import Image
import pytesseract
import cv2
import numpy as np
from pytesseract import Output
import re
在这一步中,我们将打开一个图像调整其大小,然后再次保存以供进一步使用和可视化。
从URL读取图像
image = Image.open(requests.get('https://i.stack.imgur.com/pbIdS.png', stream=True).raw)
image = image.resize((300,150))
image.save('sample.png')
image
输出:
设置tesseract的路径
pytesseract.pytesseract.tesseract_cmd = r'C:Program FilesTesseract-OCRtesseract.exe'
注意:上面的命令将在系统配置中设置tesseract库的路径,如果路径没有根据系统配置设置,那么即使安装了tesseract也会抛出错误。
在这里,我们将使用自定义配置从图像中提取文本。
# Simply extracting text from image
custom_config = r'-l eng --oem 3 --psm 6'
text = pytesseract.image_to_string(image,config=custom_config)
print(text)
输出:
在自定义配置中,你可以看到**“eng”表示英语,即它会识别英文字母,你还可以添加多种语言,“PSM”表示页面分割**,它设置了块如何识别字符,“OEM”是默认配置。
现在,我们将通过用空字符串替换符号,从提取的文本中删除不需要的符号
# Extracting text from image and removing irrelevant symbols from characters
try:
text=pytesseract.image_to_string(image,lang="eng")
characters_to_remove = "!()@—*“>+-/,'|?#%$&^_~"
new_string = text
for character in characters_to_remove:
new_string = new_string.replace(character, "")
print(new_string)
except IOError as e:
输出:
在下面的单元格中,我们将图像读入OpenCV格式以进一步处理。当我们需要从复杂图像中提取文本时,这是必需的。
现在我们将执行OpenCV操作以从复杂图像中获取文本。
image = cv2.imread('sample.png') # will read in the array format
输出:
将图像转换为灰度图像,使其处理起来不那么复杂,因为它只有 0 和 1 两个值。这里我们使用cv2.cvtColor()方法将彩色图像转换为灰度格式,而cv2.cvtColor 实际上可以帮助图像的 150 色转换。
灰度图像
def get_grayscale(image):
return cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray = get_grayscale(image)
Image.fromarray(gray)
输出:
现在我们将模糊图像,以便我们可以从图像中去除噪声。在这里,我们使用函数cv2.medianBlur() 函数以减少图像中的噪声**,**模糊基本上是通过应用相关平滑滤波器来平滑图像的技术,是图像处理中广泛使用的方法之一。
降噪
def remove_noise(image):
return cv2.medianBlur(image,5)
noise = remove_noise(gray)
Image.fromarray(gray)
输出:
我们将在这里进行阈值变换。阈值适用于简单的概念,即当像素值低于给定的阈值时,颜色为白色,否则像素颜色正好相反,即黑色。使用的函数是cv2.threshold。
阈值
def thresholding(image):
# source image, grayscale image
return cv2.threshold(image, 0, 255, cv2.THRESH_BINARY +
cv2.THRESH_OTSU)[1]
thresh = thresholding(gray)
Image.fromarray(thresh)
输出:
这里我们正在做腐蚀变换。腐蚀变换是图像变换中最基本、最重要的步骤之一。腐蚀变换通常会拟合图像中缺失的形状和格子,这有助于在图像中稍微模糊或扭曲时识别字符。在这里,我们使用cv2 库中的erode()函数进行腐蚀转换。
腐蚀
def erode(image):
kernel = np.ones((5,5),np.uint8)
return cv2.erode(image, kernel, iterations = 1)
erode = erode(gray)
Image.fromarray(erode)
输出:
在这里,我们将执行形态变换。形态变换是最适合二值图像的技术之一,它根据图像的像素值对图像进行排序,而不是在考虑阈值的情况下对图像的数值进行排序。
形态变换
def opening(image):
kernel = np.ones((5,5),np.uint8)
return cv2.morphologyEx(image, cv2.MORPH_OPEN, kernel)
opening = opening(gray)
Image.fromarray(opening)
输出:
在这里,我们试图匹配图像。当我们传递相同的图像进行匹配时,我们得到了99.99%的相似度。这里,模板匹配是一种在较大的图像中搜索和查找模板图像的位置的方法。对于模板匹配,我们使用cv2 库中的 match template()函数。
模板匹配
def match_template(image, template):
return cv2.matchTemplate(image, template, cv2.TM_CCOEFF_NORMED)
match = match_template(gray, gray)
match
输出:
array([[1.]], dtype=float32)
现在我们将通过在文本周围创建一个矩形来分隔文本中的每个字符。
# Drawing rectangle around text
img = cv2.imread('sample.png')
h, w, c = img.shape
boxes = pytesseract.image_to_boxes(img)
for b in boxes.splitlines():
b = b.split(' ')
img = cv2.rectangle(img, (int(b[1]), h - int(b[2])), (int(b[3]), h - int(b[4])), (0, 255, 0), 2)
Image.fromarray(img)
输出:
最后,我们可以围绕特定的图案或单词绘制矩形。
# Drawing pattern on specific pattern or word
img = cv2.imread('sample.png')
d = pytesseract.image_to_data(img, output_type=Output.DICT)
keys = list(d.keys())
date_pattern = 'artificially'
n_boxes = len(d['text'])
for i in range(n_boxes):
if float(d['conf'][i]) > 60:
if re.match(date_pattern, d['text'][i]):
(x, y, w, h) = (d['left'][i], d['top'][i], d['width'][i], d['height'][i])
img = cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)
Image.fromarray(img)
输出:
结论
我们从学习如何安装用于文本提取的 tesseract 开始。接下来,我们拍摄了一张图像并从该图像中提取了文本。我们了解到我们需要使用 OpenCV 的某些图像转换函数来从复杂图像中提取文本。
尾注
希望你们会喜欢这个使用 Pytesseract逐步学习光学字符识别的方法。