第5章 Python 数字图像处理(DIP) - 图像复原与重建12 - 空间滤波 - 使用频率域滤波降低周期噪声 - 陷波滤波、最优陷波滤波

本章陷波滤波器有部分得出的结果不佳,如果有更好的解决方案,请赐教,不胜感激。

使用频率域滤波降低周期噪声

陷波滤波深入介绍

零相移滤波器必须关于原点(频率矩形中心)对称,中以为 ( u 0 , v 0 ) (u_0, v_0) (u0,v0)的陷波滤波器传递函数在 ( − u 0 , − v 0 ) (-u_0, -v_0) (u0,v0)位置必须有一个对应的陷波。陷波带阻滤波器传递函数可用中心被平移到陷波滤波中心的高通滤波器函数的乘积来产生

H N R ( u , v ) = ∏ k = 1 Q H k ( u , v ) H − k ( u , v ) (5.33) H_{NR}(u, v) = \prod_{k=1}^Q H_k(u, v) H_{-k}(u, v) \tag{5.33} HNR(u,v)=k=1QHk(u,v)Hk(u,v)(5.33)

每个滤波器的距离计算公式为
D k ( u , v ) = [ ( u − M / 2 − u k ) 2 + ( v − N / 2 − v k ) 2 ] 1 / 2 (5.34) D_{k}(u, v) = \big[(u - M / 2 - u_{k})^2 + (v - N / 2 - v_{k})^2 \big]^{1/2} \tag{5.34} Dk(u,v)=[(uM/2uk)2+(vN/2vk)2]1/2(5.34)
D − k ( u , v ) = [ ( u − M / 2 + u k ) 2 + ( v − N / 2 + v k ) 2 ] 1 / 2 (5.35) D_{-k}(u, v) = \big[(u - M / 2 + u_{k})^2 + (v - N / 2 + v_{k})^2 \big]^{1/2} \tag{5.35} Dk(u,v)=[(uM/2+uk)2+(vN/2+vk)2]1/2(5.35)

3个 n n n阶巴特沃斯带阻滤波器
H N R ( u , v ) = ∏ k = 1 3 [ 1 1 + [ D 0 k / D k ( u , v ) ] n ] [ 1 1 + [ D 0 k / D − k ( u , v ) ] n ] (5.36) H_{NR}(u, v) = \prod_{k=1}^3\bigg[ \frac{1}{1 + [D_{0k}/D_{k}(u,v)]^n} \bigg] \bigg[ \frac{1}{1 + [D_{0k}/D_{-k}(u,v)]^n} \bigg] \tag{5.36} HNR(u,v)=k=13[1+[D0k/Dk(u,v)]n1][1+[D0k/Dk(u,v)]n1](5.36)

常数 D 0 k D_{0k} D0k对每对陷波是相同的,但对不同的陷波对,它可以不同。

陷波带通滤波器传递函数可用陷波带阻滤波器得到
H N P ( u , v ) = 1 − H N R ( u , v ) (5.37) H_{NP}(u, v) = 1 - H_{NR}(u, v) \tag{5.37} HNP(u,v)=1HNR(u,v)(5.37)

