《深入浅出OCR》第二章:OCR技术发展与分类

⚠️本文为稀土掘金技术社区首发签约文章,30天内禁止转载,30天后未获授权禁止转载,侵权必究!

image.png

专栏介绍: 经过几个月的精心筹备,本作者推出全新系列《深入浅出OCR》专栏,对标最全OCR教程,具体章节如导图所示,将分别从OCR技术发展、方向、概念、算法、论文、数据集等各种角度展开详细介绍。

?个人主页: GoAI |? 公众号: GoAI的学习小屋 | ?交流群: 704932595 |?个人简介 : 掘金签约作者、百度飞桨PPDE、领航团团长、开源特训营导师、CSDN、阿里云社区人工智能领域博客专家、新星计划计算机视觉方向导师等,专注大数据与人工智能知识分享。

?文章目录

《深入浅出OCR》前言知识(二):深度学习基础总结 (✨文末有深度学习总结导图福利!)

《深入浅出OCR》前言知识(一):机器学习基础总结 (✨文末有机器学习总结导图福利!)

《深入浅出OCR》第一章:OCR技术导论

《深入浅出OCR》第二章:OCR技术发展与分类 (本篇)


?‍?本篇导读: 本篇为《深入浅出OCR》第二章:OCR技术发展与分类。本篇主要介绍传统OCR和深度学习OCR方法,从图像处理特征提取、文字检测与识别等角度展开详细介绍,配合作者总结思维导图,尽可能总结OCR全面知识。

《深入浅出OCR》第二章:OCR技术发展与分类

OCR技术发展总览

通常来说,OCR技术可以分为传统方法和深度学习方法。 传统方法受限于手工设计特征的表达能力和处理流程的复杂性,在复杂场景下很难达到理想的文字识别效果,而基于深度学习OCR利用CNN模型算法替换传统的手动方法,自动检测出文本的类别及位置信息,根据相应位置文本信息自动识别文本内容,识别效果更为优秀。

接下来,作者按时间顺序总结了OCR发展流程,具体如下图:

ocr技术.png

  • 在70年代至15年前,传统OCR技术一般采用连通域分析等方法寻找潜在文字切分位置,通过一定方法以过分割方式对文字进行切分,然后进行单字识别。

  • 直到16年,深度学习OCR技术取得重大突破,白翔等人提出CRNN网络识别方法,以序列方式进行识别,通过采用无需分割方法避免分割错误,成为主流OCR文字识别方法。

一、传统OCR

传统OCR文字识别算法主要基于图像处理技术(如投影、膨胀、旋转等)和相关统计机器学习实现图片文本内容提取,其主要应用于背景颜色单一、分辨率高的简单文档图像识别。

1.1 技术流程:

传统OCR文字识别是将文本行的字符识别看成一个多标签任务学习的过程。其识别过程为图像预处理(彩色图像灰度化、二值化处理、图像 变化角度检测、矫正处理等)、版面划分(直线检测、倾斜检测)、字符定位切分、字符 识别、版面恢复、后处理、校对等。

在这里插入图片描述

文本检测和识别是OCR技术的两个重要核心技术,传统的OCR方法通过针对文本检测和识别分别设计鲁棒的特征,来提高模型的文字识别效果。

image.png

文本检测:主要用于定位图片中文本的区域,传统的文本检测方法可以分为基于显著特征的检测方法和基于滑动窗口的检测方法两大类。

文本识别阶段:可划分为文本二值化、文本行分段、字符分割、单字识别、字符矫正等一系列子问题。然而,传统的文本检测与识别方法受限于手工设计特征的表达能力和处理流程的复杂性,对于较为复杂的图片情况,例如带有大角度畸变以及模糊不清的文本图像,很难达到理想的文字识别效果,受限于手工设计特征。

1.3 传统机器学习OCR方法

传统文字识别一般首先需要文本区域定位,将定位后的倾斜文本进行矫正再分割出单个文字,然后在特征提取阶段使用人工特征或CNN特征进行,再结合分类模型 对单字进行识别,最后基于统计语言模型(如隐马尔科夫链,HMM)或者规则进行语义纠错,即语言规则后处理。

接下来,本人将着重从特征提取角度和分类模型出发,介绍传统OCR文字识别技术,让大家快速了解OCR技术的发展。

1.3.1 特征提取方法

(1)基于结构形态的特征提取:

基于结构形态的特征提取主要通过查找轮廓特征和区域特征进行操作。

1.边界特征法

基于结构形态的特征提取是计算机视觉领域中的一种方法,它主要用于从图像或其他类型的数据中提取形态学结构和模式。结构形态学是一种数学理论,用于描述和分析图像中的形状和结构,包括各类算子(Canny、HOG、Sober、SIFI)等。

  1. 傅里叶特征算子法

