1951 字
10 分钟
OpenCV:频域滤波【傅里叶变换】

1. 理论基础#

​ 图像处理一般分为空间域处理频率域处理

空间域处理直接对图像内的像素进行处理。空间域处理主要划分为灰度变换空间滤波两种形式。灰度变换是对图像内的单个像素进行处理,比如调节对比度处理阈值等;空间滤波涉及图像质量的改变,例如图像平滑图像锐化等。空间域处理的计算简单方便,运算速度更快。

频率域处理先将图像变换到频率域,然后在频率域对图像进行处理,最后再通过反变换将图像从频率域变换到空间域傅里叶变换 是应用最广泛的一种频域变换,它能够将图像从空间域变换到频率域,而 逆傅里叶变换 能够将频率域信息变换到空间域内。

​ 在图像处理过程中,傅里叶变换就是将图像分解为正弦分量余弦分量两部分,数字图像经过傅里叶变换后,得到的频域值是复数。显示傅里叶变换的结果需要使用实数图像加虚数图像的形式,或者幅度图像加相位图像的形式。因为幅度图像包含了原图像中我们所需要的大部分信息,所以在图像处理过程中, 通常仅使用幅度图像如果需要通过逆傅里叶变换恢复到原有的空域图像,就必须同时保留幅度图像和相位图像

​ 对图像进行傅里叶变换后,我们会得到图像中的 低频信息高频信息低频信息对应图像内变化缓慢的灰度分量高频信息对应图像内变化越来越快的灰度分量

傅里叶变换在图像处理领域发挥着非常关键的作用,可以实现图像增强图像去噪边缘检测特征提取图像压缩和加密等。

2. Numpy实现傅里叶变换#

2.1 傅里叶变换#

numpy.fft.fft2()#

  • 通过函数numpy.fft.fft2(),实现傅里叶变换
  • 函数原型complex_ndarray = numpy.fft.fft2( gray_img )
  • 参数说明
    • complex_ndarray:表示复数数组
    • gray_img:表示灰度图像

numpy.fft.fftshift()#

  • 通过函数numpy.fft.fftshift(),实现傅里叶变换的频谱移动
  • 函数原型spectrum_shift = numpy.fft.fftshift( spectrum )
  • 参数说明
    • spectrum_shift :表示转变后的频谱
    • spectrum:表示原始频谱
注意

对图像进行傅里叶变换后,得到的是一个复数数组。为了显示方便,需要将它们的值调整到[0, 255]的灰度空间内。可以使用20 * np.log(np.abs(频谱值))进行。

2.2 逆傅里叶变换#

numpy.fft.ifft2()#

  • 通过函数numpy.fft.ifft2(),实现逆傅里叶变换

  • 函数原型complex_ndarray_output = numpy.fft.fft2( complex_ndarray_input )

  • 参数说明

    • complex_ndarray_output:表示复数数组
    • complex_ndarray_input:表示灰度图像
  • 图像获取逆傅里叶变换得到的空域信息是一个复数数组,可以通过img = np.abs(spectrum)将该信息调整至[0, 255]灰度空间内。

numpy.fft.ifftshift()#

  • 通过函数numpy.fft.ifftshift(),实现傅里叶变换的频谱移动,和函数numpy.fft.fftshift()的操作过程相反。
  • 函数原型spectrum_shift = numpy.fft.ifftshift( spectrum )
  • 参数说明
    • spectrum_shift :表示转变后的频谱
    • spectrum:表示原始频谱
注意

​ 如果在傅里叶变换过程中使用了numpy.fft.fftshift()函数移动零频率分量,那么在逆傅里叶变换过程中,需要先使用numpy.fft.ifftshift()函数将零频率分量移到原来的位置,再进行逆傅里叶变换。

2.3 示例#

import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread("person.jpg", 0)
# FFT
spectrum = np.fft.fft2(img)
spectrum_shift = np.fft.fftshift(spectrum)
spectrum_show = 20 * np.log(np.abs(spectrum_shift))
# iFFT
spectrum_ishift = np.fft.ifftshift(spectrum_shift)
spectrum_img = np.fft.ifft2(spectrum_ishift)
fft_img = np.abs(spectrum_img)
plt.subplot(131)
plt.title('img')
plt.imshow(img, cmap='gray')
plt.axis('off')
plt.subplot(132)
plt.imshow(spectrum_show, cmap='gray')
plt.title('result')
plt.axis('off')
plt.subplot(133)
plt.imshow(fft_img, cmap='gray')
plt.title('fft_img')
plt.axis('off')
plt.show()