def butterworth_notch_resistant_filter(img, uk, vk, radius=10, n=1):
    """
    create butterworth notch resistant filter, equation 4.155
    param: img:    input, source image
    param: uk:     input, int, center of the height
    param: vk:     input, int, center of the width
    param: radius: input, int, the radius of circle of the band pass filter, default is 10
    param: w:      input, int, the width of the band of the filter, default is 5
    param: n:      input, int, order of the butter worth fuction, 
    return a [0, 1] value butterworth band resistant filter
    """   
    M, N = img.shape[1], img.shape[0]
    
    u = np.arange(M)
    v = np.arange(N)
    
    u, v = np.meshgrid(u, v)
    
    DK = np.sqrt((u - M//2 - uk)**2 + (v - N//2 - vk)**2)
    D_K = np.sqrt((u - M//2 + uk)**2 + (v - N//2 + vk)**2)
    D0 = radius
    kernel = (1 / (1 + (D0 / (DK+1e-5))**n)) * (1 / (1 + (D0 / (D_K+1e-5))**n))
    
    return kernel
def idea_notch_resistant_filter(source, uk, vk, radius=5):
    """
    create idea notch resistant filter 
    param: source: input, source image
    param: uk:     input, int, center of the height
    param: vk:     input, int, center of the width
    param: radius: input, the radius of the lowest value, greater value, bigger blocker out range, if the radius is 0, then all
                   value is 0
    return a [0, 1] value filter
    """
    M, N = source.shape[1], source.shape[0]
    
    u = np.arange(M)
    v = np.arange(N)
    
    u, v = np.meshgrid(u, v)
    
    DK = np.sqrt((u - M//2 - uk)**2 + (v - N//2 - vk)**2)
    D_K = np.sqrt((u - M//2 + uk)**2 + (v - N//2 + vk)**2)
    D0 = radius
    k_1 = DK.copy()
    k_2 = D_K.copy()
    
    k_1[DK > D0] = 1
    k_1[DK <= D0] = 0
    
    k_2[D_K > D0] = 1
    k_2[D_K <= D0] = 0
    
    kernel = k_1 * k_2
    
    return kernel
def gauss_notch_resistant_filter(source, uk, vk, radius=5):
    """
    create gauss low pass filter 
    param: source: input, source image
    param: uk:     input, int, center of the height
    param: vk:     input, int, center of the width
    param: radius: input, the radius of the lowest value, greater value, bigger blocker out range, if the radius is 0, then all
                   value is 0
    return a [0, 1] value filter
    """    
    M, N = source.shape[1], source.shape[0]
    
    u = np.arange(M)
    v = np.arange(N)
    
    u, v = np.meshgrid(u, v)
    
    DK = np.sqrt((u - M//2 - uk)**2 + (v - N//2 - vk)**2)
    D_K = np.sqrt((u - M//2 + uk)**2 + (v - N//2 + vk)**2)
    D0 = radius
    
    k_1 = 1 - np.exp(- (DK**2)/(D0**2))   
    k_2 = 1 - np.exp(- (D_K**2)/(D0**2))   
    
    kernel = k_1 * k_2
    return kernel
def plot_3d(ax, x, y, z, cmap):
    ax.plot_surface(x, y, z, antialiased=True, shade=True, cmap=cmap)
    ax.view_init(20, -20), ax.grid(b=False), ax.set_xticks([]), ax.set_yticks([]), ax.set_zticks([])
# 理想、高斯、巴特沃斯陷波滤波器
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
from matplotlib import pyplot as plt
from matplotlib import cm

img_temp = np.zeros([256, 256])

INRF = idea_notch_resistant_filter(img_temp, radius=20, uk=30, vk=80)
GNRF = gauss_notch_resistant_filter(img_temp, radius=20, uk=30, vk=80)
BNRF = butterworth_notch_resistant_filter(img_temp, radius=20, uk=30, vk=80, n=5)

# 用来绘制3D图
M, N = img_temp.shape[1], img_temp.shape[0]
u = np.arange(M)
v = np.arange(N)
u, v = np.meshgrid(u, v)

fig = plt.figure(figsize=(21, 7))
ax_1 = fig.add_subplot(1, 3, 1, projection='3d')
plot_3d(ax_1, u, v, INRF, cmap=cm.plasma)

ax_1 = fig.add_subplot(1, 3, 2, projection='3d')
plot_3d(ax_1, u, v, GNRF, cmap=cm.PiYG)

ax_1 = fig.add_subplot(1, 3, 3, projection='3d')
plot_3d(ax_1, u, v, BNRF, cmap=cm.PiYG)
plt.tight_layout()
plt.show()

在这里插入图片描述

def centralized_2d(arr):
    """
    centralized 2d array $f(x, y) (-1)^{x + y}$, about 4.5 times faster than index, 160 times faster than loop,
    """
    
    def get_1_minus1(img):
        """
        get 1 when image index is even, -1 while index is odd, same shape as input image, need this array to multiply with input image
        to get centralized image for DFT
        Parameter: img: input, here we only need img shape to create the array
        return such a [[1, -1, 1], [-1, 1, -1]] array, example is 3x3
        """
        dst = np.ones(img.shape)
        dst[1::2, ::2] = -1
        dst[::2, 1::2] = -1
        return dst

    #==================中心化=============================
    mask = get_1_minus1(arr)
    dst = arr * mask

    return dst
def pad_image(img, mode='constant'):
    """
    pad image into PxQ shape, orginal is in the top left corner.
    param: img: input image
    param: mode: input, str, is numpy pad parameter, default is 'constant'. for more detail please refere to Numpy pad
    return PxQ shape image padded with zeros or other values
    """
    dst = np.pad(img, ((0, img.shape[0]), (0, img.shape[1])), mode=mode)
    return dst    
def add_sin_noise(img, scale=1, angle=0):
    """
    add sin noise for image
    param: img: input image, 1 channel, dtype=uint8
    param: scale: sin scaler, smaller than 1, will enlarge, bigger than 1 will shrink
    param: angle: angle of the rotation
    return: output_img: output image is [0, 1] image which you could use as mask or any you want to
    """
    
    height, width = img.shape[:2]  # original image shape
    
    # convert all the angle
    if int(angle / 90) % 2 == 0:
        rotate_angle = angle % 90
    else:
        rotate_angle = 90 - (angle % 90)
    
    rotate_radian = np.radians(rotate_angle)    # convert angle to radian
    
    # get new image height and width
    new_height = int(np.ceil(height * np.cos(rotate_radian) + width * np.sin(rotate_radian)))
    new_width = int(np.ceil(width * np.cos(rotate_radian) + height * np.sin(rotate_radian))) 
    
    # if new height or new width less than orginal height or width, the output image will be not the same shape as input, here set it right
    if new_height < height:
        new_height = height
    if new_width < width:
        new_width = width
    
    # meshgrid
    u = np.arange(new_width)
    v = np.arange(new_height)
    u, v = np.meshgrid(u, v)
    
    # get sin noise image, you could use scale to make some difference, better you could add some shift
#     noise = abs(np.sin(u * scale))
    noise = 1 - np.sin(u * scale)
    
    # here use opencv to get rotation, better write yourself rotation function
    C1 = cv2.getRotationMatrix2D((new_width/2.0, new_height/2.0), angle, 1)
    new_img = cv2.warpAffine(noise, C1, (int(new_width), int(new_height)), borderValue=0)
      
    # ouput image should be the same shape as input, so caculate the offset the output image and the new image
    # I make new image bigger so that it will cover all output image
    
    offset_height = abs(new_height - height) // 2
    offset_width = abs(new_width - width) // 2
    img_dst = new_img[offset_height:offset_height + height, offset_width:offset_width+width]
    output_img = normalize(img_dst)
    
    return output_img 
def spectrum_fft(fft):
    """
    return FFT spectrum
    """
    return np.sqrt(np.power(fft.real, 2) + np.power(fft.imag, 2))
# 陷波滤波器处理周期噪声
img_ori = cv2.imread('DIP_Figures/DIP3E_Original_Images_CH05/Fig0507(a)(ckt-board-orig).tif', 0) #直接读为灰度图像

# 正弦噪声
noise = add_sin_noise(img_ori, scale=0.35, angle=-20)
img = np.array(img_ori / 255, np.float32)
img_noise = img + noise
img_noise = np.uint8(normalize(img_noise)*255)

# 频率域中的其他特性
# FFT
img_fft = np.fft.fft2(img_noise.astype(np.float32))
# 中心化
fshift = np.fft.fftshift(img_fft)            # 将变换的频率图像四角移动到中心
# 中心化后的频谱
spectrum_fshift = spectrum_fft(fshift)
spectrum_fshift_n = np.uint8(normalize(spectrum_fshift) * 255)

# 对频谱做对数变换
spectrum_log = np.log(1 + spectrum_fshift)

BNRF = butterworth_notch_resistant_filter(img_ori, radius=5, uk=25, vk=10, n=4)

f1shift = fshift * (BNRF)
f2shift = np.fft.ifftshift(f1shift) #对新的进行逆变换
img_new = np.fft.ifft2(f2shift)
img_new = np.abs(img_new)

plt.figure(figsize=(15, 15))
plt.subplot(221), plt.imshow(img_noise, 'gray'), plt.title('With Sine noise'), plt.xticks([]),plt.yticks([])
plt.subplot(222), plt.imshow(spectrum_log, 'gray'), plt.title('Spectrum'), plt.xticks([]),plt.yticks([])
# 在图像上加上箭头
plt.arrow(180, 180, 25, 30, width=5,length_includes_head=True, shape='full')
plt.arrow(285, 265, -25, -30, width=5,length_includes_head=True, shape='full')

plt.subplot(223), plt.imshow(BNRF, 'gray'), plt.title('Spectrum'), plt.xticks([]),plt.yticks([])
# 在图像上加上箭头
plt.arrow(180, 180, 25, 30, width=5,length_includes_head=True, shape='full')
plt.arrow(285, 265, -25, -30, width=5,length_includes_head=True, shape='full')

plt.subplot(224), plt.imshow(img_new, 'gray'), plt.title('Spectrum'), plt.xticks([]),plt.yticks([])

plt.tight_layout()
plt.show()

在这里插入图片描述

# 陷波滤波器提取周期噪声
img_ori = cv2.imread('DIP_Figures/DIP3E_Original_Images_CH05/Fig0507(a)(ckt-board-orig).tif', 0) #直接读为灰度图像

# 正弦噪声
noise = add_sin_noise(img_ori, scale=0.35, angle=-20)
img = np.array(img_ori / 255, np.float32)
img_noise = img + noise
img_noise = np.uint8(normalize(img_noise)*255)

# 频率域中的其他特性
# FFT
img_fft = np.fft.fft2(img_noise.astype(np.float32))
# 中心化
fshift = np.fft.fftshift(img_fft)            # 将变换的频率图像四角移动到中心
# 中心化后的频谱
spectrum_fshift = spectrum_fft(fshift)
spectrum_fshift_n = np.uint8(normalize(spectrum_fshift) * 255)

# 对频谱做对数变换
spectrum_log = np.log(1 + spectrum_fshift)

BNRF = 1 - butterworth_notch_resistant_filter(img_ori, radius=5, uk=25, vk=10, n=4)

f1shift = fshift * (BNRF)
f2shift = np.fft.ifftshift(f1shift) #对新的进行逆变换
img_new = np.fft.ifft2(f2shift)
img_new = np.abs(img_new)

plt.figure(figsize=(15, 15))
# plt.subplot(221), plt.imshow(img_noise, 'gray'), plt.title('With Sine noise'), plt.xticks([]),plt.yticks([])
# plt.subplot(222), plt.imshow(spectrum_log, 'gray'), plt.title('Spectrum'), plt.xticks([]),plt.yticks([])
# # 在图像上加上箭头
# plt.arrow(180, 180, 25, 30, width=5,length_includes_head=True, shape='full')
# plt.arrow(285, 265, -25, -30, width=5,length_includes_head=True, shape='full')

# plt.subplot(223), plt.imshow(BNRF, 'gray'), plt.title('Spectrum'), plt.xticks([]),plt.yticks([])
# # 在图像上加上箭头
# plt.arrow(180, 180, 25, 30, width=5,length_includes_head=True, shape='full')
# plt.arrow(285, 265, -25, -30, width=5,length_includes_head=True, shape='full')

plt.subplot(224), plt.imshow(img_new, 'gray'), plt.title('Sine pattern'), plt.xticks([]),plt.yticks([])

plt.tight_layout()
plt.show()

在这里插入图片描述

def butterworth_band_resistant_filter(source, center, radius=10, w=5, n=1):
    """
    create butterworth band resistant filter, equation 4.150
    param: source: input, source image
    param: center: input, the center of the filter, where is the lowest value, (0, 0) is top left corner, source.shape[:2] is 
                   center of the source image
    param: radius: input, int, the radius of circle of the band pass filter, default is 10
    param: w:      input, int, the width of the band of the filter, default is 5
    param: n:      input, int, order of the butter worth fuction, 
    return a [0, 1] value butterworth band resistant filter
    """    
    epsilon = 1e-8
    N, M = source.shape[:2]
    
    u = np.arange(M)
    v = np.arange(N)
    
    u, v = np.meshgrid(u, v)
    
    D = np.sqrt((u - center[1]//2)**2 + (v - center[0]//2)**2)
    C0 = radius
    
    temp = (D * w) / ((D**2 - C0**2) + epsilon)
    
    kernel = 1 / (1 + temp ** (2*n)) 
    return kernel

def butterworth_low_pass_filter(img, center, radius=5, n=1):
    """
    create butterworth low pass filter 
    param: source: input, source image
    param: center: input, the center of the filter, where is the lowest value, (0, 0) is top left corner, source.shape[:2] is 
                   center of the source image
    param: radius: input, the radius of the lowest value, greater value, bigger blocker out range, if the radius is 0, then all
                   value is 0
    param: n: input, float, the order of the filter, if n is small, then the BLPF will be close to GLPF, and more smooth from low
              frequency to high freqency.if n is large, will close to ILPF
    return a [0, 1] value filter
    """  
    epsilon = 1e-8
    M, N = img.shape[1], img.shape[0]
    
    u = np.arange(M)
    v = np.arange(N)
    
    u, v = np.meshgrid(u, v)
    
    D = np.sqrt((u - center[1]//2)**2 + (v - center[0]//2)**2)
    D0 = radius
    kernel = (1 / (1 + (D / (D0 + epsilon))**(2*n)))
    
    return kernel
# 陷波滤波器处理周期噪声,用巴特沃斯低通滤波器得到的效果比目前的陷波滤波器效果还要好
img_ori = cv2.imread('DIP_Figures/DIP3E_Original_Images_CH05/Fig0516(a)(applo17_boulder_noisy).tif', 0)
M, N = img_ori.shape[:2]

fp = pad_image(img_ori, mode='reflect')
fp_cen = centralized_2d(fp)
fft = np.fft.fft2(fp_cen)

# 中心化后的频谱
spectrum_fshift = spectrum_fft(fft)
spectrum_log = np.log(1 + spectrum_fshift)

# 滤波器
n = 15
r = 20
H = butterworth_low_pass_filter(fp, fp.shape, radius=100, n=4)
# BNRF_1 = butterworth_notch_resistant_filter(fp, radius=r, uk=355, vk=0, n=n)
# BNRF_2 = butterworth_notch_resistant_filter(fp, radius=r, uk=0, vk=355, n=n)
# BNRF_3 = butterworth_notch_resistant_filter(fp, radius=r, uk=250, vk=250, n=n)
# BNRF_4 = butterworth_notch_resistant_filter(fp, radius=r, uk=-250, vk=250, n=n)
# BNRF = BNRF_1 * BNRF_2 * BNRF_3 * BNRF_4  * H
BNRF = H

fft_filter = fft * BNRF

# 滤波后的频谱
spectrum_filter = spectrum_fft(fft_filter)
spectrum_filter_log = np.log(1 + spectrum_filter)

# 傅里叶反变换
ifft = np.fft.ifft2(fft_filter)

# 去中心化反变换的图像,并取左上角的图像
img_new = centralized_2d(ifft.real)[:M, :N]
img_new = np.clip(img_new, 0, img_new.max())
img_new = np.uint8(normalize(img_new) * 255)

plt.figure(figsize=(15, 12))
plt.subplot(221), plt.imshow(img_ori, 'gray'), plt.title('With noise'), plt.xticks([]),plt.yticks([])
plt.subplot(222), plt.imshow(spectrum_log, 'gray'), plt.title('Spectrum'), plt.xticks([]),plt.yticks([])
plt.subplot(223), plt.imshow(spectrum_filter_log, 'gray'), plt.title('Spectrum With Filter'), plt.xticks([]),plt.yticks([])
plt.subplot(224), plt.imshow(img_new, 'gray'), plt.title('IDFT'), plt.xticks([]),plt.yticks([])
plt.tight_layout()
plt.show()

在这里插入图片描述

# 陷波滤波器提取周期噪声
img_ori = cv2.imread('DIP_Figures/DIP3E_Original_Images_CH05/Fig0516(a)(applo17_boulder_noisy).tif', 0)
M, N = img_ori.shape[:2]

fp = pad_image(img_ori, mode='constant')
fp_cen = centralized_2d(fp)
fft = np.fft.fft2(fp_cen)

# 中心化后的频谱
spectrum_fshift = spectrum_fft(fft)
spectrum_log = np.log(1 + spectrum_fshift)

# 滤波器
n = 15
r = 20
H = butterworth_low_pass_filter(fp, fp.shape, radius=100, n=3)
# BNRF_1 = butterworth_notch_resistant_filter(fp, radius=r, uk=355, vk=0, n=n)
# BNRF_2 = butterworth_notch_resistant_filter(fp, radius=r, uk=0, vk=355, n=n)
# BNRF_3 = butterworth_notch_resistant_filter(fp, radius=r, uk=250, vk=250, n=n)
# BNRF_4 = butterworth_notch_resistant_filter(fp, radius=r, uk=-250, vk=250, n=n)
# BNRF = BNRF_1 * BNRF_2 * BNRF_3 * BNRF_4 * H
BNRF = H
fft_filter = fft * (1 - BNRF)

# 滤波后的频谱
spectrum_filter = spectrum_fft(fft_filter)
spectrum_filter_log = np.log(1 + spectrum_filter)

# 傅里叶反变换
ifft = np.fft.ifft2(fft_filter)

# 去中心化反变换的图像,并取左上角的图像
img_new = centralized_2d(ifft.real)[:M, :N]
img_new = np.clip(img_new, 0, img_new.max())
img_new = np.uint8(normalize(img_new) * 255)

plt.figure(figsize=(15, 12))
# plt.subplot(221), plt.imshow(img_ori, 'gray'), plt.title('With Sine noise'), plt.xticks([]),plt.yticks([])
# plt.subplot(222), plt.imshow(spectrum_log, 'gray'), plt.title('Spectrum'), plt.xticks([]),plt.yticks([])
# plt.subplot(223), plt.imshow(spectrum_filter_log, 'gray'), plt.title('Spectrum'), plt.xticks([]),plt.yticks([])
plt.subplot(224), plt.imshow(img_new, 'gray'), plt.title('Spectrum'), plt.xticks([]),plt.yticks([])
plt.tight_layout()
plt.show()

在这里插入图片描述

def narrow_notch_filter(img, w=5, opening=10, vertical=True, horizontal=False):
    """
    create narrow notch resistant filter
    param: img:        input, source image
    param: w:          input, int, width of the resistant, value is 0, default is 5
    param: opening:    input, int, opening of the resistant, value is 1, default is 10
    param: vertical:   input, boolean, whether vertical or not, default is "True"
    param: horizontal: input, boolean, whether horizontal or not, default is "False"
    return a [0, 1] value butterworth band resistant filter
    """       
    assert w > 0, "W must greater than 0"
    w_half = w//2
    opening_half = opening//2
    img_temp = np.ones(img.shape[:2])
    M, N = img_temp.shape[:]
    img_vertical = img_temp.copy()
    img_horizontal = img_temp.copy()
    
    if horizontal:
        img_horizontal[M//2 - w_half:M//2 + w - w_half, :] = 0
        img_horizontal[:, N//2 - opening_half:N//2 + opening - opening_half] = 1
    if vertical:
        img_vertical[:, N//2 - w_half:N//2 + w - w_half] = 0
        img_vertical[M//2 - opening_half:M//2 + opening - opening_half, :] = 1
    img_dst = img_horizontal * img_vertical
    
    return img_dst
# 陷波滤波器处理周期噪声,用巴特沃斯低通滤波器得到的效果比目前的陷波滤波器效果还要好
img_ori = cv2.imread('DIP_Figures/DIP3E_Original_Images_CH05/Fig0519(a)(florida_satellite_original).tif', 0)
M, N = img_ori.shape[:2]

fp = pad_image(img_ori, mode='reflect')
fp_cen = centralized_2d(fp)
fft = np.fft.fft2(fp_cen)

# 中心化后的频谱
spectrum_fshift = spectrum_fft(fft)
spectrum_log = np.log(1 + spectrum_fshift)

# 滤波器
n = 15
r = 20
H = narrow_notch_filter(fp, w=10, opening=30, vertical=True, horizontal=False)
# BNRF_1 = butterworth_notch_resistant_filter(fp, radius=r, uk=355, vk=0, n=n)
# BNRF_2 = butterworth_notch_resistant_filter(fp, radius=r, uk=0, vk=355, n=n)
# BNRF_3 = butterworth_notch_resistant_filter(fp, radius=r, uk=250, vk=250, n=n)
# BNRF_4 = butterworth_notch_resistant_filter(fp, radius=r, uk=-250, vk=250, n=n)
# BNRF = BNRF_1 * BNRF_2 * BNRF_3 * BNRF_4  * H
BNRF = H

fft_filter = fft * BNRF

# 滤波后的频谱
spectrum_filter = spectrum_fft(fft_filter)
spectrum_filter_log = np.log(1 + spectrum_filter)

# 傅里叶反变换
ifft = np.fft.ifft2(fft_filter)

# 去中心化反变换的图像,并取左上角的图像
img_new = centralized_2d(ifft.real)[:M, :N]
img_new = np.clip(img_new, 0, img_new.max())
img_new = np.uint8(normalize(img_new) * 255)

plt.figure(figsize=(15, 16))
plt.subplot(221), plt.imshow(img_ori, 'gray'), plt.title('With noise'), plt.xticks([]),plt.yticks([])
plt.subplot(222), plt.imshow(spectrum_log, 'gray'), plt.title('Spectrum'), plt.xticks([]),plt.yticks([])
plt.subplot(223), plt.imshow(spectrum_filter_log, 'gray'), plt.title('Spectrum With Filter'), plt.xticks([]),plt.yticks([])
plt.subplot(224), plt.imshow(img_new, 'gray'), plt.title('IDFT'), plt.xticks([]),plt.yticks([])
plt.tight_layout()
plt.show()

在这里插入图片描述

# 陷波滤波器提取周期噪声,用巴特沃斯低通滤波器得到的效果比目前的陷波滤波器效果还要好
img_ori = cv2.imread('DIP_Figures/DIP3E_Original_Images_CH05/Fig0519(a)(florida_satellite_original).tif', 0)
M, N = img_ori.shape[:2]

fp = pad_image(img_ori, mode='reflect')
fp_cen = centralized_2d(fp)
fft = np.fft.fft2(fp_cen)

# 中心化后的频谱
spectrum_fshift = spectrum_fft(fft)
spectrum_log = np.log(1 + spectrum_fshift)

# 滤波器
n = 15
r = 20
H = narrow_notch_filter(fp, w=10, opening=30, vertical=True, horizontal=False)
# BNRF_1 = butterworth_notch_resistant_filter(fp, radius=r, uk=355, vk=0, n=n)
# BNRF_2 = butterworth_notch_resistant_filter(fp, radius=r, uk=0, vk=355, n=n)
# BNRF_3 = butterworth_notch_resistant_filter(fp, radius=r, uk=250, vk=250, n=n)
# BNRF_4 = butterworth_notch_resistant_filter(fp, radius=r, uk=-250, vk=250, n=n)
# BNRF = BNRF_1 * BNRF_2 * BNRF_3 * BNRF_4  * H
BNRF = H

fft_filter = fft * (1 - BNRF)

# 滤波后的频谱
spectrum_filter = spectrum_fft(fft_filter)
spectrum_filter_log = np.log(1 + spectrum_filter)

# 傅里叶反变换
ifft = np.fft.ifft2(fft_filter)

# 去中心化反变换的图像,并取左上角的图像
img_new = centralized_2d(ifft.real)[:M, :N]
img_new = np.clip(img_new, 0, img_new.max())
img_new = np.uint8(normalize(img_new) * 255)

plt.figure(figsize=(15, 16))
# plt.subplot(221), plt.imshow(img_ori, 'gray'), plt.title('With noise'), plt.xticks([]),plt.yticks([])
# plt.subplot(222), plt.imshow(spectrum_log, 'gray'), plt.title('Spectrum'), plt.xticks([]),plt.yticks([])
# plt.subplot(223), plt.imshow(spectrum_filter_log, 'gray'), plt.title('Spectrum With Filter'), plt.xticks([]),plt.yticks([])
plt.subplot(224), plt.imshow(img_new, 'gray'), plt.title('IDFT'), plt.xticks([]),plt.yticks([])
plt.tight_layout()
plt.show()

在这里插入图片描述

# 使用陷波带阻滤波器滤波
img_florida = cv2.imread("DIP_Figures/DIP3E_Original_Images_CH05/Fig0519(a)(florida_satellite_original).tif", -1)

#--------------------------------
fft = np.fft.fft2(img_florida)
fft_shift = np.fft.fftshift(fft)
amp_img = np.abs(np.log(1 + np.abs(fft_shift)))

#--------------------------------
BNF = narrow_notch_filter(img_florida, w=5, opening=20, vertical=True, horizontal=False)

fft_NNF = np.fft.fft2(BNF*255)
fft_shift_NNF = np.fft.fftshift(fft_NNF)
amp_img_NNF = np.abs(np.log(1 + np.abs(fft_shift_NNF)))


#--------------------------------
f1shift = fft_shift * (BNF)
f2shift = np.fft.ifftshift(f1shift) #对新的进行逆变换
img_new = np.fft.ifft2(f2shift)

#出来的是复数,无法显示
img_new = np.abs(img_new)

#调整大小范围便于显示
img_new = (img_new-np.amin(img_new))/(np.amax(img_new)-np.amin(img_new))

fft_mask = amp_img * BNF

plt.figure(figsize=(15, 16))
plt.subplot(221),plt.imshow(img_florida,'gray'),plt.title('Image with noise')
plt.subplot(222),plt.imshow(amp_img,'gray'),plt.title('FFT')
plt.subplot(223),plt.imshow(fft_mask,'gray'),plt.title('FFT with mask')
plt.subplot(224),plt.imshow(img_new,'gray'),plt.title('Denoising')
plt.tight_layout()
plt.show()

在这里插入图片描述

最优陷波滤波

这种滤波方法的过程如下:
首先分离干扰模式的各个主要贡献,然后从被污染图像中减去该模式的一个可变加权部分。

首先提取干模式的主频率分量,提取方法是在每个尖峰位置放一个陷波带通滤波器传递函数 H N P ( u , v ) H_{NP}(u, v) HNP(u,v),则干扰噪声模式的傅里叶变换为:
N ( u , v ) = H N P ( u , v ) G ( u , v ) (5.38) N(u, v) = H_{NP}(u, v)G(u, v) \tag{5.38} N(u,v)=HNP(u,v)G(u,v)(5.38)

则有噪声模式:
η ( x , y ) = J − 1 { H N P ( u , v ) G ( u , v ) } (5.39) \eta(x, y) = \mathfrak{J}^-1 \{ H_{NP}(u, v)G(u, v) \} \tag{5.39} η(x,y)=J1{HNP(u,v)G(u,v)}(5.39)

如果我们知道了噪声模式,我们假设噪声是加性噪声,只可以用污染的噪声 g ( x , y ) g(x, y) g(x,y)减去噪声模式 η ( x , y ) \eta(x, y) η(x,y)可得到 f ^ ( x , y ) \hat{f}(x, y) f^(x,y),但通常这只是一个近似值。
f ^ ( x , y ) = g ( x , y ) − w ( x , y ) η ( x , y ) (5.40) \hat{f}(x, y) = g(x, y) - w(x, y)\eta(x, y) \tag{5.40} f^(x,y)=g(x,y)w(x,y)η(x,y)(5.40)
w ( x , y ) w(x, y) w(x,y)是一个加权函数或调制函数,这个方法的目的就是选取 w ( x , y ) w(x, y) w(x,y),以便以某种意义的方式来优化结果。一种方法是选择 w ( x , y ) w(x, y) w(x,y),使 f ^ ( x , y ) \hat{f}(x, y) f^(x,y)在每点 ( x , y ) (x, y) (x,y)的规定邻域上的方差最小。

m × n m\times{n} m×n(奇数)的邻域 S x y S_{xy} Sxy f ^ ( x , y ) \hat{f}(x, y) f^(x,y)的“局部”方差估计如下:
σ 2 ( x , y ) = 1 m n ∑ ( r , c ) ∈ S x y [ f ^ ( r , c ) − f ^ ˉ ] 2 (5.41) \sigma^2(x, y) = \frac{1}{mn} \sum_{(r,c)\in S_{xy}} \Big[ \hat{f}(r, c) - \bar{\hat{f}} \Big]^2 \tag{5.41} σ2(x,y)=mn1(r,c)Sxy[f^(r,c)f^ˉ]2(5.41)

f ^ ˉ \bar{\hat{f}} f^ˉ是邻域 f ^ \hat{f} f^的平均值,
f ^ ˉ = 1 m n ∑ ( r , c ) ∈ S x y f ^ ( r , c ) (5.42) \bar{\hat{f}} = \frac{1}{mn} \sum_{(r,c)\in S_{xy}} \hat{f}(r, c) \tag{5.42} f^ˉ=mn1(r,c)Sxyf^(r,c)(5.42)

将式(5.40)代入(5.41),得
σ 2 ( x , y ) = 1 m n ∑ ( r , c ) ∈ S x y { [ g ( r , c ) − w ( r , c ) η ( r , c ) ] − [ g ‾ − w η ‾ ] } 2 (5.43) \sigma^2(x, y) = \frac{1}{mn} \sum_{(r,c)\in S_{xy}} \Big\{\big[g(r, c) - w(r, c) \eta(r, c)\big] - \big[\overline{g} - \overline{w\eta} \big ] \Big\}^2\tag{5.43} σ2(x,y)=mn1(r,c)Sxy{[g(r,c)w(r,c)η(r,c)][gwη]}2(5.43)

g ‾ \overline{g} g w η ‾ \overline{w\eta} wη分别是 g g g w η w\eta wη在邻域 S x y S_{xy} Sxy的平均值

若假设 w w w S x y S_{xy} Sxy内近似为常数,则可用该邻域中心的 w w w值来代替 w ( r , c ) w(r, c) w(r,c):

w ( r , c ) = w ( x , y ) (5.44) w(r, c) = w(x, y) \tag{5.44} w(r,c)=w(x,y)(5.44)

因为 w ( x , y ) w(x, y) w(x,y) S x y S_{xy} Sxy中被假设为常数,因此在 S x y S_{xy} Sxy中根据 w ‾ = w ( x , y ) \overline{w} = w(x, y) w=w(x,y)

w η ‾ = w ( x , y ) η ‾ (5.45) \overline{w\eta} = w(x, y) \overline{\eta} \tag{5.45} wη=w(x,y)η(5.45)

η ‾ \overline{\eta} η是邻域 S x y S_{xy} Sxy中的平均值,所以式(5.43)变为:

σ 2 ( x , y ) = 1 m n ∑ ( r , c ) ∈ S x y { [ g ( r , c ) − w ( x , y ) η ( r , c ) ] − [ g ‾ − w ( x , y ) η ‾ ] } 2 (5.44) \sigma^2(x, y) = \frac{1}{mn} \sum_{(r,c)\in S_{xy}} \Big\{\big[g(r, c) - w(x, y) \eta(r, c)\big] - \big[\overline{g} - {w(x, y)}\overline{\eta} \big ] \Big\}^2\tag{5.44} σ2(x,y)=mn1(r,c)Sxy{[g(r,c)w(x,y)η(r,c)][gw(x,y)η]}2(5.44)

要使得 σ 2 ( x , y ) \sigma^2(x, y) σ2(x,y)相对 w ( x , y ) w(x, y) w(x,y)最小,我们可以对式(5.44)求关于 w ( x , y ) w(x, y) w(x,y)的偏导数,并令为偏导数为0;

∂ σ 2 ( x , y ) ∂ w ( x , y ) = 0 (5.47) \frac{\partial{\sigma^2(x, y)}}{\partial{w(x, y)}} = 0 \tag{5.47} w(x,y)σ2(x,y)=0(5.47)

求得 w ( x , y ) w(x, y) w(x,y):
w ( x , y ) = g η ‾ − g ˉ η ˉ η 2 ‾ − η ˉ 2 (5.48) w(x, y) = \frac{\overline{g\eta} - \bar{g}\bar{\eta}}{\overline{\eta^2} - \bar{\eta}^2}\tag{5.48} w(x,y)=η2ηˉ2gηgˉηˉ(5.48)

把式(5.48)代入式(5.40)并在噪声图像 g g g中的每个点执行这一过程,可得到完全复原的图像。

# 这里还没有实现,迟点再弄吧
img_mariner = cv2.imread("DIP_Figures/DIP3E_Original_Images_CH05/Fig0520(a)(NASA_Mariner6_Mars).tif", 0)
M, N = img_mariner.shape[:2]

fp = pad_image(img_mariner, mode='reflect')
fp_cen = centralized_2d(fp)
fft = np.fft.fft2(fp_cen)

# 中心化后的频谱
spectrum_fshift = spectrum_fft(fft)
spectrum_log = np.log(1 + spectrum_fshift)

# 未中心化的频谱
fft_fp = np.fft.fft2(fp)
spectrum_fp = spectrum_fft(fft_fp)
spectrum_fp_log = np.log(1 + spectrum_fp)

# 滤波器
n = 15
r = 20
H = butterworth_band_resistant_filter(fp, fp.shape, radius=40, w=5, n=5)
# BNRF_1 = butterworth_notch_resistant_filter(fp, radius=r, uk=355, vk=0, n=n)
# BNRF_2 = butterworth_notch_resistant_filter(fp, radius=r, uk=0, vk=355, n=n)
# BNRF_3 = butterworth_notch_resistant_filter(fp, radius=r, uk=250, vk=250, n=n)
# BNRF_4 = butterworth_notch_resistant_filter(fp, radius=r, uk=-250, vk=250, n=n)
# BNRF = BNRF_1 * BNRF_2 * BNRF_3 * BNRF_4  * H

fft_filter = fft_fp * (1 - H)
ifft = np.fft.ifft2(fft_filter)
img_new = ifft.real[:M, :N]

# # show = spectrum_fp_log * H
# fft_filter = fft * BNRF

# # 滤波后的频谱
# spectrum_filter = spectrum_fft(fft_filter)
# spectrum_filter_log = np.log(1 + spectrum_filter)

# # 傅里叶反变换
# ifft = np.fft.ifft2(fft_filter)

# 去中心化反变换的图像,并取左上角的图像
# img_new = centralized_2d(ifft.real)[:M, :N]
# img_new = np.clip(img_new, 0, img_new.max())
# img_new = np.uint8(normalize(img_new) * 255)

plt.figure(figsize=(15, 15))
plt.subplot(221), plt.imshow(img_mariner, 'gray'), plt.title('With noise'), plt.xticks([]),plt.yticks([])
plt.subplot(222), plt.imshow(spectrum_log, 'gray'), plt.title('Spectrum Centralied'), plt.xticks([]),plt.yticks([])
plt.subplot(223), plt.imshow(spectrum_fp_log, 'gray'), plt.title('Spectrum Not Centralized'), plt.xticks([]),plt.yticks([])
plt.subplot(224), plt.imshow(img_new, 'gray'), plt.title('IDFT'), plt.xticks([]),plt.yticks([])
plt.tight_layout()
plt.show()

在这里插入图片描述

# 巴特沃斯带阻陷波滤波器 BNRF
img_dst = img_mariner - img_new
plt.figure(figsize=(16, 16))
plt.subplot(221), plt.imshow(img_dst, 'gray'), plt.title('BNF_1')
# plt.subplot(222), plt.imshow(BNF_2, 'gray'), plt.title('BNF_2')
# plt.subplot(223), plt.imshow(BNF_3, 'gray'), plt.title('BNF_3')
# plt.subplot(224), plt.imshow(BNF_dst, 'gray'), plt.title('BNF_dst')
plt.tight_layout()
plt.show()

在这里插入图片描述

  • 3
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
数字图像处理中的陷波滤波是基于matlab的一种常用技术,用于去除图像中的噪声或者干扰信号。陷波滤波在信号处理中常用于去除特定频率的噪声或干扰,使得信号更加准确和清晰。 在matlab中,实现陷波滤波可以通过多种方法。其中,常用的方法之一是使用数字滤波器设计工具包(Digital Filter Design Toolkit),该工具包提供了多种数字滤波器设计方法,如IIR滤波器设计、FIR滤波器设计等。用户可以根据实际需求选择合适的滤波器类型,并使用工具包中的函数进行设计和实现。 具体而言,用户可以通过以下步骤在matlab中实现陷波滤波: 1. 读取图像:使用imread函数读取需要进行陷波滤波处理的图像。 2. 图像预处理:根据需要,可以对图像进行预处理,如灰度化、调整亮度和对比度等,以便更好地展示和处理图像。 3. 设计滤波器:利用Digital Filter Design Toolkit中的函数,如fir1函数或者iirnotch函数,根据特定的频率选取参数进行滤波器设计。 4. 滤波处理:使用设计好的滤波器,通过filter函数对图像进行滤波处理。 5. 结果显示:通过imshow函数将滤波处理后的图像显示出来,以便用户观察图像的效果。 需要注意的是,陷波滤波的效果与所选择的滤波器类型、频率参数以及图像本身的特点有关,因此在使用matlab进行陷波滤波时,需要根据实际情况进行参数调整和反复尝试,以获得最佳的滤波效果。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jasneik

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值