python 图像处理 图像的傅立叶变换+频域滤波

一.傅立叶变换基本操作

傅立叶变换的相应操作
包括了:变换与逆变换,变换后得到频域上的图像的幅值、相位。

# 傅立叶变换 相应操作
# 得到频域上的图像,其幅值、相位
# 变换再逆变换得到原图

import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread('Lena.jpg', 0)  # 直接读为灰度图像
f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)
# 取绝对值.:将复数变化成实数
# 取对数的目的为了将数据变化到较小的范围(比如0-255)
c1 = np.log(np.abs(f))  # 频域后图像的振幅信息
c2 = np.log(np.abs(fshift))  # 中心化操作

ph_f = np.angle(f)  # 图像上每个像素点对应的相位图
ph_fshift = np.angle(fshift)  # 中心化操作

# 逆变换
f0shift = np.fft.ifftshift(fshift)
img_back = np.fft.ifft2(f0shift)
img_back = np.abs(img_back)  # 出来的是复数,无法显示

# 逆变换--取绝对值就是振幅
f1shift = np.fft.ifftshift(np.abs(fshift))
img_back1 = np.fft.ifft2(f1shift)
img_back1 = np.abs(img_back1)
img_back1 = (img_back1-np.amin(img_back1))/(np.amax(img_back1)-np.amin(img_back1))

# 逆变换--取相位
f2shift = np.fft.ifftshift(np.angle(fshift))
img_back2 = np.fft.ifft2(f2shift)
# 出来的是复数,无法显示
img_back2 = np.abs(img_back2)
# 调整大小范围便于显示
img_back2 = (img_back2-np.amin(img_back2))/(np.amax(img_back2)-np.amin(img_back2))

# 逆变换--两者合成
s1 = np.abs(fshift)  # 取振幅
s1_angle = np.angle(fshift)  # 取相位
s1_real = s1*np.cos(s1_angle)  # 取实部
s1_imag = s1*np.sin(s1_angle)  # 取虚部
s2 = np.zeros(img.shape, dtype=complex)
s2.real = np.array(s1_real)  # 重新赋值s1给s2
s2.imag = np.array(s1_imag)
f3shift = np.fft.ifftshift(s2)  # 对新的进行逆变换
img_back3 = np.fft.ifft2(f3shift)
# 出来的是复数,无法显示
img_back3 = np.abs(img_back3)
# 调整大小范围便于显示
img_back3 = (img_back3-np.amin(img_back3))/(np.amax(img_back3)-np.amin(img_back3))

plt.subplot(421), plt.imshow(img, 'gray'), plt.title('original')
plt.subplot(422), plt.imshow(c1, 'gray'), plt.title('Amplitude')
plt.subplot(423), plt.imshow(c2, 'gray'), plt.title('center')
plt.subplot(424), plt.imshow(ph_f, 'gray'), plt.title('phases')
plt.subplot(425), plt.imshow(img_back, 'gray'), plt.title('img_back')
plt.show()

结果展示:
在这里插入图片描述

二.低通滤波

频域上的低通滤波相当于平滑滤波处理。

import cv2
import numpy as np
import matplotlib.pyplot as plt


# ideal lowpass filter
def lowPassFilter(image, d):
    f = np.fft.fft2(image)
    fshift = np.fft.fftshift(f)

    def make_transform_matrix(d):
        transfor_matrix = np.zeros(image.shape)
        center_point = tuple(map(lambda x: (x - 1) / 2, image.shape))
        for i in range(transfor_matrix.shape[0]):
            for j in range(transfor_matrix.shape[1]):
                def cal_distance(pa, pb):
                    from math import sqrt
                    dis = sqrt((pa[0] - pb[0]) ** 2 + (pa[1] - pb[1]) ** 2)
                    return dis

                dis = cal_distance(center_point, (i, j))
                if dis <= d:
                    transfor_matrix[i, j] = 1
                else:
                    transfor_matrix[i, j] = 0
        return transfor_matrix

    d_matrix = make_transform_matrix(d)
    new_img = np.abs(np.fft.ifft2(np.fft.ifftshift(fshift * d_matrix)))
    return new_img


