OpenCV OCR实战 文档扫描与文字检测

本文讲述使用OpenCV- python以及easyocr库实现文档扫描与文字检测的思路和具体实现过程。

目录

知识准备

项目概述

实现过程

代码讲解 

         1.读入图片并进行预处理(灰度转换,高斯滤波)

         2.对图片进行canny边缘检测,进一步处理

         3.轮廓识别,轮廓排序,轮廓近似得到最外层轮廓角点

        4.仿射变换,二值处理 

        5.文字识别 


知识准备

本项目需要用到以下知识:

        1.OpenCV图像基础操作,如读取,灰度转换等

        2.阈值操作,如二值化

        3.canny边缘检测以及boundingBox构建

        4.卷积核构建

        5.膨胀操作

        6.形态学操作如close操作

        7.用pyplot查看图片,便于debug

        8.高斯滤波

        9.easyocr库函数调用

        10.仿射变换

项目概述

本项目旨在实现对于倾斜文稿的自动扫描以及文字检测

        给定测试图片如下


 

        实现最终效果如图

实现过程

        1.读入图片并进行预处理(灰度转换,高斯滤波)

        2.对图片进行canny边缘检测,进一步处理

        3.轮廓识别,轮廓排序,轮廓近似得到最外层轮廓角点

        4.仿射变换,二值处理

        5.文字识别

代码讲解 

         1.读入图片并进行预处理(灰度转换,高斯滤波)

import math

import cv2
import easyocr
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('bill.png')
img_gray = cv2.imread('bill.png', 0)
# show('result', img)
# show('res', img_gray)
img_blur = cv2.GaussianBlur(img_gray, (5, 5), 1)
# show('gauss', img_blur)

        本段代码实现了图片的读取和灰度转换,并按照一个5*5的卷积核进行高斯滤波操作。高斯滤波的意义在于滤除图像中的噪声点,有利于在提取边界时获得更准确有用的信息。

         2.对图片进行canny边缘检测,进一步处理

edges = cv2.Canny(img_blur, 50, 200)
# show('canny', edges)
kernel = np.ones((2, 2), np.uint8)
rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (15, 15))
edges_close = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, rectKernel)
edges_dilate = cv2.dilate(edges_close, kernel, iterations=3)
# show('dilate', edges_dilate)

# show('close', edges_close)
# show('dilate', edges_dilate)

        本段代码对滤波之后的图片实施了canny边缘检测,构建了一个2*2的卷积核并执行了闭操作和膨胀操作。

        canny后的结果如图

        闭操作结果

 

         膨胀操作结果

         可以看出,只进行一次Canny之后图片的边界信息都完整地呈现了出来,但由于我们下一步需要筛选出最外层边界,过多的边界信息会对筛选造成困难,所以加以闭操作和膨胀操作。闭操作使得文字的边界连在了一起,减少了边界的数量,增加了筛选的可靠性。膨胀操作使得边界变粗,增加了轮廓识别的可靠性。

         3.轮廓识别,轮廓排序,轮廓近似得到最外层轮廓角点

