使用深度学习的端到端文本OCR

2020-04-20 11:31:05 浏览数 (1)

来源 | Medium

编辑 | 代码医生团队

在当今这样的时代,任何组织或公司要扩大规模并保持相关性,都必须改变他们对技术的看法,并迅速适应不断变化的形势。已经知道Google如何将图书数字化。还是Google Earth如何使用NLP识别地址。或者如何读取发票,法律文书等数字文档中的文本。

但是它是如何工作的呢?

这篇文章是关于光学字符识别(OCR)的自然场景图像中的文本识别。将了解为什么这是一个棘手的问题,解决方法以及随之而来的代码。

可以在此处查看整个代码。

https://www.kaggle.com/mlwhiz/text-detection-v1

但是为什么真的呢?

在这个数字化时代,与花费数小时滚动浏览打印/手写/打字的文档相比,在数字文档中存储,编辑,索引和查找信息要容易得多。

此外,在大量的非数字文档中搜索内容不仅耗时;也有可能在手动滚动文本时错过信息。对我们来说幸运的是,计算机每天都在执行人们认为自己只能完成的任务时变得越来越好,而且性能通常也比我们更好。

从图像中提取文本已发现了许多应用。

其中一些应用程序是护照识别,自动车牌识别,将手写文本转换为数字文本,将键入的文本转换为数字文本等。

挑战性

在经历如何理解挑战之前,要面对OCR。

甚至在2012年深度学习蓬勃发展之前,就已经有许多OCR实现。尽管人们普遍认为OCR是一个已解决的问题,但OCR仍然是一个具有挑战性的问题,尤其是在不受限制的环境中拍摄文本图像时。

说的是复杂的背景,噪点,闪电,不同的字体以及图像中的几何变形。

在这种情况下,机器学习OCR工具会大放异彩。

OCR问题中的挑战主要是由于手头OCR任务的属性而引起的。通常可以将这些任务分为两类:

结构化文本-键入文档中的文本。在标准背景中,应使用适当的行,标准字体,并且大多数情况下是密集的。

非结构化文本-自然场景中随机位置的文本。文本稀疏,没有适当的行结构,复杂的背景,图像中的随机位置且没有标准字体。

许多早期的技术解决了结构化文本的OCR问题。

但是这些技术不适用于稀疏且具有与结构化数据不同的属性的自然场景。

在此博客中,将更多地关注非结构化文本,这是一个更复杂的问题。

在深度学习世界中,没有一种解决方案适用于所有人。将看到多种解决当前任务的方法,并将通过其中一种方法进行工作。

非结构化OCR任务的数据集

有许多可用的英语数据集,但是很难找到其他语言的数据集。不同的数据集表示要解决的不同任务。以下是一些常用于机器学习OCR问题的数据集示例。

SVHN数据集

http://www.iapr-tc11.org/mediawiki/index.php?title=The_Street_View_House_Numbers_(SVHN)_Dataset

街景门牌号码数据集包含用于训练的73257位数字,用于测试的26032位数字和531131作为额外的训练数据。数据集包含十个标签,它们是数字0–9。该数据集与MNIST不同,因为SVHN具有门牌号图像,且门牌号背景不同。数据集在每个数字周围都有边界框,而不是像MNIST中那样具有几个数字图像。

场景文本数据集

http://www.iapr-tc11.org/mediawiki/index.php?title=KAIST_Scene_Text_Database

该数据集包含3000种不同设置(室内和室外)和光照条件(阴影,光线和夜晚)的图像,并以韩文和英文文本显示。有些图像还包含数字。

Devanagri角色数据集

http://www.iapr-tc11.org/mediawiki/index.php?title=Devanagari_Character_Dataset

该数据集提供了来自36个字符类的1800个样本,这些样本由25个不同的本机作者在Devanagari脚本中获得。

还有很多这样的汉字,这个验证码或手写单词。

