图像矫正就是通过一些已知的参考点,即无失真图象的某些象素点和畸变图象相应象素的坐标间对应关系,拟合出映射关系中的未知系数,并作为恢复其它象素的基础。

1、矫正原理

在进行图片矫正时,有些图片具有小角度的倾斜(±45°以内),导致传入后续识别分类的模型时产生误差。可以利用文本图像具有行间空白的特性,对待检测图像进行角度旋转遍历,并同时进行水平方向像素值投影,当文本方向水平时,投影所得的0值最多。从而达到所要矫正的目的。

2、边缘投影

在参考点足够的情况下,推算全图变形函数,比如:当水平线倾斜时投影值比较小,但是当水平线正常时其在水平面上的投影是最大的。根据这个进行参考,倾斜的物体在水平方向上的投影只要经过旋转处理就可以达到最大,此时的图片就是正常。

3、基于边缘投影法的矫正过程

(1)对检测图像进行角度旋转遍历

(2)进行水平方向像素值投影

(3)找到投影所得的0值最多的方向

(4)对该方向进行矫正

用到的工具:opencv、numpy、matplotlib

首先获取图片的宽度以及高度

def rotate_bound(image, angle):# 获取图片的宽高(h, w) = image.shape[:2](cX, cY) = (w // 2, h // 2)M = cv2.getRotationMatrix2D((cX, cY), angle, 1.0)img = cv2.warpAffine(image, M, (w, h))return img

其次,寻找当前图片文本的旋转角度,在±90度之间

def findangle(_image):toWidth = _image.shape[1]//2 #500minCenterDistance = toWidth/20 #10angleThres = 45image = _image.copy()h, w = image.shape[0:2]if w > h:maskW = toWidthmaskH = int(toWidth / w * h)else:maskH = toWidthmaskW = int(toWidth / h * w)

接着,使用黑色填充图片的其他区域

# 使用黑色填充图片区域swapImage = cv2.resize(image, (maskW, maskH))grayImage = cv2.cvtColor(swapImage, cv2.COLOR_BGR2GRAY)gaussianBlurImage = cv2.GaussianBlur(grayImage, (3, 3), 0, 0)histImage = cv2.equalizeHist(~gaussianBlurImage)binaryImage = cv2.adaptiveThreshold(histImage, 1, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 15, -2)

然后,遍历角度时计算的关键点数量

pointsNum = np.sum(binaryImage!=0)//2

紧接着使用连接组件寻找并删除边框线条,计算每个连通区域坐上右下点的索引坐标与其质心的距离,距离大的即为线条

    connectivity = 8num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(binaryImage, connectivity, cv2.CV_8U)labels = np.array(labels)maxnum = [(i, stats[i][-1], centroids[i]) for i in range(len(stats))]maxnum = sorted(maxnum, key=lambda s: s[1], reverse=True)if len(maxnum) <= 1:return 0for i, (label, count, centroid) in enumerate(maxnum[1:]):cood = np.array(np.where(labels == label))distance1 = np.linalg.norm(cood[:,0]-centroid[::-1])distance2 = np.linalg.norm(cood[:,-1]-centroid[::-1])if distance1 > minCenterDistance or distance2 > minCenterDistance:binaryImage[labels == label] = 0else:break

最后,横向统计非零元素个数 越少则说明姿态越正

# 横向统计非零元素个数 越少则说明姿态越正zeroCount = np.sum(hist > toWidth/50)if zeroCount <= minCount or minCount == -1:minCount = zeroCountminRotate = rotatereturn minRotate

完整代码