contours, hierarchy = cv2.findContours(edges_dilate, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
contours = sorted(contours, key=lambda cnts: cv2.arcLength(cnts, True), reverse=True)

img_copy = img.copy()
res = cv2.drawContours(img_copy, contours, 0, (0, 0, 255), 2)
# show('res', res)
img_copy = img.copy()
cnt = contours[0]
epsilon = 0.03 * cv2.arcLength(cnt, True)  # epsilon占周长的比例
approx = cv2.approxPolyDP(cnt, epsilon, True)
res2 = cv2.drawContours(img_copy, [approx], -1, (0, 0, 255), 5)
# print(approx)
# show('res2', res2)
[[lt], [lb], [rb], [rt]] = approx
# print(lt, lb, rb, rt)
[ltx, lty] = lt
[lbx, lby] = lb
[rbx, rby] = rb
[rtx, rty] = rt
# print(ltx, lty, lbx, lby, rbx, rby, rtx, rty)
lt = (ltx, lty)
lb = (lbx, lby)
rb = (rbx, rby)
rt = (rtx, rty)
# print(lt, lb, rb, rt)

        本段代码实现了轮廓检测,对检测到的所有轮廓按照长度排序,找出了长度最长的轮廓(小票的外边界)对这个轮廓进行了近似,得到了一个矩形,而且获得了它四个角点的坐标,为下一步进行仿射变换做准备。

        cnt画在原图中的效果如下:

        4.仿射变换,二值处理 

# 仿射变换
width = max(math.sqrt((rtx - ltx) ** 2 + (rty - lty) ** 2), math.sqrt((rbx - lbx) ** 2 + (rby - lby) ** 2))
height = max(math.sqrt((ltx - lbx) ** 2 + (lty - lby) ** 2), math.sqrt((rtx - rbx) ** 2 + (rty - rby) ** 2))
pts1 = np.float32([[ltx, lty], [rtx, rty], [lbx, lby], [rbx, rby]])
pts2 = np.float32([[0, 0], [width, 0], [0, height], [width, height]])
M = cv2.getPerspectiveTransform(pts1, pts2)
width = int(width)
height = int(height)
dst = cv2.warpPerspective(img, M, (width, height))

plt.subplot(121), plt.imshow(img), plt.title('Input')
plt.subplot(122), plt.imshow(dst), plt.title('Output')
plt.show()
print(dst)
resu = cv2.threshold(dst, 120, 255, cv2.THRESH_BINARY)[1]
plt.imshow(resu), plt.title('Result')
plt.show()
cv2.imwrite('OCR.jpg', resu)

         这段代码实现了对小票的“摆正”。前两行求出了小票的宽和高,由于之前获得的角点围成的图形不一定是矩形,这里取了对应边长的最大值。pts1和pts2分别表示四个角点在原图中的坐标和其对应目标位置的坐标。M矩阵是原坐标向目标坐标的变换矩阵,这里可以通过cv自带的getPerspectiveTransform方法计算得出。最后通过warpPerspective方法将M与原图片相乘得到目标图片,另外还进行了二值化处理,保存,以便下一步进行OCR。

        运行结果如图

 

        5.文字识别 

# ocr
# 创建reader对象

reader = easyocr.Reader(['ch_sim', 'en'])

# 读取图像

result = reader.readtext('OCR.jpg')
print(result)
for i in result:
    print(i[1])

        这段代码调用了easyocr里的方法进行OCR,由于result列表的特殊结构,文字被储存在了每个列表元素的第二项。

        运行结果

        可以看出easyocr库对中文的支持度还是比较差的,但是基本达到了我们的目的。读者可以通过使用其他的OCR库来达到更高的识别成功率。另外,还可以对仿射变换后的图片进行更加优化的图形学处理来达到更好的效果。

        此外,easyocr库需要利用CUDA来实现GPU加速,由于笔者使用的电脑为M1Pro芯片,并非nvadia显卡,故无法使用CUDA,而用CPU跑这段代码需要花一些时间,请大家务必注意。

  • 5
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
### 回答1: Python OpenCV OCR 文字识别是一种使用 Python 编程语言和 OpenCV 图像处理库进行文字识别的技术。它可以通过对图像进行处理和分析,提取出其中的文字信息,并将其转换为可编辑的文本格式。这种技术在很多领域都有广泛的应用,如自动化文档处理、车牌识别、手写体识别等。 ### 回答2: Python OpenCV OCR(Optical Character Recognition)文字识别是一种可以将图像中的文字转化为可编辑文本的技术。利用OCR技术,可以将印刷体、手写体等不同类型的文字进行自动识别和转换。 Python OpenCV是一种非常流行的计算机视觉库,可用于在Python中处理图像和视频数据。通过结合Python OpenCVOCR技术,我们可以创建一个全自动的文字识别系统。 Python OpenCV OCR文字识别的实现过程如下: 1.导入Python OpenCV库和OCR库 首先,需要导入Python OpenCV库和OCR库。PythonOpenCV库包含了许多优秀的图像处理和计算机视觉函数,而OCR库则用于实现文字识别功能。 2.从图像中提取文本区域 接下来,需要从图像中提取文本区域。可以使用Python OpenCV中的图像处理技术对图像进行预处理,然后使用OCR技术识别出文本区域。 3.对文本区域进行预处理 在提取文本区域之后,需要对文本区域进行预处理。可以使用Python OpenCV中的图像处理技术,如二值化、降噪、旋转等,对文本区域进行处理,以便更好地进行OCR文字识别。 4.使用OCR技术识别文本 最后,使用OCR技术对文本区域进行识别和转换。OCR库提供了多种识别引擎和算法,可以根据实际情况进行调配。 总之,Python OpenCV OCR文字识别是一项非常有用的技术,可以应用于多种领域,如身份证识别、车牌号识别、手写体识别等。通过合理使用Python OpenCVOCR技术,可以实现自动化的文字识别和转换。 ### 回答3: Python OpenCV OCR文字识别是一项专门用于识别图像中的文字的技术。OCR代表光学字符识别,并使用一种算法实现对图像中的文字进行识别,这种算法从图像中抽取出字符并将其识别为文本。 Python OpenCV可用于识别诸如身份证、发票、车牌等各种类型的文字。它使用计算机视觉和深度学习技术,可以从图像中提取出字符并将其转换为文本。下面是Python OpenCV OCR文字识别的一些优点和应用: 优点: - Python OpenCV OCR文字识别技术可以自动读取电子文件或数字图像中的文本,提高工作效率,减少手动输入的错误。 - Python OpenCV OCR文字识别技术基于计算机视觉和深度学习技术,不需要手工标记文本或字符,因此可自动化完成任务。 - Python OpenCV OCR文字识别技术可以精确地识别文本,无论是印刷的还是手写的字体。 应用: - Python OpenCV OCR文字识别技术可用于电子清单、操作手册、合同、票据、病历等文档的自动扫描识别。 - Python OpenCV OCR文字识别技术可用于自动识别车牌、信用卡、身份证等个人身份信息的自动识别。 - Python OpenCV OCR文字识别技术可用于自动识别游戏中的文字,例如,在棋盘游戏中可以自动识别识别棋子上的文字。 在Python OpenCV OCR文字识别前,需要进行图像预处理,例如:图像增强、二值化等操作;然后进行字符分割,最后使用识别算法将图像中的字符转换为文本。一般来说,Python OpenCV OCR文字识别需要大量的图像处理技术、计算机视觉技术和深度学习技术。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

知欧zhou

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值