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

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

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值