已经感觉一个月没有更博了,最近也是在找工作找实习。最近在看的就是如何使用神经网络去做一个OCR识别,网上的资料多种多样,包括分割单字进行识别的,也有不定长文字识别。网络模型目前看到比较多的是CRNN,检测的模型包括CTPN、YOLO等等。

今天整理的是数据预处理上的文本透视矫正与水平矫正。

一、透视矫正

透视矫正是什么?比如发现了一页纸,写的挺好,你想拍下来,但是拍摄时角度的问题,你拍成了下面左边的样子,但是你本来想的是从纸的正上方去拍,所以你要想办法去把照片矫正成右边的样子,矫正的过程称为透视矫正。

所以呢为了透视矫正,首先需要的就是找到这张纸的轮廓,然后按照从大小的顺序排列,排好之后,找出最大的轮廓,如果判定找到的最大轮廓有四个点,则可以判定我们找到这张纸,然后用四点透视变换获得纸张的俯视图。

写好的函数是这样:

def order_points(pts):# 一共4个坐标点rect = np.zeros((4, 2), dtype = "float32")# 按顺序找到对应坐标0123分别是 左上,右上,右下,左下# 计算左上,右下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 rectdef 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)warped = cv2.warpPerspective(image, M, (maxWidth, maxHeight))# 返回变换后结果return warped# 透视矫正
def perspective_transformation(img):# 读取图像,做灰度化、高斯模糊、膨胀、Canny边缘检测gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)blurred = cv2.GaussianBlur(gray, (5, 5), 0)dilate = cv2.dilate(blurred, cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3)))# edged = cv2.Canny(dilate, 75, 200)edged = cv2.Canny(dilate, 30, 120, 3)cnts = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)cnts = cnts[0] if imutils.is_cv2() else cnts[1]  # 判断是OpenCV2还是OpenCV3docCnt = None# 确保至少找到一个轮廓if len(cnts) > 0:# 按轮廓大小降序排列cnts = sorted(cnts, key=cv2.contourArea, reverse=True)for c in cnts:# 近似轮廓peri = cv2.arcLength(c, True)approx = cv2.approxPolyDP(c, 0.02 * peri, True)# 如果我们的近似轮廓有四个点,则确定找到了纸if len(approx) == 4:docCnt = approxbreak# 对原始图像应用四点透视变换,以获得纸张的俯视图paper = four_point_transform(img, docCnt.reshape(4, 2))return paper

然后,你找到纸以后,可能会发现上面的字会有一点点倾斜,虽然感觉上是没什么问题,但是在识别的过程中会因为这一点点的倾斜导致识别串行。数据分析的过程就会比较麻烦。所以尽可能在预处理过程中就避免这类问题的发生。

二、文本水平矫正

其实,这也叫做文本的水平矫正。毕竟跟普通的水平矫正还不太一样,普通的水平矫正图像都会带有自己的边缘,根据边缘可以提取出一个mask,然后进行旋转即可。文本图像的背景是白色的,所以我们没有办法像人民币发票那类有明显边界的矩形物体那样,提取出轮廓并旋转矫正。这里我们用基于直线探测的水平矫正

霍夫变换算法思想:以直线检测为例,每个像素坐标点经过变换都变成都直线特质有贡献的统一度量,一个简单的例子如下:一条直线在图像中是一系列离散点的集合,通过一个直线的离散极坐标公式,可以表达出直线的离散点几何等式如下:

X *cos(theta) + Y * sin(theta)  = r 其中角度theta指r与X轴之间的夹角,r为到直线几何垂直距离。任何在直线上点,x, y都可以表达,其中 r, theta是常量。该公式图形表示如下:

然而在实现的图像处理领域,图像的像素坐标P(x, y)是已知的,而r, theta则是我们要寻找的变量。如果我们能绘制每个(r, theta)值根据像素点坐标P(x, y)值的话,那么就从图像笛卡尔坐标系统转换到极坐标霍夫空间系统,这种从点到曲线的变换称为直线的霍夫变换。变换通过量化霍夫参数空间为有限个值间隔等分或者累加格子。当霍夫变换算法开始,每个像素坐标点P(x, y)被转换到(r, theta)的曲线点上面,累加到对应的格子数据点,当一个波峰出现时候,说明有直线存在。

