python3-scipy高通滤波器

发布时间:2021-09-02 07:58:15编辑:run阅读(5189)

    什么是滤波器?

    滤波指对像素的强度值进行变换,以揭示特定的图像特征

    1 增强,这种图像特征提高了对比度;

    2 平滑,这种图像特征消除了噪声;

    3 模版匹配,这种图像特征检测已知模式;

    滤波后的图像由离散卷积描述,滤波器则由n x n离散卷积掩模描述。


    高通滤波器(HPF)只允许来自图像(通过DFT获得)的频域表示的高频分量通过,并阻止低于截止值的全部低频。利用离散傅里叶逆变换重建图像,由于高频分量对应于边缘,细节,噪声等,高通滤波器往往会提取出它们或增强高频分量。


    可以通过以下步骤在图像上实现HPF:

    (1).利用scipy.fftpack fft2实施二维快速傅里叶变换(FFT),得到频域中的图像表示;

    (2).仅保留高频分量(过滤掉低频分量);

    (3).执行傅里叶逆变换,以重建图像;

    from PIL import Image
    import scipy.fftpack as fp
    import matplotlib.pylab as pylab
    import numpy as np
    
    # 指定默认字体
    pylab.rcParams['font.sans-serif'] = ['KaiTi']
    # 解决保存图像是负号'-'显示为方块的问题
    pylab.rcParams['axes.unicode_minus'] = False
    im = np.array(Image.open(r'D:\image_processing\image3\a.jpg').convert('L'))
    freq = fp.fft2(im)
    (w, h) = freq.shape
    half_w, half_h = int(w/2), int(h/2)
    freq1 = np.copy(freq)
    freq2 = fp.fftshift(freq1)
    pylab.figure(figsize=(20,15))
    pylab.subplot(131)
    pylab.imshow(im, cmap=pylab.cm.gray)
    pylab.title('原始图像', size=25)
    pylab.axis('off')
    pylab.subplot(132)
    pylab.imshow((20*np.log10(0.1 + freq2)).astype(int))
    pylab.title('图像频谱', size=25)
    pylab.axis('off')
    pylab.show()

    image.png

    可以看到,高频分量更多的是对应于图像的边缘,而平均(平面)图像信息随着去除越来越多的低频成分而丢失。


    通过应用HPF来阻断Numpy2D数组中的低频.

    from PIL import Image
    import scipy.fftpack as fp
    import matplotlib.pylab as pylab
    import numpy as np
    
    # 指定默认字体
    pylab.rcParams['font.sans-serif'] = ['KaiTi']
    # 解决保存图像是负号'-'显示为方块的问题
    pylab.rcParams['axes.unicode_minus'] = False
    im = np.array(Image.open(r'D:\image_processing\image3\a.jpg').convert('L'))
    freq = fp.fft2(im)
    (w, h) = freq.shape
    half_w, half_h = int(w/2), int(h/2)
    freq1 = np.copy(freq)
    freq2 = fp.fftshift(freq1)
    freq2[half_w-10:half_w+11,half_h-10:half_h+11] = 0
    pylab.figure(figsize=(20,15))
    pylab.imshow((20*np.log10(0.1 + freq2)).astype(int))
    pylab.show()

    image.png


    如何通过ifft2()函数从上面的光谱中获取图像

    from PIL import Image
    import scipy.fftpack as fp
    from scipy import stats, fftpack
    import matplotlib.pylab as pylab
    import numpy as np
    
    # 指定默认字体
    pylab.rcParams['font.sans-serif'] = ['KaiTi']
    # 解决保存图像是负号'-'显示为方块的问题
    pylab.rcParams['axes.unicode_minus'] = False
    im = np.array(Image.open(r'D:\image_processing\image3\a.jpg').convert('L'))
    freq = fp.fft2(im)
    (w, h) = freq.shape
    half_w, half_h = int(w/2), int(h/2)
    freq1 = np.copy(freq)
    freq2 = fp.fftshift(freq1)
    freq2[half_w-10:half_w+11,half_h-10:half_h+11] = 0
    im1 = np.clip(fp.ifft2(fftpack.ifftshift(freq2)).real, 0, 255)
    pylab.figure(figsize=(20,15))
    pylab.subplot(131)
    pylab.imshow(im)
    pylab.title('原始图像', size=25)
    pylab.axis('off')
    pylab.subplot(132)
    pylab.imshow(im1, cmap='gray')
    pylab.title('HPF后的图像', size=25)
    pylab.axis('off')
    pylab.show()

    image.png

    可以看到图像中的边缘变得更加突出,HPF找到了图像中的边缘(其对应于更高的频谱)。



    在来看看HPF的截止频率是如何改变输出图像的。从灰度图像入手,对其进行FFT处理,通过切断截止值F阻断其以下的低频成分,从而重建输出图像,F值不同,它对输出图像的影响也将发生变换。

    from PIL import Image
    import scipy.fftpack as fp
    from scipy import stats, fftpack
    import matplotlib.pylab as pylab
    import numpy as np
    
    def signaltonoise(a, axis=0, ddof=0):
        a = np.asanyarray(a)
        m = a.mean(axis)
        sd = a.std(axis=axis, ddof=ddof)
        return np.where(sd == 0, 0, m/sd)
    im = np.array(Image.open(r'D:\image_processing\image3\b.jpg').convert('L'))
    freq = fp.fft2(im)
    (w, h) = freq.shape
    half_w, half_h = int(w/2), int(h/2)
    snrs_hp = []
    lbs = list(range(1, 25))
    pylab.figure(figsize=(12, 20))
    for l in lbs:
        freq1 = np.copy(freq)
        freq2 = fftpack.fftshift(freq1)
        freq2[half_w-l:half_w+l,half_h-l:half_h+l] = 0
        im1 = np.clip(fp.ifft2(fftpack.ifftshift(freq2)).real, 0, 255)
        snrs_hp.append(signaltonoise(a=im1,axis=None, ddof=0))
        pylab.subplot(6, 4, l)
        pylab.imshow(im1, cmap='gray')
        pylab.axis('off')
        pylab.title('F = ' + str(l+1), size=20)
    pylab.subplots_adjust(wspace=0.1, hspace=0)
    pylab.show()

    image.png

    image.png


    可以看到,随着截止F的增加,HPF是怎样实现检测到更多的边缘信息,并舍弃图像中的总体水平信息。


    信噪比随截止频率的变化情况:

    from PIL import Image
    import scipy.fftpack as fp
    from scipy import stats, fftpack
    import matplotlib.pylab as pylab
    import numpy as np
    
    pylab.rcParams['font.sans-serif'] = ['KaiTi']
    # 解决保存图像是负号'-'显示为方块的问题
    pylab.rcParams['axes.unicode_minus'] = False
    def signaltonoise(a, axis=0, ddof=0):
        a = np.asanyarray(a)
        m = a.mean(axis)
        sd = a.std(axis=axis, ddof=ddof)
        return np.where(sd == 0, 0, m/sd)
    im = np.array(Image.open(r'D:\image_processing\image3\b.jpg').convert('L'))
    freq = fp.fft2(im)
    (w, h) = freq.shape
    half_w, half_h = int(w/2), int(h/2)
    snrs_hp = []
    lbs = list(range(1, 25))
    pylab.figure(figsize=(12, 20))
    for l in lbs:
        freq1 = np.copy(freq)
        freq2 = fftpack.fftshift(freq1)
        freq2[half_w-l:half_w+l+l,half_h-l:half_h+l+l] = 0
        im1 = np.clip(fp.ifft2(fftpack.ifftshift(freq2)).real, 0, 255)
        snrs_hp.append(signaltonoise(a=im1,axis=None, ddof=0))
        pylab.subplot(6, 4, l)
        pylab.imshow(im1, cmap='gray')
        pylab.axis('off')
        pylab.title('F = ' + str(l+1), size=20)
    pylab.subplots_adjust(wspace=0.1, hspace=0)
    pylab.show()
    pylab.plot(lbs, snrs_hp, 'b.-')
    pylab.xlabel('截止频率F', size=22)
    pylab.ylabel('信噪比', size=22)
    pylab.show()

    image.png

    随着输出图像的信噪比是如何随着HPF截止频率F的增加而降低的。

关键字