0
点赞
收藏
分享

微信扫一扫

【OpenCV 完整例程】83. 频率域低通滤波:印刷文本字符修复

【OpenCV 完整例程】83. 频率域低通滤波案例:印刷文本字符修复


3.5 频率域低通滤波:印刷文本字符修复

低通滤波技术主要应用于印刷和出版业。本节给出频率域低通滤波的实际应用:印刷文本的字符修复,案例来自冈萨雷斯《数字图像处理(第四版)》P194 图 4.48。

原始图像是一幅低分辨率文本图像的样本,我们会在传真、复印或历史文档中遇到这样的文本。图片中的文本不存在污迹、折痕和撕裂,但文本中的字符因分辨率不足而产生的失真,其中许多字符是断开的。解决这个问题的一种方法是,通过模糊输入图像来桥接这些小缝隙。

例程显示了使用不同 D 0 D_0 D0 的高斯低通滤波器简单处理后的修复效果。当然这只是修复的一个步骤,接下来还要进行其它处理如阈值处理、细化处理,这些方法将在后续内容讨论。

为了方便今后的使用,例程将最优扩充的快速傅立叶变换、高斯低通滤波器封装为函数。


例程 8.22:GLPF 低通滤波案例:印刷文本字符修复 (Text character recognition)

# OpenCVdemo08.py
# Demo08 of OpenCV
# 8. 图像的频率域滤波
# Copyright 2021 Youcans, XUPT
# Crated:2021-12-15
   
# 8.22:GLPF 低通滤波案例:印刷文本字符修复 (Text character recognition)
    def gaussLowPassFilter(shape, radius=10):  # 高斯低通滤波器
        # 高斯滤波器:# Gauss = 1/(2*pi*s2) * exp(-(x**2+y**2)/(2*s2))
        u, v = np.mgrid[-1:1:2.0/shape[0], -1:1:2.0/shape[1]]
        D = np.sqrt(u**2 + v**2)
        D0 = radius / shape[0]
        kernel = np.exp(- (D ** 2) / (2 *D0**2))
        return kernel

    def dft2Image(image):  # 最优扩充的快速傅立叶变换
        # 中心化, centralized 2d array f(x,y) * (-1)^(x+y)
        mask = np.ones(image.shape)
        mask[1::2, ::2] = -1
        mask[::2, 1::2] = -1
        fImage = image * mask  # f(x,y) * (-1)^(x+y)

        # 最优 DFT 扩充尺寸
        rows, cols = image.shape[:2]  # 原始图片的高度和宽度
        rPadded = cv2.getOptimalDFTSize(rows)  # 最优 DFT 扩充尺寸
        cPadded = cv2.getOptimalDFTSize(cols)  # 用于快速傅里叶变换

        # 边缘扩充(补0), 快速傅里叶变换
        dftImage = np.zeros((rPadded, cPadded, 2), np.float32)  # 对原始图像进行边缘扩充
        dftImage[:rows, :cols, 0] = fImage  # 边缘扩充,下侧和右侧补0
        cv2.dft(dftImage, dftImage, cv2.DFT_COMPLEX_OUTPUT)  # 快速傅里叶变换
        return dftImage


    # (1) 读取原始图像
    imgGray = cv2.imread("../images/Fig0419a.tif", flags=0)  # flags=0 读取为灰度图像
    rows, cols = imgGray.shape[:2]  # 图片的高度和宽度

    plt.figure(figsize=(10, 6))
    plt.subplot(2, 3, 1), plt.title("Original"), plt.axis('off'), plt.imshow(imgGray, cmap='gray')

    # (2) 快速傅里叶变换
    dftImage = dft2Image(imgGray)  # 快速傅里叶变换 (rPad, cPad, 2)
    rPadded, cPadded = dftImage.shape[:2]  # 快速傅里叶变换的尺寸, 原始图像尺寸优化
    print("dftImage.shape:{}".format(dftImage.shape))


    D0 = [10, 30, 60, 90, 120]  # radius
    for k in range(5):
        # (3) 构建 高斯低通滤波 (Gauss low pass filter)
        lpFilter = gaussLowPassFilter((rPadded, cPadded), radius=D0[k])

        # (5) 在频率域修改傅里叶变换: 傅里叶变换 点乘 低通滤波器
        dftLPfilter = np.zeros(dftImage.shape, dftImage.dtype)  # 快速傅里叶变换的尺寸(优化尺寸)
        for j in range(2):
            dftLPfilter[:rPadded, :cPadded, j] = dftImage[:rPadded, :cPadded, j] * lpFilter

        # (6) 对低通傅里叶变换 执行傅里叶逆变换,并只取实部
        idft = np.zeros(dftImage.shape[:2], np.float32)  # 快速傅里叶变换的尺寸(优化尺寸)
        cv2.dft(dftLPfilter, idft, cv2.DFT_REAL_OUTPUT + cv2.DFT_INVERSE + cv2.DFT_SCALE)

        # (7) 中心化, centralized 2d array g(x,y) * (-1)^(x+y)
        mask2 = np.ones(dftImage.shape[:2])
        mask2[1::2, ::2] = -1
        mask2[::2, 1::2] = -1
        idftCen = idft * mask2  # g(x,y) * (-1)^(x+y)

        # (8) 截取左上角,大小和输入图像相等
        result = np.clip(idftCen, 0, 255)  # 截断函数,将数值限制在 [0,255]
        imgLPF = result.astype(np.uint8)
        imgLPF = imgLPF[:rows, :cols]

        plt.subplot(2,3,k+2), plt.title("GLPF rebuild(n={})".format(D0[k])), plt.axis('off')
        plt.imshow(imgLPF, cmap='gray')

    print("image.shape:{}".format(imgGray.shape))
    print("lpFilter.shape:{}".format(lpFilter.shape))
    print("dftImage.shape:{}".format(dftImage.shape))

    plt.tight_layout()
    plt.show()

在这里插入图片描述


(本节完)


版权声明:

youcans@xupt 原创作品,转载必须标注原文链接:【OpenCV 完整例程】82. 频率域巴特沃斯低通滤波器

Copyright 2021 youcans, XUPT

Crated:2022-1-25


举报

相关推荐

0 条评论