(2)基于几何分布的特征提取:

基于几何分布的特征提取是一种计算机视觉领域中常用的特征提取方法,它主要用于从图像或其他类型的数据中捕捉几何结构和形状的信息。该方法基于几何学原理,通过分析图像中的点、线、面等几何形态,从中提取有意义的特征。

1、二维直方图投影法

在计算机视觉领域,Opencv中常用垂直投影和水平投影可以对目标物进行精确投影,以便于后期的分割。其中,水平投影是二维图像(二值图)在y轴上的投影;垂直投影是二维图像(二值图)在x轴上的投影。

2. 区域网格投影法

上述特征提取在许多计算机视觉任务中都有广泛的应用,例如目标检测、图像匹配、形状识别等。然而对于复杂的场景和特征,单独使用基于几何或基于结构形态的特征提取可能不足以满足需求,通常需要与其他特征提取方法结合使用,以获得更全面和准确的信息。

3.模板匹配

模板匹配法是通过计算目标图像与搜索图中所有子图的相似度,其中相似度最大的即认为是最佳待匹配的位置。模板匹配法根据匹配的基本原理演变出多种匹配计算方式,如序贯相似性匹配、距离变换、最小均方误差等。

OCR技术中使用模板匹配法时首先要建立标准的模板字符库,接着将待识别字符图像与模板字符库中字符进行匹配相似度计算,得到匹配相似度值最大的就是相对应的字符识别结果。模板匹配的优点在于识别过程直接采取两幅图像间的相似匹配度,在某些特定场景有着很高的实用性。

1.3.2 传统分类方法

在字符特征提取后,需要对字符进行识别,传统机器学习将OCR识别转换为一个分类任务。 作者这里总结具体方法及其优缺点,主要包括以下几类:

(1)支持向量机

支持向量机(Support Vector Machine,SVM)是基于统计学理论的一种分类识别算法。支持向量机分类算法不仅对于小样本的情况具有较好的分类效果,并且对高维和线性不可分的问题进行了很好的解决,这是该算法的主要优。

缺点:例如核函数的选择,以及算法的实时性较差等问题。

(2)贝叶斯分类算法

贝叶斯分类算法(Bayes)主要原理是通过Bayes定理对未知样本进行预测,并计算样本进行各个类别的可能性,最后通过概率统计对图像实现分类。

优点:贝叶斯分类方法的主要优点在于鲁棒性强,稳定性好;

缺点:模型基础假设不同属性间的概率独立,即相互不影响。因此要考虑应用场景。

(3)K近邻算法

K近邻算法是一种分类算法,它的工作原理是根据给定的训练数据集,对于新的输入实例,在训练数据集中找到距离最近的K个样本点。然后通过这K个样本点所属类别的多数投票来决定该输入实例所属的类别。K近邻算法将新的数据点归类到与其最接近的K个训练数据点中所属类别中。

KNN优点:简单易懂、易于实现、不需要训练阶段等。适用于各种数据类型,特别是在数据特征较少或者数据之间有明显的局部结构时表现较好。

KNN缺点:计算复杂度较高,特别是在处理大规模数据集时。

(4)多层感知机

多层感知机(Multilayer Perceptron,简称MLP)是一种前馈神经网络–基于多层节点的人工神经网络模型,是深度学习的基本组成部分之一,被广泛用于解决分类和回归等问题。

MLP优点:通过增加隐藏层和节点的数量来处理复杂的非线性问题,提高模型的表现能力。

MLP缺点:训练和调整需要大量的数据和计算资源,容易陷入过拟合的问题。

(5)神经网络算法

神经网络算法常用在解决分类和回归问题。OCR技术中也广泛使用了基于神经网络的算法,字符图像在使用神经网络分类器进行识别时,根据网络的输入层的不同可以分为两种情况:

一是将二维的字符图像直接作为网络的输入,将图像的各个像素点作为节点进行全连接,这种方法可以实现较高的识别正确率,且抗干扰能力强,但会花费较长的时间训练网络;

二是对字符图像进行特征提取,然后将提取到字符特征信息作为祌经网络输入进行网络训练,可有效减少网络训练所需的时间,但字符识别正确率的高低取决于字符特征信息提取的有效程度。

总结: 传统OCR方法是基于投影法、连通域分析法等方法对文本行进行字符分割,利用单字分类器对分割好的字符,或利用滑动窗口按一定步长滑窗,利用单字分类器对滑动窗口内的字符进行识别,但是这些方法的准确率有限,其主要应用于背景颜色单一、尤其是在复杂场景识别下,识别效果不如基于深度学OCR习方法。

二、深度学习OCR

