图像处理一般分为空间域处理和频率域处理,空间域处理是直接对图像内的像素进行处理。频率域处理是先将图像变换到频率域,然后在频率域对图像进行处理,最后通过反变换将图像变为空间域。傅里叶变换可以将图像变换为频率域, 傅立叶反变换再将频率域变换为空间域。
在频域里,对于一幅图像,高频部分代表了图像的、纹理信息;低频部分则代表了图像的轮廓信息。如果图像受到的噪声恰好在某个特定的频率范围内,就可以使用滤波器来恢复原来的图像。因此傅里叶变换在图像处理中可以做到图像增强和去噪、图像分割之边缘检测、图像特征提取和压缩等。
傅里叶变换对图像处理有两种方式:一种是调用opencv的函数,另一种是调用numpy的函数。虽然opencv算法运算速度快,但是推荐使用numpy做傅里叶变换,简单。Opencv
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('002.tif', 0)
rows, cols = img.shape
# size为改变滤波大小
crow, ccol = rows//2, cols//2
sizex = 5
sizey = 5
# DFT的性能优化
nrows = cv2.getOptimalDFTSize(rows)
ncols = cv2.getOptimalDFTSize(cols)
right = ncols - cols
bottom = nrows - rows
bordertype = cv2.BORDER_CONSTANT # 只是为了避免PDF文件中的行中断
nimg = cv2.copyMakeBorder(img, 0, bottom, 0, right, bordertype, value=0)
# cv傅里叶变换
dft = cv2.dft(np.float32(nimg), flags=cv2.DFT_COMPLEX_OUTPUT) # 不优化就选img
dft_shift = np.fft.fftshift(dft)
# 显示傅里叶变换图
magnitude_spectrum = 20 * np.log(cv2.magnitude(dft_shift[:, :, 0], dft_shift[:, :, 1]))
plt.imshow(magnitude_spectrum, cmap='gray')
# 高通滤波器HPF删除图像中的低频内容-边缘提取
# 首先创建一个掩码,中心正方形为0,其余全为1
mask_HPF = np.ones((nrows, ncols, 2), np.uint8) # 不优化就选rows,cols
mask_HPF[crow-sizex:crow+sizex, ccol-sizey:ccol+sizey] = 0
# 应用掩码和逆DFT
dft_shift_HPF = dft_shift.copy()
fshift_HPF = dft_shift_HPF * mask_HPF
f_ishift_HPF = np.fft.ifftshift(fshift_HPF)
img_HPF = cv2.idft(f_ishift_HPF)
img_HPF = cv2.magnitude(img_HPF[:, :, 0], img_HPF[:, :, 1])
# 低通滤波器LPF删除图像中的高频内容-图像模糊
# 首先创建一个掩码,中心正方形为1,其余全为0
mask_LPF = np.zeros((nrows, ncols, 2), np.uint8) # 不优化就选rows,cols
mask_LPF[crow-sizex:crow+sizex, ccol-sizey:ccol+sizey] = 1
# 应用掩码和逆DFT
dft_shift_LPF = dft_shift.copy()
fshift_LPF = dft_shift_LPF * mask_LPF
f_ishift_LPF = np.fft.ifftshift(fshift_LPF)
img_LPF = cv2.idft(f_ishift_LPF)
img_LPF = cv2.magnitude(img_LPF[:, :, 0], img_LPF[:, :, 1])
img_HPF = np.array(img_HPF, dtype='uint8')
img_LPF = np.array(img_LPF, dtype='uint8')
cv2.imshow("img_HPF", img_HPF)
cv2.imshow("img_LPF", img_LPF)
cv2.waitKey()
plt.show()
其中,对水平线、垂直线或中心点进行插补的方法:
# 水平线插补
dft_fshift[crow, :, 0] = (dft_fshift[crow+1, :, 0] + dft_fshift[crow-1, :, 0]) / 2
dft_fshift[crow, :, 1] = (dft_fshift[crow+1, :, 1] + dft_fshift[crow-1, :, 1]) / 2
# 垂直线插补
dft_fshift[:, ccol, 0] = (dft_fshift[:, ccol+1, 0] + dft_fshift[:, ccol-1, 0]) / 2
dft_fshift[:, ccol, 1] = (dft_fshift[:, ccol+1, 1] + dft_fshift[:, ccol-1, 1]) / 2
# 中心点插补
# dft_fshift[crow, ccol, 0] = (dft_fshift[crow+1, ccol+1, 0] + dft_fshift[crow-1, ccol+1, 0]
# + dft_fshift[crow-1, ccol+1, 0] + dft_fshift[crow-1, ccol-1, 0]) / 4
# dft_fshift[crow, ccol, 1] = (dft_fshift[crow+1, ccol+1, 1] + dft_fshift[crow-1, ccol+1, 1]
# + dft_fshift[crow-1, ccol+1, 1] + dft_fshift[crow-1, ccol-1, 1]) / 4
dft_fshift[crow, ccol, 0] = (dft_fshift[crow+1, ccol, 0] + dft_fshift[crow-1, ccol, 0]
+ dft_fshift[crow, ccol+1, 0] + dft_fshift[crow, ccol-1, 0]) / 4
dft_fshift[crow, ccol, 1] = (dft_fshift[crow+1, ccol, 1] + dft_fshift[crow-1, ccol, 1]
+ dft_fshift[crow, ccol+1, 1] + dft_fshift[crow, ccol-1, 1]) / 4
# 显示傅里叶变换图
magnitude_spectrum_f = 20 * np.log(cv2.magnitude(dft_fshift[:, :, 0], dft_fshift[:, :, 1]))
plt.subplot(1, 2, 2)
plt.imshow(magnitude_spectrum_f, cmap='gray')
2. Numpy 推荐使用
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread("Ingass1.tif", 0)
cv2.imshow("img", img)
rows, cols = img.shape
crow, ccol = int(rows/2), int(cols/2) # 计算中心位置
# -------Numpy傅里叶变换
f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)
# magnitude_spectrum = 20 * np.log(np.abs(fshift))
# plt.subplot(1, 2, 1)
# plt.imshow(magnitude_spectrum, cmap='gray')
dft_fshift = fshift.copy()
sizex = 10
sizey = 10
# 高通滤波器HPF删除图像中的低频内容-边缘提取
# 首先创建一个掩码,中心正方形为0,其余全为1
mask = np.ones(img.shape, np.uint8)
mask[crow-sizex:crow+sizex, ccol-sizey:ccol+sizey] = 0
dft_fshift = fshift * mask
# 低通滤波器LPF删除图像中的高频内容-图像模糊
# 首先创建一个掩码,中心正方形为1,其余全为0
mask = np.zeros(img.shape, np.uint8)
mask[crow-sizex:crow+sizex, ccol-sizey:ccol+sizey] = 1
dft_fshift = fshift * mask
# magnitude_spectrum2 = 20 * np.log(np.abs(dft_fshift))
# plt.subplot(1, 2, 2)
# plt.imshow(magnitude_spectrum2, cmap='gray')
f_ishift = np.fft.ifftshift(dft_fshift)
img_back = np.fft.ifft2(f_ishift)
img_back = np.abs(img_back)
img_back = img_back.astype(np.uint8)
cv2.imshow("img_back", img_back)
img_back_equ = cv2.equalizeHist(img_back)
cv2.imshow("dst", img_back_equ)
plt.show()
cv2.waitKey()
其中,对水平线、垂直线或中心点进行插补的方法:
# 水平
dft_fshift[crow, ccol-number:ccol+number] = (dft_fshift[crow+1, ccol-number:ccol+number] + dft_fshift[crow-1, ccol-number:ccol+number]) / 2
# 垂直
dft_fshift[crow-number:crow+number, ccol] = (dft_fshift[crow-number:crow+number, ccol+1] + dft_fshift[crow-number:crow+number, ccol-1]) / 2
# 中心点
dft_fshift[crow, ccol] = (dft_fshift[crow+1, ccol+1] + dft_fshift[crow-1, ccol+1] + dft_fshift[crow-1, ccol+1] + dft_fshift[crow-1, ccol-1]) / 4原图10*10高通滤波10*10低通滤波