# gaussian lowpass filter
def GaussianLowFilter(image, d):
    f = np.fft.fft2(image)
    fshift = np.fft.fftshift(f)

    def make_transform_matrix(d):
        transfor_matrix = np.zeros(image.shape)
        center_point = tuple(map(lambda x: (x-1)/2, image.shape))
        for i in range(transfor_matrix.shape[0]):
            for j in range(transfor_matrix.shape[1]):
                def cal_distance(pa, pb):
                    from math import sqrt
                    dis = sqrt((pa[0]-pb[0])**2+(pa[1]-pb[1])**2)
                    return dis
                dis = cal_distance(center_point, (i, j))
                transfor_matrix[i, j] = np.exp(-(dis**2)/(2*(d**2)))
        return transfor_matrix

    d_matrix = make_transform_matrix(d)
    new_img = np.abs(np.fft.ifft2(np.fft.ifftshift(fshift*d_matrix)))
    return new_img


img_man = cv2.imread('Lena.jpg', 0)  # 直接读为灰度图像
plt.subplot(121), plt.imshow(img_man, 'gray'), plt.title('origial')
plt.xticks([]), plt.yticks([])
# --------------------------------
rows, cols = img_man.shape
mask = np.zeros(img_man.shape, np.uint8)
mask[int(rows/2-20):int(rows/2+20), int(cols/2-20):int(cols/2+20)] = 1
# --------------------------------
f1 = np.fft.fft2(img_man)
f1shift = np.fft.fftshift(f1)
f1shift = f1shift*mask
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))

plt.subplot(122), plt.imshow(img_new, 'gray'), plt.title('Lowpass')
plt.xticks([]), plt.yticks([])
plt.show()

结果展示:
在这里插入图片描述

三.高通滤波

频域上的高通滤波相当于边缘检测算子,提取边缘。

# 高通滤波
# 有利于提取图像的轮廓

import cv2
import numpy as np
import matplotlib.pyplot as plt


# ideal highpass filter
def highPassFilter(image, d):  # D为阈值
    f = np.fft.fft2(image)
    fshift = np.fft.fftshift(f)

    def make_transform_matrix(d):
        transfor_matrix = np.zeros(image.shape)
        center_point = tuple(map(lambda x: (x-1)/2, image.shape))
        for i in range(transfor_matrix.shape[0]):
            for j in range(transfor_matrix.shape[1]):
                def cal_distance(pa,pb):
                    from math import sqrt
                    dis = sqrt((pa[0]-pb[0])**2+(pa[1]-pb[1])**2)
                    return dis
                dis = cal_distance(center_point, (i, j))
                if dis <= d:
                    transfor_matrix[i, j] = 0
                else:
                    transfor_matrix[i, j] = 1
        return transfor_matrix

    d_matrix = make_transform_matrix(d)
    new_img = np.abs(np.fft.ifft2(np.fft.ifftshift(fshift*d_matrix)))
    return new_img


# gaussian highpass
def GaussianHighFilter(image, d):
    f = np.fft.fft2(image)
    fshift = np.fft.fftshift(f)

    def make_transform_matrix(d):
        transfor_matrix = np.zeros(image.shape)
        center_point = tuple(map(lambda x: (x-1)/2, image.shape))
        for i in range(transfor_matrix.shape[0]):
            for j in range(transfor_matrix.shape[1]):
                def cal_distance(pa, pb):
                    from math import sqrt
                    dis = sqrt((pa[0]-pb[0])**2+(pa[1]-pb[1])**2)
                    return dis
                dis = cal_distance(center_point, (i, j))
                transfor_matrix[i, j] = 1-np.exp(-(dis**2)/(2*(d**2)))
        return transfor_matrix

    d_matrix = make_transform_matrix(d)
    new_img = np.abs(np.fft.ifft2(np.fft.ifftshift(fshift*d_matrix)))
    return new_img


img_man = cv2.imread('Lena.jpg', 0)  # 直接读为灰度图像
plt.subplot(121), plt.imshow(img_man, 'gray'), plt.title('origial')
plt.xticks([]), plt.yticks([])
# --------------------------------
rows, cols = img_man.shape
mask = np.ones(img_man.shape, np.uint8)
mask[int(rows/2-30):int(rows/2+30), int(cols/2-30):int(cols/2+30)] = 0
# --------------------------------
f1 = np.fft.fft2(img_man)
f1shift = np.fft.fftshift(f1)
f1shift = f1shift*mask
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))