近年来随着深度学习技术的飞速发展,OCR技术逐渐由手工设计文本特征训练模型的方式演变成使用CNN深度卷积神经网络模型进行图像自动特征提取,在文字识别效果上也有了较大的提升。

2.1技术流程:

深度学习图像文字识别流程包括:输入图像、深度学习文字区域检测、预处理、特征提取、深度学习识别器、深度学习后处理等。

在这里插入图片描述

  • 图像预处理:  这一阶段是对输入的图像或视频进行一些必要的处理,以便于后续的文字检测和识别。主要包括灰度化、二值化、降噪、倾斜校正、归一化等操作。
  • 文字检测:  这一阶段是将图像中的文字区域定位出来,并给出其位置和方向的信息。主要包括基于回归的方法和基于分割的方法,以及一些将两者结合的方法。常用的模型有CTPN、EAST、SegLink、TextBoxes、R2CNN、PixelLink、PSENet等。
  • 文字识别:  这一阶段是对检测出的文字区域进行字符级别的识别,将图像中的文字转换为可读的文本信息。主要包括单字分类、整词分类和整词识别三种类型,以及一些解码算法来进行输入输出的对齐。常用的模型有CRNN、Attention OCR等。
  • 后处理:  这一阶段是对识别结果进行优化和校正,以提高准确率和可读性。主要包括利用语言模型、字典、规则等方法来纠正错误或歧义的识别结果,以及利用版面分析、格式化等方法来还原原始文档的排版和结构。

2.2 OCR文字检测与文字识别

OCR识别算法可分为两阶段算法和端对端的算法。两阶段OCR算法分为两部分,文本检测和文本识别算法,文字检测算法从图像得到文本行检测框,然后识别算法去识别文本框中内容。

同时,按数据集分类识别:可以分为不规则文本及规则文本识别,按处理场景识别可分为简单应用场景和复杂场景识别,其中,端到端算法可以处理复杂场景识别。

image.png

2.2.1 深度学习文字检测

(1)深度学习文字检测模型发展:

image.png

(2)场景文字检测方法分类

从结构出发,文字检测技术可以分为自顶向上和自顶向上。而从识别方式上,主要分为基于回归和基于分割两种检测方式。

image.png

2.2.2 深度学习文字识别

(1)文字识别模型发展:

image.png

(2)场景文字识别方法分类:

image.png

(3) 文字识别算法流程

目前主流的深度学习识别算法通用框架包括图像预处理(校正变化)、视觉特征提取、序列提取及预测等模块,其流程如图所示:

image.png

深度学习OCR方法分类总结:

深度学习OCR识别方法主要包括基于CTC、基于Attention、基于Transformer、基于分割及端到端识别等几种方法。其中文字识别主流方法有CRNN、ASTER、SRN、ABINet等。

具体分类及论文参考下表:

算法类别 主要思路 主要论文
传统算法 滑动窗口、字符提取、动态规划
ctc 基于ctc的方法,序列不对齐,更快速识别 CRNN, Rosetta
Attention 基于attention的方法,应用于非常规文本 RARE, DAN, PREN
Transformer 基于transformer的方法 SRN, NRTR, Master, ABINet
校正 校正模块学习文本边界并校正成水平方向 RARE, ASTER, SAR
分割 基于分割的方法,提取字符位置再做分类 Text Scanner, Mask TextSpotter

OCR识别算法总结:

  • 基于CTC识别算法主要CRNN,CTC损失解决序列对齐问题,推理速度快,识别精度高。
  • 基于Attention识别算法主要有ASTER、RAEN等,结合注意力机制基本思想让系统学会注意力关注重点信息,同时忽略无关信息,有效提升精度。
  • 端到端识别主要有STN-OCR、FOTS、ABCnet、MORAN等方法,无需检测后在识别,可以实现端到端识别。

注:文字识别算法详细介绍建第四章。

2.3 端到端自然场景检测和识别方法:

端对端OCR算法可以在一个算法中完成文字检测和文字识别,其基本思想是设计一个同时具有检测单元和识别模块的模型,共享其中两者的CNN特征,并联合训练。由于端对端OCR算法是使用一个模型同时完成文字检测和识别,因此,端对端模型更小,速度更快。

深度学习端到端文本识别具有代表性的方法大致可分为两类:

  • 端到端规则文本识别(平直文本或倾斜文本),代表算法有FOTS、TextSpotter等。

  • 端到端任意形状文本识别(弯曲、变形、平直、倾斜文本)。代表算法有Mask TextSpotter系列、ABCNet系列、PGNet、PAN++等。

image.png

总结: 端到端规则文本识别主要是解决平直文或着倾斜文本的检测和识别,然而弯曲、变形等文本在自然场景中大量出现,如印章等,在检测和识别这些文本需要使用端到端任意形状文本识别算法,与此同时这些算法也可以检测和识别平直和倾斜的文本。