import cv2
import numpy as np
from matplotlib import pyplot as pltdef rotate_bound(image, angle):# 获取图片的宽高(h, w) = image.shape[:2](cX, cY) = (w // 2, h // 2)M = cv2.getRotationMatrix2D((cX, cY), angle, 1.0)img = cv2.warpAffine(image, M, (w, h))return imgdef rotate_points(points, angle, cX, cY):M = cv2.getRotationMatrix2D((cX, cY), angle, 1.0).astype(np.float16)a = M[:, :2]b = M[:, 2:]b = np.reshape(b, newshape=(1, 2))a = np.transpose(a)points = np.dot(points, a) + bpoints = points.astype(np.int)return pointsdef findangle(_image):toWidth = _image.shape[1]//2 #500minCenterDistance = toWidth/20 #10angleThres = 45image = _image.copy()h, w = image.shape[0:2]if w > h:maskW = toWidthmaskH = int(toWidth / w * h)else:maskH = toWidthmaskW = int(toWidth / h * w)# 使用黑色填充图片区域swapImage = cv2.resize(image, (maskW, maskH))grayImage = cv2.cvtColor(swapImage, cv2.COLOR_BGR2GRAY)gaussianBlurImage = cv2.GaussianBlur(grayImage, (3, 3), 0, 0)histImage = cv2.equalizeHist(~gaussianBlurImage)binaryImage = cv2.adaptiveThreshold(histImage, 1, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 15, -2)pointsNum = np.sum(binaryImage!=0)//2connectivity = 8num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(binaryImage, connectivity, cv2.CV_8U)labels = np.array(labels)maxnum = [(i, stats[i][-1], centroids[i]) for i in range(len(stats))]maxnum = sorted(maxnum, key=lambda s: s[1], reverse=True)if len(maxnum) <= 1:return 0for i, (label, count, centroid) in enumerate(maxnum[1:]):cood = np.array(np.where(labels == label))distance1 = np.linalg.norm(cood[:,0]-centroid[::-1])distance2 = np.linalg.norm(cood[:,-1]-centroid[::-1])if distance1 > minCenterDistance or distance2 > minCenterDistance:binaryImage[labels == label] = 0else:breakminRotate = 0minCount = -1(cX, cY) = (maskW // 2, maskH // 2)points = np.column_stack(np.where(binaryImage > 0))[:pointsNum].astype(np.int16)for rotate in range(-angleThres, angleThres):rotatePoints = rotate_points(points, rotate, cX, cY)rotatePoints = np.clip(rotatePoints[:,0], 0, maskH-1)hist, bins = np.histogram(rotatePoints, maskH, [0, maskH])# 横向统计非零元素个数 越少则说明姿态越正zeroCount = np.sum(hist > toWidth/50)if zeroCount <= minCount or minCount == -1:minCount = zeroCountminRotate = rotatereturn minRotatePath = '003.jpg'
cv_img = cv2.imdecode(np.fromfile(Path, dtype=np.uint8), -1)
cv_img = cv2.cvtColor(cv_img, cv2.COLOR_RGB2BGR)for agl in range(-30, 30):img = cv_img.copy()img = rotate_bound(img, agl)angle = findangle(img)img = rotate_bound(img, -angle)angle = findangle(img)cv2.imshow('after', img)key = cv2.waitKey(1) & 0xFF# 按'q'健退出循环if key == ord('q'):break
cv2.destroyAllWindows()plt.imshow(img)
plt.show()

与原图效果进行比较

其他图片的矫正效果

相比较于用直线勘测的方法对图像进行矫正

