前言
在日常工作中,我们经常需要从扫描的文档图片中提取文本数据,并转换成规范格式的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 的强大图像处理能力,本方法有效解决了扫描图像文本倾斜的问题。这不仅使得从图像到文本的转换更加高效、准确,还大大提升了后续数据处理的流畅性。实际应用中,该技术表现出了优越的性能和广泛的适用性,为类似的图像处理任务提供了一个可靠的解决方案。
希望这篇博客能激发更多同行在面对图像处理挑战时,采用创新的解决方案。对于想要深入了解和应用这些技术的朋友,我建议亲自动手实验不同类型的图像样本,以获得更全面的经验和理解,转载请附明出处。