使用 OpenCV 和 PaddleOCR 自动纠正图像中的文本倾斜

前言

在日常工作中,我们经常需要从扫描的文档图片中提取文本数据,并转换成规范格式的Excel和文本文件。然而,由于部分图片来源于扫描仪,它们往往带有不同程度的倾斜,这严重影响了文本识别的准确性和后续处理的效率。传统的图像处理方法虽多,但常常难以达到理想的矫正效果。

面对这一挑战,我灵光一现,想到了使用 PaddleOCR 来识别图片中的文本位置,其返回结果包括文本的四个角点,这让计算文本的倾斜角度成为可能。有了这些角度信息,我可以使用 OpenCV 进行精确的图像旋转,以矫正文本的倾斜。实践证明,这种方法不仅提高了文本识别的准确性,也极大地优化了整个文件处理流程。

完整代码

import math

import os

import cv2

import numpy as np

import paddlehub as hub

def calculate_angle(point1, point2):

"""

计算两点构成的斜线与水平线的夹角。

参数:

point1 (list): 第一个点的坐标 [x1, y1]

point2 (list): 第二个点的坐标 [x2, y2]

返回:

float: 两点之间的角度,正值表示第二个点在第一个点上方,负值表示在下方。

"""

# 计算水平和垂直距离

dx = point2[0] - point1[0]

dy = point2[1] - point1[1]

# 使用atan2计算角度(返回值是弧度)

angle_rad = math.atan2(dy, dx)

# 将弧度转换为度

angle_deg = math.degrees(angle_rad)

# 根据y坐标判断返回正角度还是负角度

if dy < 0:

# 第二个点在第一个点的下方

return -abs(angle_deg)

else:

# 第二个点在第一个点的上方或同一水平线上

return abs(angle_deg)

def rotate_image_without_cropping(img, angle, scale=1.0):

(h, w) = img.shape[:2]

center = (w // 2, h // 2)

# 计算旋转矩阵(考虑不裁剪的情况)

M = cv2.getRotationMatrix2D(center, angle, scale)

# 计算旋转后图像的新边界

cos = np.abs(M[0, 0])

sin = np.abs(M[0, 1])

# 新的边界尺寸

nW = int((h * sin) + (w * cos))

nH = int((h * cos) + (w * sin))

# 调整旋转矩阵以考虑平移

M[0, 2] += (nW / 2) - center[0]

M[1, 2] += (nH / 2) - center[1]

# 旋转整个图像

rotated = cv2.warpAffine(img, M, (nW, nH))

return rotated

def rotate_image(img, angle):

# 获取图像维度和中心点

(h, w) = img.shape[:2]

center = (w // 2, h // 2)

# 计算旋转矩阵

M = cv2.getRotationMatrix2D(center, angle, 1.0) # 旋转中心,旋转角度,缩放因子

# 执行旋转

rotated_img = cv2.warpAffine(img, M, (w, h))

return rotated_img

if __name__=="__main__":

# 图片所在文件夹的路径

folder_path = r'.\img'

# mkldnn加速仅在CPU下有效 引入ocr深度学习模型

ocr = hub.Module(name="ch_pp-ocrv3", enable_mkldnn=True)

offset = 0

# 遍历文件夹中的所有文件

for filename in os.listdir(folder_path):

if filename.endswith('.jpg') or filename.endswith('.png'):

# 打开图片文件

image_path = os.path.join(folder_path, filename)

img = cv2.imread(image_path)

# 获取图片宽高

height, width, = img.shape[:2]

#识别文字

results = ocr.recognize_text(images=[img])

angleTotal=0

angleNum = 0

# img_rect=img

for result in results:

data = result['data']

angleNum=len(data)

for infomation in data:

# img_rect=cv2.rectangle(img_rect,infomation['text_box_position'][0],infomation['text_box_position'][2],(255,0,0),2)

angleTotal+=calculate_angle(infomation['text_box_position'][0],infomation['text_box_position'][1])

# angleTotal+=calculate_angle(infomation['text_box_position'][2],infomation['text_box_position'][3])

# print(infomation['text_box_position'][0][0],infomation['text_box_position'][1][0])

angle=angleTotal/(angleNum)

img=rotate_image(img,angle)

# cv2.imwrite(r"./rect/" +filename, img_rect)

cv2.imwrite(r"./rotate/" +filename, img)

print(angle)

print(image_path)

效果

以下是旋转前后对比,效果我还是很满意。

总结

通过结合 PaddleOCR 的高效文本检测功能与 OpenCV 的强大图像处理能力,本方法有效解决了扫描图像文本倾斜的问题。这不仅使得从图像到文本的转换更加高效、准确,还大大提升了后续数据处理的流畅性。实际应用中,该技术表现出了优越的性能和广泛的适用性,为类似的图像处理任务提供了一个可靠的解决方案。

希望这篇博客能激发更多同行在面对图像处理挑战时,采用创新的解决方案。对于想要深入了解和应用这些技术的朋友,我建议亲自动手实验不同类型的图像样本,以获得更全面的经验和理解,转载请附明出处。