数字图像处理 - 实验作业三 - Python

第四章 频率域滤波

滤波器:抑制或最小化某些频率的波或振荡的装置或材料

频率:自变量单位变化期间,一个周期函数重复相同值序列的次数

在开始实验之前,可以先看一下三篇文章了解一下傅里叶变换

什么是傅里叶变换

通俗讲解图像傅里叶变换

如何理解图像傅里叶变换的频谱图

1、实现图像的傅里叶变换,显示其幅度谱的图像(0 频在显示图像的中间位置)

M×N图像的二维离散傅里叶变换的公式为
F ( u , v ) = ∑ x = 0 M − 1 ∑ y = 0 N − 1 f ( x , y ) e − 2 π ( u x M + v y N ) F(u,v)=\sum_{x=0}^{M-1} \sum_{y=0}^{N-1}f(x,y)e^{-2\pi(\frac{ux}{M}+\frac{vy}{N})} F(u,v)=x=0M1y=0N1f(x,y)e2π(Mux+Nvy)

但在实际的实现中,如果自己编写相关的代码,速度是很慢的。可以调用NumPy自带的快速傅里叶变换的方法来显示图像的幅度谱

由于经过傅里叶变换后的图像像素值比较大,所以还需要用对数函数来使之归到0-255之间,中间各个过程的图像如下所示


在频谱中心化后的图像中,中间是低频,四周都是高频未经过频谱中心化的图像则相反
实现的代码如下所示:

import numpy as np
import matplotlib.pyplot as plt
from PIL import Image

img_path = "man.jpg"

src = np.array(Image.open(img_path).convert("L"))

dft_src = np.fft.fft2(src)
log_src = np.log(1 + np.abs(dft_src))
ctr_src = np.fft.fftshift(log_src)
img_list = [src, dft_src, log_src, ctr_src]
img_list_name = ["原图像", "DFT图像", "DFT+对数变换图像", "中心化图像"]

plt.rcParams['font.family'] = ['sans-serif']
plt.rcParams['font.sans-serif'] = ['SimHei']

_, img_xy = plt.subplots(2, 2, figsize=(12, 12))

for i in range(2):
    for j in range(2):
        img_xy[i][j].imshow(np.abs(img_list[i * 2 + j]), cmap="gray")
        img_xy[i][j].set_title(img_list_name[i * 2 + j], size=20)
        img_xy[i][j].axis("off")

plt.show()

2、用理想低通滤波器在频率域实现低通滤波

从这里往下代码重叠度比较高,因为基本原理是相同的