在野外阅读文本

任何典型的机器学习OCR管道都遵循以下步骤:

前处理

  • 消除图像中的噪点
  • 从图像中删除复杂的背景
  • 处理图像中的不同闪电条件

这些是在计算机视觉任务中预处理图像的标准方法。在本博客中,将不再关注预处理步骤。

文字检测

需要文本检测技术来检测图像中的文本,并在具有文本的图像部分周围创建边框。标准异物检测技术也可以在这里使用。

推拉窗技术

可以通过滑动窗口技术在文本周围创建边框。但是,这是一个计算量很大的任务。在这种技术中,滑动窗口穿过图像以检测该窗口中的文本,就像卷积神经网络一样。尝试使用不同的窗口大小,以免丢失具有不同大小的文本部分。滑动窗口有卷积实现,可以减少计算时间。

单发和基于区域的检测器

有单次检测技术,例如YOLO(您只看一次),以及基于区域的文本检测技术,用于图像中的文本检测。

YOLO是单发技术,与滑动窗口不同,仅传递图像一次即可检测该区域中的文本。

基于区域的方法分两个步骤进行。

首先,网络提出可能要进行测试的区域,然后对是否具有文本的区域进行分类。在我们的案例中是文本检测。

EAST(高效准确的场景文本检测器)

这是一种基于本文的非常健壮的深度学习文本检测方法。值得一提的是,它只是一种文本检测方法。它可以找到水平和旋转边界框。它可以与任何文本识别方法结合使用。

本文中的文本检测管道排除了冗余和中间步骤,只有两个阶段。

人们利用全卷积网络直接产生单词或文本行级别的预测。通过非最大抑制步骤进一步处理可能旋转的矩形或四边形的生成的预测,以产生最终输出。

EAST可以检测图像和视频中的文本。如本文所述,它在720p图像上以13FPS实时运行,具有很高的文本检测精度。此技术的另一个好处是,它的实现在OpenCV 3.4.2和OpenCV 4中可用。将看到这种EAST模型以及文本识别的实际应用。

文字识别

一旦检测到包含文本的边界框,下一步就是识别文本。有几种识别文本的技术。在下一节中,将讨论一些最佳方法。

神经网络

卷积递归神经网络(CRNN)是CNN,RNN和CTC(连接器时间分类)损失的组合,用于基于图像的序列识别任务,例如场景文本识别和OCR。网络架构摘自2015年发表的这篇论文。

这种神经网络架构将特征提取,序列建模和转录集成到一个统一的框架中。此模型不需要字符分割。卷积神经网络从输入图像(文本检测区域)中提取特征。深度双向递归神经网络通过字符之间的某种关系来预测标签序列。转录层将RNN生成的每帧转换为标记序列。有两种转录模式,即无词典和基于词典的转录。在基于词典的方法中,将预测最高可能的标记序列。

使用Tesseract的机器学习OCR

Tesseract最初是在1985年至1994年之间由惠普实验室开发的。2005年,它由HP开源。

在2006年,Tesseract被认为是当时最精确的开源OCR引擎之一。

Tesseract的功能主要限于结构化文本数据。它在带有明显噪音的非结构化文本中的效果会很差。自2006年以来,Google一直赞助Tesseract的进一步开发。

基于深度学习的方法对于非结构化数据表现更好。Tesseract 4在基于LSTM网络(一种递归神经网络)的OCR引擎中添加了基于深度学习的功能,该引擎专注于行识别,但也支持Tesseract 3的传统Tesseract OCR引擎,该引擎通过识别字符模式进行工作。最新的稳定版本4.1.0已于2019年7月7日发布。此版本在非结构化文本上也更加准确。

将使用其中的一些图像来显示使用EAST方法进行文本检测和使用Tesseract 4进行文本识别。下面的代码来看一下实际的文本检测和识别。本文在这里被证明是编写代码为这个项目有用的资源。