所以我们的思路是:

  1. 用霍夫线变换探测出图像中的所有直线
  2. 计算出每条直线的倾斜角,求他们的平均值
  3. 根据倾斜角旋转矫正

给出完整代码:

# coding=utf-8
import cv2
import numpy as npinput_img_file = "../test/test.png"# 度数转换
def DegreeTrans(theta):res = theta / np.pi * 180return res# 逆时针旋转图像degree角度(原尺寸)
def rotateImage(src, degree):# 旋转中心为图像中心h, w = src.shape[:2]# 计算二维旋转的仿射变换矩阵RotateMatrix = cv2.getRotationMatrix2D((w/2.0, h/2.0), degree, 1)print(RotateMatrix)# 仿射变换,背景色填充为白色rotate = cv2.warpAffine(src, RotateMatrix, (w, h), borderValue=(255, 255, 255))return rotate# 通过霍夫变换计算角度
def CalcDegree(srcImage):midImage = cv2.cvtColor(srcImage, cv2.COLOR_BGR2GRAY)dstImage = cv2.Canny(midImage, 50, 200, 3)lineimage = srcImage.copy()# 通过霍夫变换检测直线# 第4个参数就是阈值,阈值越大,检测精度越高lines = cv2.HoughLines(dstImage, 1, np.pi/180, 200)# 由于图像不同,阈值不好设定,因为阈值设定过高导致无法检测直线,阈值过低直线太多,速度很慢sum = 0# 依次画出每条线段for i in range(len(lines)):for rho, theta in lines[i]:# print("theta:", theta, " rho:", rho)a = np.cos(theta)b = np.sin(theta)x0 = a * rhoy0 = b * rhox1 = int(round(x0 + 1000 * (-b)))y1 = int(round(y0 + 1000 * a))x2 = int(round(x0 - 1000 * (-b)))y2 = int(round(y0 - 1000 * a))# 只选角度最小的作为旋转角度sum += thetacv2.line(lineimage, (x1, y1), (x2, y2), (0, 0, 255), 1, cv2.LINE_AA)cv2.imshow("Imagelines", lineimage)# 对所有角度求平均,这样做旋转效果会更好average = sum / len(lines)angle = DegreeTrans(average) - 90return angleif __name__ == '__main__':image = cv2.imread(input_img_file)cv2.imshow("Image", image)# 倾斜角度矫正degree = CalcDegree(image)print("调整角度:", degree)rotate = rotateImage(image, degree)cv2.imshow("rotate", rotate)# cv2.imwrite("../test/recified.png", rotate, [int(cv2.IMWRITE_PNG_COMPRESSION), 0])cv2.waitKey(0)cv2.destroyAllWindows()

所以我就从参考的博客中也找的一样的图进行测试,效果还不错~以下图分别是原图,直线检测之后,旋转之后。

谢谢大佬们提供的思路,后续可以再利用这个方法提取出需要的数据区域等等,未完待续哦~

【参考资料】

http://www.cnblogs.com/skyfsm/p/7324346.html

http://www.cnblogs.com/skyfsm/p/6902524.html

https://blog.csdn.net/jia20003/article/details/7724530

