本文讲述使用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 mathimport cv2
import easyocr
import numpy as np
from matplotlib import pyplot as pltimg = 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跑这段代码需要花一些时间,请大家务必注意。

OpenCV OCR实战 文档扫描与文字检测相关推荐

  1. OpenCv图像处理实战——文档扫描

    文档扫描 测试图片自取 page.jpg import cv2 import argparse import numpy as np import matplotlib.pyplot as plt d ...

  2. 基于C++的OpenCV项目实战——文档照片转换成扫描文件

    基于C++的OpenCV项目实战--文档照片转换成扫描文件 一.背景 前段时间都是基于Python的OpecCV进行一些学习和实践,但小的知识点并没有应用到实际的项目中:并且基于Python的版本的移 ...

  3. 项目实战——文档扫描OCR识别

    扫描全能王的实现,maybe 目录 一.文档扫描 1.引入所需要的库 2.图像的读取与预处理 读取图像 图像reszie, 图像灰度化.滤波.边缘检测. 3.轮廓检测 4.透视与二值变换 二.文字识别 ...

  4. 【实战】OpenCV+Python项目实战--文档扫描OCR识别

    文章目录 1 准备工作(python) 1.1 np.diff用法 1.2 tesseract和pytesseract安装 2代码实现 2.1 文档提取与摆正 2.2 OCR扫描 1 准备工作(pyt ...

  5. 实战:基于OpenCV实现偏斜文档校正

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达本文转自|OpenCV学堂 纸质文档扫描中经常会发生扫描出来的图像有 ...

  6. opencv项目实战(2)——文档扫描OCR识别

    文章目录 思路 文档扫描 代码 运行结果 文字识别 预处理 代码 运行结果 Debug 记录 思路 STEP 1: 边缘检测 STEP 2: 获取轮廓 STEP 3: 变换 文档扫描 代码 scan. ...

  7. OpenCV计算机视觉实战(Python)| 10、项目实战:文档扫描OCR识别

    文章目录 简介 总结 1. 介绍 2. 流程 3. 程序 4. 知识点总结 简介 本节为<OpenCV计算机视觉实战(Python)>版第10讲,项目实战:文档扫描OCR识别,的总结. 总 ...

  8. Opencv实战——OCR文档扫描

    文章目录 前言 一.安装Tesseract-OCR 二.文档扫描 1.需要透视变换的图像 2.直接Tesseract-OCR 总结 前言 这里实现文档扫描主要是依靠Tesseract,Tesserac ...

  9. 深入学习OpenCV文档扫描OCR识别及答题卡识别判卷(文档扫描,图像矫正,透视变换,OCR识别)

    人工智能学习离不开实践的验证,推荐大家可以多在FlyAI-AI竞赛服务平台多参加训练和竞赛,以此来提升自己的能力.FlyAI是为AI开发者提供数据竞赛并支持GPU离线训练的一站式服务平台.每周免费提供 ...

最新文章

  1. 不使用任何框架实现CNN网络
  2. 2月书讯 | 冬奥结束看什么?看看“天花板”级别新作!
  3. 支付宝支付 第三集:搭建项目及测试(含代码)
  4. mysql视图学习总结
  5. 操作系统-并发性:互斥与同步
  6. 指定应用程序网络连接_总结Java开发Web应用程序应该理解的几个知识点
  7. linux下的struct sigaction
  8. 4.WCF事务【Transaction】
  9. Android Studio之导入别人的module后config.gradle配置文件没有生效
  10. leetcode111. 二叉树的最小深度(层序遍历10)
  11. 更改mysql数据库存放位置_更改mysql数据库存放位置
  12. 群晖 百度网盘_海康威视联合百度网盘推出NAS私有存储 贡献带宽获积分兑网盘会员...
  13. 人工智能将进入能源生产领域
  14. 力控批量添加变量_力控组态软件的变量操作函数1
  15. java关键字_Java关键字
  16. unittest框架(惨不忍睹低配版)
  17. 计算机网络自顶向下方法 【第一章 计算机网络及因特网】
  18. nginx 502错误原因及解决办法
  19. 如何解决电脑网络提示无Internet访问权限
  20. 路飞学城python电子书闲鱼_路飞学城-python开发集训-第一章之用户登录作业

热门文章

  1. 807计算机考研真题,东北财经大学807计算机综合历年考研真题汇编.pdf
  2. 旅行商问题的手工运算及完整代码(TSP)
  3. 计算两个向量的余弦相似度
  4. UI设计中的交互设计原则有哪些?
  5. 2019python下半年考试报名时间_2019年下半年教师资格证考试时间安排已出,9月起报名...
  6. outlook计算机应用操作题,《计算机应用基础》Internet应用题型专项练习
  7. linux tcpreplay命令
  8. 怎么批量抠复杂的图_剪映教程:剪映怎么抠图?
  9. 系统分析--详细描述
  10. 新人制作机器人的7大误区