# 畸变矫正_边缘投影法对文本图像矫正——python相关推荐

  1. python 图像倾斜校正_边缘投影法对文本图像矫正——python

    图像矫正就是通过一些已知的参考点,即无失真图象的某些象素点和畸变图象相应象素的坐标间对应关系,拟合出映射关系中的未知系数,并作为恢复其它象素的基础. 1.矫正原理 在进行图片矫正时,有些图片具有小角度 ...

  2. 大广角镜头 镜头畸变 矫正_如何用广角镜头对焦

    大广角镜头 镜头畸变 矫正 Focusing is easy when you're using an aperture of f/8 or narrower: most things in the ...

  3. # 畸变矫正_别让这个细节毁了你的照片,学会正确进行畸变调整

    相信每一位摄影爱好者都拍过不少图片,由于很多摄影新人对摄影后期不了解,曾经拍摄大量的图片没有进行后期处理,有一些不错的照片原图就被"遗留在角落".趁现在宅家抗疫的期间,我们不妨将曾 ...

  4. python pdf模块_用于将PDF转换为文本的Python模块

    编辑(再次): PDFMiner已在版本中再次更新.20100213 您可以使用以下内容检查已安装的版本:>>> import pdfminer>>> pdfmin ...

  5. c#垂直投影法_投影学

    投影学 题解:本文命名<投影学>,是由于本文讨论投影的一些最基础的问题. 1 投影法 1.1投影的基本概念 投影,是一种通过降维的方法在平面上表示空间形体的办法.在工程上,投影是一种光线照 ...

  6. 文本分割之水平投影法基于OpenCV(python)版实现

    对于如下一张图片,如何将文本区域分割成一行一行的了? 在文本分割领域中有一种很优秀的算法:投影法,包括水平投影法和垂直投影法.本文主要讲述水平投影法,水平投影法可以理解为一束光线从图像的左侧向右边进行 ...

  7. 文本分割之垂直投影法基于OpenCV(python)的实现

    在我的上一篇博客中讲述了水平投影法取出文本行图像的实现,在这里将用垂直投影法对文本行的每个字符进行分割.下图是用水平投影法切割的文本行: 文本分割的原理如下,先用水平投影取出单一文本行,接着使用垂直投 ...

  8. c语言 投影法图像定位,基于抛物线拟合和边缘点搜索的虹膜精确定位

    摘  要: 虹膜的定位包括瞳孔(内圆)和虹膜外圆的定位.该方法首先预判断瞳孔中心和半径截取目标区域小图,然后对目标区域提取边缘采用最小二乘抛物线拟合,算出左右固定区域内边缘点极值点坐标,得到瞳孔初始的 ...

  9. python opencv 摄像头标定_(五)单目摄像头标定与畸变矫正(C++,opencv)

    本文将梳理一种单目摄像头标定和矫正的方法,在梳理的过程中,首先使用网上离线的图片数据跑通流程,然后接入自己的camera,手动采集标定图像,实时矫正相机的畸变,然后输出矫正后的图像.全文基于Openc ...

最新文章

  1. python学习笔记(IO模型)
  2. NARF(Normal Aligned Radial Feature)关键点
  3. 问题 RadioButtonList+TextBox的复合控件如何做
  4. IIS7.0下 HTTP 错误 404.15 - Not Found 请求筛选模块被配置为拒绝包含的查询字符串过长的请求...
  5. HTML 5 的自定义 data-* 属性和jquery的data()方法的使用
  6. EnvironmentError: mysql_config not found
  7. 【Elasticsearch】基于 Elasticsearch + kibana 实现 IP 地址分布地图可视化
  8. python自带网页解析器_Python爬虫Chrome网页解析工具-XPath Helper
  9. Timeout occurred while waiting for latch: class 'ACCESS_METHODS_DATASET_PARENT'
  10. 安卓c语言文档下载,C语言.NET技术09.doc
  11. 基于socket编程的多人聊天室
  12. PIE调用Python获得彩色直方图
  13. 攻防世界misc新手_攻防世界密码学解密
  14. python实现自动打电话软件_python 实现手机自动拨打电话的方法(通话压力测试)
  15. 客户需求分析8个维度_电商数据分析的4大思维和8个指标
  16. LeetCode 打家劫舍题型 解析
  17. 李迟2022年4月工作生活总结
  18. 随机效应模型介绍及实例分析
  19. 深度学习模型提升性能的策略
  20. php5.2.17 pecl,php pecl的使用

热门文章

  1. 简单计算机app inventor,app inventor计算器
  2. ajax传递字符,Ajax怎么传递特殊字符的数据
  3. 华为修改优先级命令_(完整版)华为设备基本配置命令
  4. 2021-06-19 sklearn中的线性回归模型
  5. R语言学习笔记(三)多元数据的数据特征、相关分析与图形表示
  6. 【java基础知识】java.util.LinkedHashMap cannot be cast to com.XXX.XXX
  7. Java代码计算一元二次方程
  8. oppo手机android 版本号,ColorOS新系统定档!紧跟安卓发布,但版本号亮了
  9. 把爬取信息导出到mysql,关于爬虫学习的一些小小记录(四)——爬取数据存入数据库...
  10. c语言课设报告函数的比较,c语言课程设计设计报告函数的调用关系图及主要算法.doc...