代码语言:javascript复制
##Loading the necessary packages  
import numpy as np
import cv2
from imutils.object_detection import non_max_suppression
import pytesseract
from matplotlib import pyplot as plt
#Creating argument dictionary for the default arguments needed in the code.
args = {"image":"../input/text-detection/example-images/Example-images/ex24.jpg", "east":"../input/text-detection/east_text_detection.pb", "min_confidence":0.5, "width":320, "height":320}

在这里,正在处理基本软件包。OpenCV软件包使用EAST模型进行文本检测。tesseract软件包用于识别在为文本检测到的边界框中的文本。

确保tesseract版本> =4。在线上有多个资源可指导Tesseract的安装。

为代码中所需的默认参数创建了一个字典。看看这些论点的含义。

  • 图像:用于文本检测和识别的输入图像的位置。
  • EAST:具有预先训练的EAST检测器模型的文件的位置。
  • 最小置信度:在该位置预测的几何形状的置信度的最小概率分数。
  • width:图像宽度应为32的倍数,以使EAST模型正常工作。
  • height:图像高度应为32的倍数,以使EAST模型正常工作。

图像处理

代码语言:javascript复制
#Give location of the image to be read.
#"Example-images/ex24.jpg" image is being loaded here.
args['image']="../input/text-detection/example-images/Example-images/ex24.jpg"
image = cv2.imread(args['image'])
#Saving a original image and shape
orig = image.copy()
(origH, origW) = image.shape[:2]
# set the new height and width to default 320 by using args #dictionary.  
(newW, newH) = (args["width"], args["height"])
#Calculate the ratio between original and new image for both height and weight.
#This ratio will be used to translate bounding box location on the original image.
rW = origW / float(newW)
rH = origH / float(newH)
# resize the original image to new dimensions
image = cv2.resize(image, (newW, newH))
(H, W) = image.shape[:2]
# construct a blob from the image to forward pass it to EAST model
blob = cv2.dnn.blobFromImage(image, 1.0, (W, H),
(123.68, 116.78, 103.94), swapRB=True, crop=False)

加载预训练的EAST模型并定义输出层

代码语言:javascript复制
# load the pre-trained EAST model for text detection
net = cv2.dnn.readNet(args["east"])
# We would like to get two outputs from the EAST model.
#1. Probabilty scores for the region whether that contains text or not.
#2. Geometry of the text -- Coordinates of the bounding box detecting a text
# The following two layer need to pulled from EAST model for achieving this.
layerNames = [
"feature_fusion/Conv_7/Sigmoid",
"feature_fusion/concat_3"]

通过EAST模型向前传递图像

代码语言:javascript复制
#Forward pass the blob from the image to get the desired output layers
net.setInput(blob)
(scores, geometry) = net.forward(layerNames)

从EAST模型预测中解码边界框的功能

代码语言:javascript复制
# Find predictions and  apply non-maxima suppression
(boxes, confidence_val) = predictions(scores, geometry)
boxes = non_max_suppression(np.array(boxes), probs=confidence_val)

在本练习中,仅解码水平边界框。从分数和几何图形解码旋转边界框更为复杂。

非最大抑制后获取最终边界框

代码语言:javascript复制
# Find predictions and  apply non-maxima suppression
(boxes, confidence_val) = predictions(scores, geometry)
boxes = non_max_suppression(np.array(boxes), probs=confidence_val)

现在在应用non-max-suppression后得出了边界框。希望看到图像上的边界框,以及如何从检测到的边界框提取文本。使用Tesseract进行此操作。

生成具有边界框坐标和框中可识别文本的列表

代码语言:javascript复制
# initialize the list of results
results = []
# loop over the bounding boxes to find the coordinate of bounding boxes
for (startX, startY, endX, endY) in boxes:
# scale the coordinates based on the respective ratios in order to reflect bounding box on the original image
startX = int(startX * rW)
startY = int(startY * rH)
endX = int(endX * rW)
endY = int(endY * rH)
#extract the region of interest
r = orig[startY:endY, startX:endX]
#configuration setting to convert image to string.  
configuration = ("-l eng --oem 1 --psm 8")
    ##This will recognize the text from the image of bounding box
