Opencv4 -Python官方教程学习笔记23---傅里叶变换

目标

在本节中,我们将学习 - 使用OpenCV查找图像的傅立叶变换 - 利用Numpy中可用的FFT函数 - 傅立叶变换的某些应用程序 - 我们将看到以下函数:cv.dft(),cv.idft()等

理论

傅立叶变换用于分析各种滤波器的频率特性。对于图像,使用2D离散傅里叶变换(DFT)查找频域。一种称为快速傅立叶变换(FFT)的快速算法用于DFT的计算。关于这些的详细信息可以在任何图像处理或信号处理教科书中找到。请参阅其他资源部分。

对于正弦信号x(t)=Asin(2πft)
,我们可以说f是信号的频率,如果采用其频域,则可以看到f的尖峰。如果对信号进行采样以形成离散信号,我们将获得相同的频域,但是在[−π,π]或[0,2π]范围内(对于N点DFT为[0,N]

)是周期性的。您可以将图像视为在两个方向上采样的信号。因此,在X和Y方向都进行傅立叶变换,可以得到图像的频率表示。

更直观地说,对于正弦信号,如果幅度在短时间内变化如此之快,则可以说它是高频信号。如果变化缓慢,则为低频信号。您可以将相同的想法扩展到图像。图像中的振幅在哪里急剧变化?在边缘点或噪声。因此,可以说边缘和噪声是图像中的高频内容。如果幅度没有太大变化,则它是低频分量。(一些链接已添加到“其他资源”,其中通过示例直观地说明了频率变换)。

现在,我们将看到如何找到傅立叶变换。

Numpy中的傅里叶变换

首先,我们将看到如何使用Numpy查找傅立叶变换。Numpy具有FFT软件包来执行此操作。np.fft.fft2()为我们提供了频率转换,它将是一个复杂的数组。它的第一个参数是输入图像,即灰度图像。第二个参数是可选的,它决定输出数组的大小。如果它大于输入图像的大小,则在计算FFT之前用零填充输入图像。如果小于输入图像,将裁切输入图像。如果未传递任何参数,则输出数组的大小将与输入的大小相同。

现在,一旦获得结果,零频率分量(DC分量)将位于左上角。如果要使其居中,则需要在两个方向上将结果都移动N2
。只需通过函数np.fft.fftshift()即可完成。(它更容易分析)。找到频率变换后,就可以找到幅度谱。

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
path = r'D:\Laboratory\Study\Computer Vision\opencv4-python\juzi.png'  
img = cv.imread(path) 