理想低通滤波器(ILPF)的滤波器传递函数为
H ( u , v ) = { 1 D ( u , v ) ≤ D 0 0 D ( u , v ) > D 0 H(u, v)=\left\{\begin{array}{ll} 1 & D(u, v) \leq D_{0} \\ 0 & D(u, v)>D_{0} \end{array}\right. H(u,v)={10D(u,v)D0D(u,v)>D0

D ( u , v ) = [ ( u − M / 2 ) 2 + ( v − N / 2 ) 2 ] 1 / 2 D(u,v)=[(u-M/2)^2+(v-N/2)^2]^{1/2} D(u,v)=[(uM/2)2+(vN/2)2]1/2

将理想低通滤波器其用不同的方式可视化表达出来

在这里插入图片描述

实现的方式:

  1. 对图像做傅里叶变换并使得频谱中心化
  2. 设定滤波的半径,并以图像中心为圆心画圆
  3. 圆内的滤波器值设为1,圆外为0
  4. 逆中心化和逆傅里叶变换

低通滤波得到的结果如下所示
在这里插入图片描述
图中总共设置了5种滤波的半径,可以观察到,低通滤波一是模糊,二是会有振铃效应,出现振铃效应的主要原因是理想滤波器在频域是一个门函数,但是在时域对应的是一个sinc函数,而频域的相乘就是时域的卷积。

时域卷积sinc函数就是对该函数进行搬移与叠加,那自然就有一圈圈波纹产生,也就是我们所谓的振铃效应

理想低通滤波器实现的代码如下所示

import numpy as np
import matplotlib.pyplot as plt
from PIL import Image


def fourier_trans(src):
    """
    fourier transformation
        source: source image
        ctr_src: spectrum after fourier transformation and centralization
        plt_src: spectrum after log transformation
    """
    fft_src = np.fft.fft2(src)
    ctr_src = np.fft.fftshift(fft_src)
    plt_src = np.log(np.abs(ctr_src))

    return ctr_src, plt_src


def inv_fourier_trans(src):
    """
    inverse fourier transformation
        src: spectrums
        ifft_img: the image after inverse fourier transformation
    """
    inv_ctr_img = np.fft.ifftshift(src)
    ifft_img = np.fft.ifft2(inv_ctr_img)

    return ifft_img


def idea_low_pass_filter(source, radius=5):
    """
    LPF
        source: source image
        radius: size for low pass filter
    """
    # get the paras
    filter_radius = radius
    img = source

    # set paras for filter
    height, weight = img.shape
    center_h = int(height / 2)
    center_w = int(weight / 2)

    # initialize filter
    low_pass_filter = np.zeros_like(img)

    # set the low pass area
    for i in range(height):
        for j in range(weight):
            dist_from_center = np.sqrt(np.power((i - center_h), 2) + np.power((j - center_w), 2))
            if dist_from_center < radius:
                low_pass_filter[i][j] = 1

    # filter the image
    filtered_img = np.multiply(img, low_pass_filter)

    return filtered_img


img_path = "man.jpg"
src = np.array(Image.open(img_path).convert("L"))
fft_src, _ = fourier_trans(src)

img_list = [src]
radius_list = ['origin', 5, 15, 30, 50, 100]
for i in radius_list[1:]:
    img_list.append(inv_fourier_trans(idea_low_pass_filter(fft_src, i)))

img_list_name = radius_list

_, img_xy = plt.subplots(2, 3, figsize=(12, 12))

for i in range(2):
    for j in range(3):
        img_xy[i][j].imshow(np.abs(img_list[i * 3 + j]), cmap="gray")
        img_xy[i][j].set_title(img_list_name[i * 3 + j], size=20)
        img_xy[i][j].axis("off")

plt.show()

3、用理想高通滤波器在频率域实现低通滤波

理想高通滤波器(IHPF)滤波器传递函数为
H ( u , v ) = { 0 D ( u , v ) ≤ D 0 1 D ( u , v ) > D 0 H(u, v)=\left\{\begin{array}{ll}0 & D(u, v) \leq D_{0} \\1 & D(u, v)>D_{0}\end{array}\right. H(u,v)={01D(u,v)D0D(u,v)>D0

D ( u , v ) = [ ( u − M / 2 ) 2 + ( v − N / 2 ) 2 ] 1 / 2 D(u,v)=[(u-M/2)^2+(v-N/2)^2]^{1/2} D(u,v)=[(uM/2)2+(vN/2)2]1/2

将理想高通滤波器用不同的方式可视化表达出来

在这里插入图片描述

实现的方式:

  1. 对图像做傅里叶变换并使得频谱中心化
  2. 设定滤波的半径,并以图像中心为圆心画圆
  3. 圆内的滤波器值设为0,圆外为1
  4. 逆中心化和逆傅里叶变换

实现的效果如下所示:

在这里插入图片描述

实现的代码如下所示:

import numpy as np
import matplotlib.pyplot as plt
from PIL import Image


def fourier_trans(src):
    """
    fourier transformation
        source: source image
        ctr_src: spectrum after fourier transformation and centralization
        plt_src: spectrum after log transformation
    """
    fft_src = np.fft.fft2(src)
    ctr_src = np.fft.fftshift(fft_src)
    plt_src = np.log(np.abs(ctr_src))

    return ctr_src, plt_src


def inv_fourier_trans(src):
    """
    inverse fourier transformation
        src: spectrums
        ifft_img: the image after inverse fourier transformation
    """
    inv_ctr_img = np.fft.ifftshift(src)
    ifft_img = np.fft.ifft2(inv_ctr_img)

    return ifft_img


def idea_high_pass_filter(source, radius=5):
    """
    HPF
        source: source image
        radius: size for High pass filter
    """
    # get the paras
    filter_radius = radius
    img = source

    # set paras for filter
    height, weight = img.shape
    center_h = int(height / 2)
    center_w = int(weight / 2)

    # initialize filter
    high_pass_filter = np.ones_like(img)

    # set the high pass area
    for i in range(height):
        for j in range(weight):
            dist_from_center = np.sqrt(np.power((i - center_h), 2) + np.power((j - center_w), 2))

            if dist_from_center < radius:
                high_pass_filter[i][j] = 0

    # filter the image
    filtered_img = np.multiply(img, high_pass_filter)

    return filtered_img


img_path = "man.jpg"
src = np.array(Image.open(img_path).convert("L"))
fft_src, _ = fourier_trans(src)

img_list = [src]
radius_list = ['origin', 5, 15, 30, 50, 100]
for i in radius_list[1:]:
    img_list.append(inv_fourier_trans(idea_high_pass_filter(fft_src, i)))

img_list_name = radius_list

_, img_xy = plt.subplots(2, 3, figsize=(12, 12))

for i in range(2):
    for j in range(3):
        img_xy[i][j].imshow(np.abs(img_list[i * 3 + j]), cmap="gray")
        img_xy[i][j].set_title(img_list_name[i * 3 + j], size=20)
        img_xy[i][j].axis("off")

plt.show()

4、用巴特沃斯低通滤波器和高斯低通滤波器实现图像的低通滤波

4.1 巴特沃斯低通滤波器

巴特沃斯低通滤波器(BLPF)滤波器传递函数为
H ( u , v ) = 1 1 + [ D ( u , v ) / D 0 ] 2 n H(u, v)=\frac{1}{1+\left[D(u, v) / D_{0}\right]^{2 n}} H(u,v)=1+[D(u,v)/D0]2n1

D ( u , v ) = [ ( u − M / 2 ) 2 + ( v − N / 2 ) 2 ] 1 / 2 D(u,v)=[(u-M/2)^2+(v-N/2)^2]^{1/2} D(u,v)=[(uM/2)2+(vN/2)2]1/2

将巴特沃斯低通滤波器用不同的方式可视化表达出来

在这里插入图片描述

实现的效果如下所示(采用2阶巴特沃斯低通滤波器):

在这里插入图片描述

观察可以发现,巴特沃斯低通滤波器虽然依然有模糊,但基本上可以说没有振铃效应

观察不同阶数的巴特沃斯低通滤波器的空间表示(从左到右分别是1阶,2阶,5阶,),可以发现(低阶)“振”的部分减少了,虽然1阶不存在振铃效应,但是低通性不好,所以之前的实现采用了2阶,振铃效应也是基本不可见

在这里插入图片描述

但是高阶的巴特沃斯低通滤波器依然有,比如以下的20阶巴特沃斯低通滤波器

在这里插入图片描述

实现的代码如下所示

import numpy as np
import matplotlib.pyplot as plt
from PIL import Image


def fourier_trans(src):
    """
    fourier transformation
        source: source image
        ctr_src: spectrum after fourier transformation and centralization
        plt_src: spectrum after log transformation
    """
    fft_src = np.fft.fft2(src)
    ctr_src = np.fft.fftshift(fft_src)
    plt_src = np.log(np.abs(ctr_src))

    return ctr_src, plt_src


def inv_fourier_trans(src):
    """
    inverse fourier transformation
        src: spectrums
        ifft_img: the image after inverse fourier transformation
    """
    inv_ctr_img = np.fft.ifftshift(src)
    ifft_img = np.fft.ifft2(inv_ctr_img)

    return ifft_img


def butterworth_low_pass_filter(source, radius=5, order=1):
    # get the paras
    filter_radius = radius
    img = source

    # set paras for filter
    height, weight = img.shape
    center_h = int(height / 2)
    center_w = int(weight / 2)

    # initialize filter
    butterworth_low_pass_filter = np.zeros_like(img)

    # set the pass area
    for i in range(height):
        for j in range(weight):
            dist_from_center = np.sqrt(np.power((i - center_h), 2) + np.power((j - center_w), 2))
            butterworth_low_pass_filter[i][j] = 1 / (1 + np.power(dist_from_center / radius, 2 * order))

    # filter the image
    filtered_img = np.multiply(img, butterworth_low_pass_filter)

    return filtered_img


img_path = "man.jpg"
src = np.array(Image.open(img_path).convert("L"))
fft_src, _ = fourier_trans(src)

img_list = [src]
radius_list = ['origin', 5, 15, 30, 50, 100]
for i in radius_list[1:]:
    img_list.append(inv_fourier_trans(butterworth_low_pass_filter(fft_src, i, 2)))

img_list_name = radius_list

_, img_xy = plt.subplots(2, 3, figsize=(12, 12))

for i in range(2):
    for j in range(3):
        img_xy[i][j].imshow(np.abs(img_list[i * 3 + j]), cmap="gray")
        img_xy[i][j].set_title(img_list_name[i * 3 + j], size=20)
        img_xy[i][j].axis("off")

plt.show()

4.2 高斯低通滤波器

高斯低通滤波器(GLPF)滤波器传递函数为
H ( u , v ) = e − D 2 ( u , v ) / 2 D 0 2 H(u, v)=e^{-D^{2}(u, v) / 2 D_{0}^{2}} H(u,v)=eD2(u,v)/2D02

D ( u , v ) = [ ( u − M / 2 ) 2 + ( v − N / 2 ) 2 ] 1 / 2 D(u,v)=[(u-M/2)^2+(v-N/2)^2]^{1/2} D(u,v)=[(uM/2)2+(vN/2)2]1/2

将高斯低通滤波器其用不同的方式可视化表达出来

在这里插入图片描述

实现的效果如下所示:

在这里插入图片描述

可以观察到,高斯低通滤波器同样是模糊但是没有振铃效应

实现的代码如下所示:

import numpy as np
import matplotlib.pyplot as plt
from PIL import Image


def fourier_trans(src):
    """
    fourier transformation
        source: source image
        ctr_src: spectrum after fourier transformation and centralization
        plt_src: spectrum after log transformation
    """
    fft_src = np.fft.fft2(src)
    ctr_src = np.fft.fftshift(fft_src)
    plt_src = np.log(np.abs(ctr_src))

    return ctr_src, plt_src


def inv_fourier_trans(src):
    """
    inverse fourier transformation
        src: spectrums
        ifft_img: the image after inverse fourier transformation
    """
    inv_ctr_img = np.fft.ifftshift(src)
    ifft_img = np.fft.ifft2(inv_ctr_img)

    return ifft_img


def guass_low_pass_filter(source, radius=5):
    # get the paras
    filter_radius = radius
    img = source

    # set paras for filter
    height, weight = img.shape
    center_h = int(height / 2)
    center_w = int(weight / 2)

    # initialize filter
    guass_low_pass_filter = np.zeros_like(img)

    # set the pass area
    for i in range(height):
        for j in range(weight):
            dist_from_center = np.sqrt(np.power((i - center_h), 2) + np.power((j - center_w), 2))
            guass_low_pass_filter[i][j] = np.exp(-(np.power(dist_from_center, 2) / np.power(radius, 2)))

    # filter the image
    filtered_img = np.multiply(img, guass_low_pass_filter)

    return filtered_img


img_path = "man.jpg"
src = np.array(Image.open(img_path).convert("L"))
fft_src, _ = fourier_trans(src)

img_list = [src]
radius_list = ['origin', 5, 15, 30, 50, 100]
for i in radius_list[1:]:
    img_list.append(inv_fourier_trans(guass_low_pass_filter(fft_src, i)))

img_list_name = radius_list

_, img_xy = plt.subplots(2, 3, figsize=(12, 12))

for i in range(2):
    for j in range(3):
        img_xy[i][j].imshow(np.abs(img_list[i * 3 + j]), cmap="gray")
        img_xy[i][j].set_title(img_list_name[i * 3 + j], size=20)
        img_xy[i][j].axis("off")

plt.show()

5、用巴特沃斯高通滤波器和高斯高通滤波器实现图像的高频增强

5.1 巴特沃斯高通滤波器

巴特沃斯高通滤波器(BHPF)滤波器传递函数为
H ( u , v ) = 1 1 + [ D 0 / D ( u , v ) / ] 2 n H(u, v)=\frac{1}{1+\left[D_{0}/D(u, v) / \right]^{2 n}} H(u,v)=1+[D0/D(u,v)/]2n1

D ( u , v ) = [ ( u − M / 2 ) 2 + ( v − N / 2 ) 2 ] 1 / 2 D(u,v)=[(u-M/2)^2+(v-N/2)^2]^{1/2} D(u,v)=[(uM/2)2+(vN/2)2]1/2

将巴特沃斯高通滤波器用不同的方式可视化表达出来

在这里插入图片描述

实现的效果如下所示:

在这里插入图片描述

实现的代码如下所示:

import numpy as np
import matplotlib.pyplot as plt
from PIL import Image


def fourier_trans(src):
    """
    fourier transformation
        source: source image
        ctr_src: spectrum after fourier transformation and centralization
        plt_src: spectrum after log transformation
    """
    fft_src = np.fft.fft2(src)
    ctr_src = np.fft.fftshift(fft_src)
    plt_src = np.log(np.abs(ctr_src))

    return ctr_src, plt_src


def inv_fourier_trans(src):
    """
    inverse fourier transformation
        src: spectrums
        ifft_img: the image after inverse fourier transformation
    """
    inv_ctr_img = np.fft.ifftshift(src)
    ifft_img = np.fft.ifft2(inv_ctr_img)

    return ifft_img


def butterworth_high_pass_filter(source, radius=5, order=2):
    # get the paras
    filter_radius = radius
    img = source

    # set paras for filter
    height, weight = img.shape
    center_h = int(height / 2)
    center_w = int(weight / 2)

    # initialize filter
    butterworth_high_pass_filter = np.zeros_like(img)

    # set the pass area
    for i in range(height):
        for j in range(weight):
            dist_from_center = np.sqrt(np.power((i - center_h), 2) + np.power((j - center_w), 2))
            if dist_from_center != 0:
                butterworth_high_pass_filter[i][j] = 1 / (1 + np.power(radius / dist_from_center, 2 * order))
    # filter the image
    filtered_img = np.multiply(img, butterworth_high_pass_filter)

    return filtered_img


img_path = "man.jpg"
src = np.array(Image.open(img_path).convert("L"))
fft_src, _ = fourier_trans(src)

img_list = [src]
radius_list = ['origin', 5, 15, 30, 50, 100]
for i in radius_list[1:]:
    img_list.append(inv_fourier_trans(butterworth_high_pass_filter(fft_src, i)))

img_list_name = radius_list

_, img_xy = plt.subplots(2, 3, figsize=(12, 12))

for i in range(2):
    for j in range(3):
        img_xy[i][j].imshow(np.abs(img_list[i * 3 + j]), cmap="gray")
        img_xy[i][j].set_title(img_list_name[i * 3 + j], size=20)
        img_xy[i][j].axis("off")

plt.show()

5.2 高斯高通滤波器

高斯高通滤波器(GHPF)滤波器传递函数为
H ( u , v ) = 1 − e − D 2 ( u , v ) / 2 D 0 2 H(u, v)=1-e^{-D^{2}(u, v) / 2 D_{0}^{2}} H(u,v)=1eD2(u,v)/2D02

D ( u , v ) = [ ( u − M / 2 ) 2 + ( v − N / 2 ) 2 ] 1 / 2 D(u,v)=[(u-M/2)^2+(v-N/2)^2]^{1/2} D(u,v)=[(uM/2)2+(vN/2)2]1/2

将高斯高通滤波器用不同的方式可视化表达出来

在这里插入图片描述

实现的效果如下所示

在这里插入图片描述

至此,三种高通滤波器(理想、巴特沃兹,高通)都已经表示了出来,他们的空间表示如下所示(与前面顺序对应),可以看出三者在振铃效应上的区别

在这里插入图片描述

实现的代码如下所示

import numpy as np
import matplotlib.pyplot as plt
from PIL import Image


def fourier_trans(src):
    """
    fourier transformation
        source: source image
        ctr_src: spectrum after fourier transformation and centralization
        plt_src: spectrum after log transformation
    """
    fft_src = np.fft.fft2(src)
    ctr_src = np.fft.fftshift(fft_src)
    plt_src = np.log(np.abs(ctr_src))

    return ctr_src, plt_src


def inv_fourier_trans(src):
    """
    inverse fourier transformation
        src: spectrums
        ifft_img: the image after inverse fourier transformation
    """
    inv_ctr_img = np.fft.ifftshift(src)
    ifft_img = np.fft.ifft2(inv_ctr_img)

    return ifft_img

def guass_high_pass_filter(source, radius = 5):
    # get the paras
    filter_radius = radius
    img = source
    
    # set paras for filter
    height,weight = img.shape
    center_h = int(height/2)
    center_w = int(weight/2)
    
    # initialize filter
    guass_high_pass_filter = np.zeros_like(img)
    
    # set the pass area
    for i in range(height):
        for j in range(weight):
            dist_from_center = np.sqrt(np.power((i-center_h),2) + np.power((j-center_w),2))
            guass_high_pass_filter[i][j] = 1 - np.exp(-(np.power(dist_from_center,2)/np.power(radius,2)))
    
    # filter the image
    filtered_img = np.multiply(img, guass_high_pass_filter)
    
    return filtered_img

img_path = "man.jpg"
src = np.array(Image.open(img_path).convert("L"))
fft_src, _ = fourier_trans(src)

img_list = [src]
radius_list = ['origin', 5, 15, 30, 50, 100]
for i in radius_list[1:]:
    img_list.append(inv_fourier_trans(guass_high_pass_filter(fft_src, i)))

img_list_name = radius_list

_, img_xy = plt.subplots(2, 3, figsize=(12, 12))

for i in range(2):
    for j in range(3):
        img_xy[i][j].imshow(np.abs(img_list[i * 3 + j]), cmap="gray")
        img_xy[i][j].set_title(img_list_name[i * 3 + j], size=20)
        img_xy[i][j].axis("off")

plt.show()
  • 15
    点赞
  • 61
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值