text = pytesseract.image_to_string(r, config=configuration)
# append bbox coordinate and associated text to the list of results
results.append(((startX, startY, endX, endY), text))

代码的上述部分已将边界框坐标和关联的文本存储在列表中。将看到它在图像上的外观。

在案例中,使用了Tesseract的特定配置。tesseract配置有多个选项。

  • 语言,在上述代码中选择英语。
  • oem(OCR引擎模式):

0仅旧式引擎。

1仅神经网络LSTM引擎。

2个旧版 LSTM引擎。

3默认,基于可用选项。

  • psm(页面分割模式):

0仅方向和脚本检测(OSD)。

1使用OSD自动进行页面分割。

2自动页面分割,但没有OSD或OCR。(未实现)

3全自动页面分割,但没有OSD。(默认)

4假设一列可变大小的文本。

5假定单个统一的垂直对齐文本块。

6假设一个统一的文本块。

7将图像视为单个文本行。

8将图像视为一个单词。

9将图像视为一个圆圈中的单个单词。

10将图像视为一个字符。

11稀疏文本。以无特定顺序查找尽可能多的文本。

12带有OSD的稀疏文本。

13原始行。将图像视为单个文本行,绕过特定于Tesseract的黑客。

可以根据图像数据选择特定的Tesseract配置。

代码语言:javascript复制
#Display the image with bounding box and recognized text
orig_image = orig.copy()
# Moving over the results and display on the image
for ((start_X, start_Y, end_X, end_Y), text) in results:
# display the text detected by Tesseract
print("{}n".format(text))
# Displaying text
text = "".join([x if ord(x) < 128 else "" for x in text]).strip()
cv2.rectangle(orig_image, (start_X, start_Y), (end_X, end_Y),
(0, 0, 255), 2)
cv2.putText(orig_image, text, (start_X, start_Y - 30),
cv2.FONT_HERSHEY_SIMPLEX, 0.7,(0,0, 255), 2)
plt.imshow(orig_image)
plt.title('Output')
plt.show()

结果

上面的代码使用OpenCV EAST模型进行文本检测,并使用Tesseract进行文本识别。已根据图像设置了Tesseract的PSM。重要的是要注意,Tesseract需要清晰的图像,通常情况下才能正常工作。

在当前的实现中,由于实现的复杂性,没有考虑旋转边界框。但是在旋转文本的实际情况下,上面的代码将无法正常工作。此外只要图像不是很清晰,Tesseract就会难以正确识别文本。

通过上面的代码生成的一些输出是:

该代码可以为上述所有三个图像提供出色的结果。这些图像中的文字清晰,并且文字的背景也很均匀。

该模型在这里表现很好。但是某些字母不能正确识别。会看到边界框应该是正确的。稍微旋转可能会有所帮助。但是当前的实现不提供旋转边界框。似乎是由于图像清晰度。Tesseract无法完全识别它。

该模型在这里的表现相当不错。但是边界框中的某些文本无法正确识别。根本无法检测到数字。这里存在不均匀的背景,也许生成统一的背景将有助于解决这种情况。另外,盒子中的24边界不正确。在这种情况下,对边界框进行填充可能会有所帮助。

在上述情况下,背景中带有阴影的风格化字体似乎已经影响了结果。

不能指望OCR模型是100%准确的。尽管如此,使用EAST模型和Tesseract仍取得了良好的结果。添加更多用于处理图像的滤镜可能有助于改善模型的性能。

还可以在Kaggle内核上找到此项目的代码,以自己尝试。

https://www.kaggle.com/mlwhiz/text-detection-v1

0 人点赞