# numpy实现傅里叶变换
f = np.fft.fft2(img)       #实现傅里叶变化,返回复数数组
fshift = np.fft.fftshift(f)    #将零频率分量移动到频谱中心
magnitude_spectrum = 20*np.log(np.abs(fshift))    #设置频谱范围
plt.subplot(121),plt.imshow(img, cmap = 'gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(magnitude_spectrum, cmap = 'gray')
plt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([])
plt.show()

结果:
在这里插入图片描述
看,您可以在中心看到更多白色区域,这表明低频内容更多。

因此,您发现了频率变换现在,您可以在频域中进行一些操作,例如高通滤波和重建图像,即找到逆DFT。为此,您只需用尺寸为60x60的矩形窗口遮罩即可消除低频。然后,使用np.fft.ifftshift()应用反向移位,以使DC分量再次出现在左上角。然后使用np.ifft2()函数找到逆FFT。同样,结果将是一个复数。您可以采用其绝对值。

rows, cols = img.shape
crow,ccol = rows//2 , cols//2
fshift[crow-30:crow+31, ccol-30:ccol+31] = 0
f_ishift = np.fft.ifftshift(fshift)
img_back = np.fft.ifft2(f_ishift)
img_back = np.real(img_back)
plt.subplot(131),plt.imshow(img, cmap = 'gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(132),plt.imshow(img_back, cmap = 'gray')
plt.title('Image after HPF'), plt.xticks([]), plt.yticks([])
plt.subplot(133),plt.imshow(img_back)
plt.title('Result in JET'), plt.xticks([]), plt.yticks([])
plt.show()

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

Numpy实现逆傅里叶变换

在对频谱图进行处理之后,我们需要还原图像,这里就需要傅里叶逆变换,代码如下:

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
path = r'D:\Laboratory\Study\Computer Vision\opencv4-python\qingshi.png'  
img = cv.imread(path)
# numpy实现傅里叶变换
f = np.fft.fft2(img)       #实现傅里叶变化,返回复数数组
fshift = np.fft.fftshift(f)    #将零频率分量移动到频谱中心
ishift = np.fft.ifftshift(fshift)  #将零频率移动回左上角(逆变换)
iimg = np.fft.ifft2(ishift)        #逆傅里叶变换
iimg = np.abs(iimg)
cv.imshow('xx',iimg)
plt.subplot(121),plt.imshow(img, cmap = 'gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(iimg, cmap = 'gray')
plt.title('xx'), plt.xticks([]), plt.yticks([])
plt.show()

这里没有对图像做任何吃力,所以两幅图一模一样。

在这里插入图片描述

在频域进行高通滤波

高通滤波用来去除低频信息,也就是提取边缘。也就是对频谱图中心的高亮区域进行滤波,将其灰度值变大。
代码如下:

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
path = r'D:\Laboratory\Study\Computer Vision\opencv4-python\qingshi.png'  
img = cv.imread(path,0)
f = np.fft.fft2(img)      
fshift = np.fft.fftshift(f)       
rows, cols = img.shape
crow,ccol = int(rows/2),int(cols/2)
fshift[crow-30:crow+31, ccol-30:ccol+31] = 0    #将频谱图的中心涂黑
ishift = np.fft.ifftshift(fshift)  #将零频率移动回左上角(逆变换)
iimg = np.fft.ifft2(ishift)        #逆傅里叶变换
iimg = np.abs(iimg)
plt.subplot(121),plt.imshow(img, cmap = 'gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(iimg, cmap = 'gray')
plt.title('xx'), plt.xticks([]), plt.yticks([])
plt.show()

高通滤波的结果:
在这里插入图片描述

Opencv实现傅里叶变换

OpenCV为此提供了cv.dft()和cv.idft()函数。它返回与前一个相同的结果,但是有两个通道。第一个通道是结果的实部,第二个通道是结果的虚部。输入图像首先应转换为np.float32。我们来看看怎么做。

import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
path = r'D:\Laboratory\Study\Computer Vision\opencv4-python\qingshi.png'  
img = cv.imread(path,0)
#opencv中原始图像需要转换成float格式;cv.DFT_COMPLEX_OUTPUT:指定输出类型
dft = cv.dft(np.float32(img),flags = cv.DFT_COMPLEX_OUTPUT)   #得到频谱值,双通道:实数;虚数
dft_shift = np.fft.fftshift(dft)       #低频移到中心
# cv.magnitude:将双通道的数据集转换到0-255
magnitude_spectrum = 20*np.log(cv.magnitude(dft_shift[:,:,0],dft_shift[:,:,1]))  
plt.subplot(121),plt.imshow(img, cmap = 'gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(magnitude_spectrum, cmap = 'gray')
plt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([])
plt.show()

结果如下:
在这里插入图片描述

Opencv实现逆傅里叶变换

opencv的逆傅里叶变换和numy的一样,多了一步使用magnitude聚合,代码如下:

import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
path = r'D:\Laboratory\Study\Computer Vision\opencv4-python\qingshi.png'  
img = cv.imread(path,0)
#正傅里叶变换
dft = cv.dft(np.float32(img),flags = cv.DFT_COMPLEX_OUTPUT)   
fshift = np.fft.fftshift(dft)
#逆傅里叶变换
ishift = np.fft.ifftshift(fshift)
iimg = cv.idft(ishift)
iimg = cv.magnitude(iimg[:,:,0],iimg[:,:,1])
plt.subplot(121),plt.imshow(img, cmap = 'gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(iimg, cmap = 'gray')
plt.title('xx'), plt.xticks([]), plt.yticks([])
plt.show()

在频域进行低通滤波

原理和高通滤波器一样,只不过是中心框内的像素值为白色

#%%低通滤波器
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
path = r'D:\Laboratory\Study\Computer Vision\opencv4-python\333.jpg'  
img = cv.imread(path,0)
#提取频谱图
dft = cv.dft(np.float32(img),flags = cv.DFT_COMPLEX_OUTPUT)   
fshift = np.fft.fftshift(dft)
#低通滤波器       
rows, cols = img.shape
crow,ccol = int(rows/2),int(cols/2)
mask = np.zeros((rows,cols,2),np.uint8)
mask[crow-30:crow+31, ccol-30:ccol+31] = 1    #将频谱图的中心涂白
ishift = fshift*mask
ishift = np.fft.ifftshift(fshift)  #将零频率移动回左上角(逆变换)
iimg = cv.idft(ishift)
iimg = cv.magnitude(iimg[:,:,0],iimg[:,:,1])
plt.subplot(121),plt.imshow(img, cmap = 'gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(iimg, cmap = 'gray')
plt.title('xx'), plt.xticks([]), plt.yticks([])
plt.show()

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值