out = GaussianHighFilter(img_man, 60)
plt.subplot(122), plt.imshow(out, 'gray'), plt.title('Highpass')
plt.xticks([]), plt.yticks([])
plt.show()

结果展示:
在这里插入图片描述

四.带通滤波

带通滤波处于高通和低通之间,可指定频率的范围。

# 带通滤波器

import cv2
import numpy as np
import matplotlib.pyplot as plt


img_man = cv2.imread('Lena.jpg', 0)  # 直接读为灰度图像
plt.subplot(121), plt.imshow(img_man, 'gray'), plt.title('origial')
plt.xticks([]), plt.yticks([])
# --------------------------------
rows, cols = img_man.shape
mask1 = np.ones(img_man.shape, np.uint8)
mask1[int(rows/2-8):int(rows/2+8), int(cols/2-8):int(cols/2+8)] = 0
mask2 = np.zeros(img_man.shape, np.uint8)
mask2[int(rows/2-80):int(rows/2+80), int(cols/2-80):int(cols/2+80)] = 1
mask = mask1*mask2
# --------------------------------
f1 = np.fft.fft2(img_man)
f1shift = np.fft.fftshift(f1)
f1shift = f1shift*mask
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))
plt.subplot(122), plt.imshow(img_new, 'gray')
plt.xticks([]), plt.yticks([])
plt.show()

结果展示:
在这里插入图片描述

五.巴特沃兹滤波

一种常见并应用广泛的频域上的滤波器。

# 巴特沃斯滤波器

import cv2
import numpy as np
import matplotlib.pyplot as plt


def butterworthPassFilter(image, d, n):
    f = np.fft.fft2(image)
    fshift = np.fft.fftshift(f)

    def make_transform_matrix(d):
        transfor_matrix = np.zeros(image.shape)
        center_point = tuple(map(lambda x: (x - 1) / 2, image.shape))
        for i in range(transfor_matrix.shape[0]):
            for j in range(transfor_matrix.shape[1]):
                def cal_distance(pa, pb):
                    from math import sqrt
                    dis = sqrt((pa[0] - pb[0]) ** 2 + (pa[1] - pb[1]) ** 2)
                    return dis

                dis = cal_distance(center_point, (i, j))
                transfor_matrix[i, j] = 1 / ((1 + (d / dis)) ** n)
        return transfor_matrix

    d_matrix = make_transform_matrix(d)
    new_img = np.abs(np.fft.ifft2(np.fft.ifftshift(fshift * d_matrix)))
    return new_img


img = cv2.imread('Lena.jpg', 0)
plt.subplot(231)
butter_100_1 = butterworthPassFilter(img, 100, 1)
plt.imshow(butter_100_1, cmap="gray")
plt.title("d=100,n=1")
plt.axis("off")
plt.subplot(232)
butter_100_2 = butterworthPassFilter(img, 100, 2)
plt.imshow(butter_100_2, cmap="gray")
plt.title("d=100,n=2")
plt.axis("off")
plt.subplot(233)
butter_100_3 = butterworthPassFilter(img, 100, 3)
plt.imshow(butter_100_3, cmap="gray")
plt.title("d=100,n=3")
plt.axis("off")
plt.subplot(234)
butter_100_1 = butterworthPassFilter(img, 30, 1)
plt.imshow(butter_100_1, cmap="gray")
plt.title("d=30,n=1")
plt.axis("off")
plt.subplot(235)
butter_100_2 = butterworthPassFilter(img, 30, 2)
plt.imshow(butter_100_2, cmap="gray")
plt.title("d=30,n=2")
plt.axis("off")
plt.subplot(236)
butter_100_3 = butterworthPassFilter(img, 30, 3)
plt.imshow(butter_100_3, cmap="gray")
plt.title("d=30,n=3")
plt.axis("off")
plt.show()

结果展示:
D和n为滤波器的参数。
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/Wadewhl/article/details/112987618