2.4 应用#

高通滤波器:边缘提取#

  • 允许高频信号通过的滤波器称为高通滤波器
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread("person.jpg", 0)
center_row, center_col = int(img.shape[0]/2), int(img.shape[1]/2)
delta = 45
# FFT
f = np.fft.fft2(img)
f_shift = np.fft.fftshift(f)
fft = 20 * np.log(np.abs(f_shift))
f_shift[(center_row-delta):(center_row+delta), (center_col-delta):(center_col+delta)] = 1
fft_filter = 20 * np.log(np.abs(f_shift))
# iFFT
f_ishift = np.fft.ifftshift(f_shift)
ifft_img = np.fft.ifft2(f_ishift)
ifft_img = np.abs(ifft_img)
plt.subplot(221), plt.title('img'), plt.axis('off')
plt.imshow(img, cmap='gray')
plt.subplot(222), plt.title('ifft_img'), plt.axis('off')
plt.imshow(ifft_img, cmap='gray')
plt.subplot(223), plt.title('fft'), plt.axis('off')
plt.imshow(fft, cmap='gray')
plt.subplot(224), plt.title('fft_filter'), plt.axis('off')
plt.imshow(fft_filter, cmap='gray')
plt.show()

numpy_高通滤波器

低通滤波器:图像模糊#

  • 允许低频信号通过的滤波器称为低通滤波器
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread("person.jpg", 0)
row, col = img.shape
center_row, center_col = int(row/2), int(col/2)
delta = 100
# FFT
f = np.fft.fft2(img)
f_shift = np.fft.fftshift(f)
fft = 20 * np.log(np.abs(f_shift))
mask = np.zeros((row, col),np.uint8)
mask[(center_row-delta):(center_row+delta), (center_col-delta):(center_col+delta)] = 1
f_shift = f_shift * mask
f_shift[f_shift==0] = 1
fft_filter = 20 * np.log(np.abs(f_shift))
# iFFT
f_ishift = np.fft.ifftshift(f_shift)
ifft_img = np.fft.ifft2(f_ishift)
ifft_img = np.abs(ifft_img)
plt.subplot(221), plt.title('img'), plt.axis('off')
plt.imshow(img, cmap='gray')
plt.subplot(222), plt.title('ifft_img'), plt.axis('off')
plt.imshow(ifft_img, cmap='gray')
plt.subplot(223), plt.title('fft'), plt.axis('off')
plt.imshow(fft, cmap='gray')
plt.subplot(224), plt.title('fft_filter'), plt.axis('off')
plt.imshow(fft_filter, cmap='gray')
plt.show()

numpy_低通滤波器

3. OpenCV实现傅里叶变换#

3.1 傅里叶变换#

cv2.dft()#

  • 通过函数cv2.dft(),实现傅里叶变换
  • 函数原型输出数组 = cv2.dft( 原始图像, 转换标识 )
  • 参数说明
    • 输出数组:格式为复数数组
      • 返回的值是双通道的。第1个通道实数部分第2个通道虚数部分
    • 原始图像:首先使用np.float32()函数将图像转换成np.float32格式
    • 转换标识:通常为cv2.DFT_COMPLEX_OUTPUT,用来输出一个复数数组

cv2.magnitude()#

  • 通过函数cv2.magnitude(),计算频谱信息的幅度
  • 函数原型返回值 = cv2.magnitude(参数 1,参数 2)
  • 参数说明
    • 参数1:浮点型的x坐标值,也就是实部
    • 参数2:浮点型的y坐标值,也就是虚部
    • 返回值:参数1和参数2平方和的平方根,即 ret=(x2+y2)ret = \sqrt{(x^2 + y^2)}
注意

对图像进行傅里叶变换后,得到的是一个复数数组。为了显示方便,需要将它们的值调整到[0, 255]的灰度空间内。可以使用20 * np.log(幅度值)进行

3.2 逆傅里叶变换#

cv2.idft()#

  • 通过函数cv2.idft(),实现逆傅里叶变换
  • 函数原型返回图像 = cv2.idft( 复数数组 )
  • 图像获取逆傅里叶变换得到的空域信息是一个复数数组,可以通过img = np.abs(spectrum)将该信息调整至[0, 255]灰度空间内。
注意