三、基于OpenCV的传统OCR识别实战

import cv2
import numpy as np
import argparse
import imutils
from imutils import contours
import pytesseract
from  PIL import Image
import os

def ShowImage(name, image):
    cv2.imshow(name, image)
    cv2.waitKey(0)  # 等待时间,0表示任意键退出
    cv2.destroyAllWindows()

def order_points(pts):
    # 四个点坐标
    rect = np.zeros((4,2), dtype="float32")

    # 按顺序找到坐标,分别左上,右上,右下,左下
    # 计算左上、右下
    s = pts.sum(axis=1)
    rect[0] = pts[np.argmin(s)]
    rect[2] = pts[np.argmax(s)]

    # 计算右上和左下
    diff = np.diff(pts, axis=1)
    rect[1] =pts[np.argmin(diff)]
    rect[3] = pts[np.argmax(diff)]
    return rect

def four_point_transform(image, pts):
    # 获取输入坐标点
    rect = order_points(pts)
    (tl, tr, br, bl) = rect

    # 计算输入的W和h值
    widthA = np.sqrt(((br[0] - bl[0])**2) + ((br[1] - bl[1])**2))
    widthB = np.sqrt(((tr[0] - tl[0]) ** 2) + ((tr[1] - tl[1]) ** 2))
    maxWidth = max(int(widthA), int(widthB))

    heightA = np.sqrt(((tr[0] - br[0]) ** 2) + ((tr[1] - br[1]) ** 2))
    heightB = np.sqrt(((tl[0] - bl[0]) ** 2) + ((tl[1] - bl[1]) ** 2))
    maxheight = max(int(heightA), int(heightB))

    # 变换后的对应坐标位置
    dst = np.array([
        [0,0],
        [maxWidth-1, 0],
        [maxWidth-1,maxheight-1],
        [0, maxheight-1]

    ], dtype="float32")

    # 计算变换矩阵
    M = cv2.getPerspectiveTransform(rect, dst)
    warp = cv2.warpPerspective(image, M, (maxWidth, maxheight))
    return warp

def resize(image, width=None, height=None, inter=cv2.INTER_AREA):
    dim = None
    (h,w)=image.shape[:2]
    if width is None and height is None:
        return image
    if width is None:
        r=height/float(h)
        dim=(int(w*r), height)
    else:
        r=width/float(w)
        dim=(width, int(h*r))
    resized = cv2.resize(image, dim,interpolation=inter)
    return resized

image = cv2.imread('ocr1.png')
ratio = image.shape[0]/500     # ratio ,是图像转换的比例,稍后会将图像置为500高度的大小,,最后面在转换后需要转换为原来大小
orig = image.copy()   # orig,先复制一个原图出来,后面在处理时,image会变化
image = resize(image, height=500)   # 将图像变为高500的图像

#图像预处理
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)  # 转化为灰度图
gray = cv2.GaussianBlur(gray, (5,5), 0)         # 通过高斯滤波去除噪声
edged = cv2.Canny(gray, 75, 200)        # 检测边缘
ShowImage('edged', edged)

# 轮廓检测
cnts,his = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
cnts = sorted(cnts, key=cv2.contourArea, reverse=True)[:5]  # 按轮廓面积进行排列,取前面5个轮廓

# 遍历每一个轮廓
for c in cnts:
    # 计算轮廓近似
    peri = cv2.arcLength(c,True)

    # c表示输入的点集
    # epsilon表示从原始轮廓到近似轮廓的最大距离,它是一个准确度参数
    # True表示封闭的
    approx = cv2.approxPolyDP(c,0.02*peri, True)

    # 四个点的时候就拿出来
    if len(approx)  == 4:
        screecnt = approx
        break

# 画图
cv2.drawContours(image, [screecnt], -1, (0,0,255), 2)
ShowImage('image',image)

# 透视变换,将输入的四个点,已知4个目标点,通过矩阵变换,图像旋转到目标位置
warped = four_point_transform(orig, screecnt.reshape(4,2)*ratio)
ShowImage('warped', warped)
# 二值处理
warped = cv2.cvtColor(warped, cv2.COLOR_BGR2GRAY)  # 转换为灰度图
ref = cv2.threshold(warped, 100, 255, cv2.THRESH_BINARY)[1]  # 图像二值化
ShowImage('binary', ref)

# 用OCR工具包test
filename = "{}.png".format(os.getpid())
cv2.imwrite(filename, ref)
text = pytesseract.image_to_string(Image.open(filename))
print(text)
os.remove(filename)

ShowImage('image', ref)

实现效果:

image.png

image.png

image.png

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYzzO6uG' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片