OpenCV-Python的文本透视矫正与水平矫正相关推荐

  1. OpenCV—python OCR文本检测

    文章目录 一.形态学文本区域检测 1.1 直接匹配 1.2 多尺度匹配 二.MSER+NMS文本区域检测 2.1 MSER 2.2 NMS 一.形态学文本区域检测 图像形态学操作,包括膨胀.腐蚀基本操 ...

  2. python opencv 文字识别_文本识别 使用 Tesseract 进行 OpenCV OCR 和 文本识别

    文本识别 用 Tesseract 进行 OpenCV OCR 和 文本识 在本教程中,您将学习如何应用OpenCV OCR(光学字符识别).我们将使用OpenCV,Python和Tesseract 执 ...

  3. 实战 | OpenCV实现扫描文本矫正应用与实现详解(附源码)

    导读 本文主要介绍使用OpenCV对扫描文本矫正的应用实例及详细实现步骤. 背景介绍 在使用打印机或扫描仪扫描文档时,由于摆放位置差异难免造成扫描文档的倾斜.本文将使用OpenCV将倾斜的文档矫正水平 ...

  4. OpenCvSharp (C# OpenCV) 实现扫描文本矫正应用与实现详解(附源码)

    导  读 本文主要介绍使用OpenCV对扫描文本矫正的应用实例及详细实现步骤. 背景介绍 在使用打印机或扫描仪扫描文档时,由于摆放位置差异难免造成扫描文档的倾斜.本文将使用OpenCV将倾斜的文档矫正 ...

  5. python 图片 文本 矫正

    python 图片 文本 矫正 代码 # -*- coding: UTF-8 -*- import numpy as np import cv2 import os ## 图片旋转 def rotat ...

  6. python.freelycode.com-通过OpenCV和Python进行文本倾斜校正

    Python部落(python.freelycode.com)组织翻译,禁止转载,欢迎转发. 本文所展示的是一个由Pyhton实现的文本倾斜校正的脚本,在实现中使用到了OpenCV和Python的图像 ...

  7. 机器视觉 OpenCV—python 基于LSTM网络的OCR文本检测与识别

    文章目录 一.背景与环境搭建 二.文本检测与识别 一.背景与环境搭建 OpenCV的文本识别流程: OpenCV EAST 文本检测器执行文本检测, 我们提取出每个文本 ROI 并将其输入 Tesse ...

  8. python写透视挂_如何用Python openCV 用透视变换的方法对图像进行矫正

    .需要矫正的图片1 需要矫正的图 矫正后的结果: 矫正后的图 需要矫正的图片2 矫正前 矫正后 # import the necessary packages from imutils.perspec ...

  9. Opencv - python快速入门

    Opencv - python 文章目录 Opencv - python 1. 图像的IO操作 1.1 读取图像 1.2显示图像 1.3 保存图像 1.4 总结 2 绘制几何图形 2.1 绘制直线 2 ...

最新文章

  1. 关于jQuery对象与DOM对象
  2. 全志 添加PWM7参数
  3. axios、ajax和xhr前端发送测试
  4. linux下echo与time服务的程序实现
  5. 企业实战04:Oracle数据库_管理表
  6. pytorch学习笔记(二十六):NIN
  7. UnityShader29:模板测试
  8. 在kettle中实现数据验证和检查
  9. 英读廊——为什么打印机不使用RGB颜色体系而是CMYK体系
  10. 利用有放回抽样估计自然常数e python
  11. 苹果微信更新不了最新版本_微信更新7.0版本,为何优先给iOS用户体验?这是在歧视安卓?...
  12. 俞敏洪励志演讲稿【二】
  13. html网页右侧悬浮代码,html悬浮窗口代码
  14. mysql里面除号写法_Mysql之常见函数
  15. CentOS7_mysql数据库备份
  16. javascript设计模式-观察者模式(observer pattern)
  17. ecdf函数的逆函数_如何区分反函数和逆函数
  18. 挂载 nfs 文件系统
  19. 0.8um具备DCG特性的CIS
  20. 一则uiautomation错误处理

热门文章

  1. java工厂方法模式记录日志_java工厂方法模式
  2. 猿创征文 |【敢问路在何方,路在脚下】-一个野生产品的血泪技术成长史
  3. 使用HbuilderX 的UNIapp开发app, 打包后定位不能使用的解决方式
  4. 用C语言根据出生年月日判断年龄
  5. 计算机毕业设计如何制作电子商务网站怎么制作购物网站计算机课程设计电子商城做什么(PHP-ASP.NET-c#-JavaWeb-SSM-SSH-J2EE-springBoot
  6. 如何查看自己电脑显卡对应的cuda版本
  7. Python双目相机计算三维坐标(使用opencv自带图片)
  8. Swift Black Substratum主题v23.3补丁[最新]
  9. 俄罗斯方块的设计思路
  10. 如何平衡老师任务和自学之间的关系