​ 如果在傅里叶变换过程中使用了numpy.fft.fftshift()函数移动零频率分量,那么在逆傅里叶变换过程中,需要先使用numpy.fft.ifftshift()函数将零频率分量移到原来的位置,再进行逆傅里叶变换。

3.3 示例#

import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread("person.jpg", 0)
# DFT
spectrum = cv2.dft(np.float32(img), flags=cv2.DFT_COMPLEX_OUTPUT)
spectrum_shift = np.fft.fftshift(spectrum)
spectrum_magnitude = cv2.magnitude(spectrum_shift[:,:,0], spectrum_shift[:,:,1])
spectrum_show = 20 * np.log(spectrum_magnitude)
# iDFT
spectrum_ishift = np.fft.ifftshift(spectrum_shift)
spectrum_img = cv2.idft(spectrum_ishift)
dft_img = cv2.magnitude(spectrum_img[:,:,0], spectrum_img[:,:,1])
plt.subplot(131)
plt.title('img')
plt.imshow(img, cmap='gray')
plt.axis('off')
plt.subplot(132)
plt.imshow(spectrum_show, cmap='gray')
plt.title('result')
plt.axis('off')
plt.subplot(133)
plt.imshow(dft_img, cmap='gray')
plt.title('dft_img')
plt.axis('off')
plt.show()

3.4 应用#

高通滤波器:边缘提取#

  • 允许高频信号通过的滤波器称为高通滤波器
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread("person.jpg", 0)
center_row, center_col = int(img.shape[0]/2), int(img.shape[1]/2)
delta = 45
# DFT
f = cv2.dft(np.float32(img), flags=cv2.DFT_COMPLEX_OUTPUT)
f_shift = np.fft.fftshift(f)
fft = 20 * np.log(cv2.magnitude(f_shift[:,:,0], f_shift[:,:,1]))
f_shift[(center_row-delta):(center_row+delta), (center_col-delta):(center_col+delta)] = 1
fft_filter = 20 * np.log(cv2.magnitude(f_shift[:,:,0], f_shift[:,:,1]))
# iDFT
f_ishift = np.fft.ifftshift(f_shift)
ifft_img = cv2.idft(f_ishift)
ifft_img = cv2.magnitude(ifft_img[:,:,0], ifft_img[:,:,1])
plt.subplot(221), plt.title('img'), plt.axis('off')
plt.imshow(img, cmap='gray')
plt.subplot(222), plt.title('idft_img'), plt.axis('off')
plt.imshow(ifft_img, cmap='gray')
plt.subplot(223), plt.title('dft'), plt.axis('off')
plt.imshow(fft, cmap='gray')
plt.subplot(224), plt.title('dft_filter'), plt.axis('off')
plt.imshow(fft_filter, cmap='gray')
plt.show()

OpenCV_高通滤波器

低通滤波器:图像模糊#

  • 允许低频信号通过的滤波器称为低通滤波器
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread("person.jpg", 0)
row, col = img.shape
center_row, center_col = int(row/2), int(col/2)
delta = 100
# DFT
f = cv2.dft(np.float32(img), flags=cv2.DFT_COMPLEX_OUTPUT)
f_shift = np.fft.fftshift(f)
fft = 20 * np.log(cv2.magnitude(f_shift[:,:,0], f_shift[:,:,1]))
mask = np.zeros((row, col, 2),np.uint8)
mask[(center_row-delta):(center_row+delta), (center_col-delta):(center_col+delta)] = 1
f_shift = f_shift * mask
f_shift[f_shift==0] = 1
fft_filter = 20 * np.log(cv2.magnitude(f_shift[:,:,0], f_shift[:,:,1]))
# iDFT
f_ishift = np.fft.ifftshift(f_shift)
ifft_img = cv2.idft(f_ishift)
ifft_img = cv2.magnitude(ifft_img[:,:,0], ifft_img[:,:,1])
plt.subplot(221), plt.title('img'), plt.axis('off')
plt.imshow(img, cmap='gray')
plt.subplot(222), plt.title('idft_img'), plt.axis('off')
plt.imshow(ifft_img, cmap='gray')
plt.subplot(223), plt.title('dft'), plt.axis('off')
plt.imshow(fft, cmap='gray')
plt.subplot(224), plt.title('dft_filter'), plt.axis('off')
plt.imshow(fft_filter, cmap='gray')
plt.show()

OpenCV_低通滤波器

封面
示例歌曲
示例艺术家
封面
示例歌曲
示例艺术家
0:00 / 0:00