opencv教程(基于python)----图象傅里叶变换

首先说的是关于图象的傅里叶变化,这个数学概念只有部分工科的专业才学,大家可以自己上网看一下。
傅里叶变化通常用来分析不同滤波器的频率特征,我们使用离散傅里叶变换来分析图形的频域特征。实现DFT的一个快速算法被称为快速傅里叶变换(FFT)。
对于之歌正选信号(那种最普通的,scdn弄不出来公式,大家脑补吧。)她频率为f,如果把这个信号转到它的频域表示,我们会在频率f中看到一个峰值。如果我们的信号是采样产生的离散信号组成,我们会看到类似的频谱图,只不过是离散的。
我们对图象进行x方向和y方向的傅里叶变换,我们会得到这幅图象的频谱图 。
更直观一点,图象中的噪声和边界一般是频谱图中的高频分量,没有这么大幅度的我们称之为低频分量。
这里我先用numpy的函数求出频谱图。这里用到的是numpy的fft模块,提供了快速傅里叶变换的功能,在这个模块里很多函数都存在对应的逆操作。

numpy.fft.fft(a, n=None, axis=-1, norm=None)#计算一维的傅里叶变换
numpy.fft.ifft(a, n=None, axis=-1, norm=None)#上面函数的逆操作
numpy.fft.fft2(a, n=None, axis=-1, norm=None)#计算二维的傅里叶变换
numpy.fft.fftn#计算n维的傅里叶变换
numpy.fft.rfftn#计算n维实数的傅里叶变换
numpy.fft.fftfreq#返回傅里叶变换的采样频率
np.fft.fftshift#将FFT输出中的直流分量移动到频谱的中央

下面就是

import cv2
import numpy as np
import matplotlib.pyplot as plt
img1=cv2.imread('C:/Users/dell/Desktop/00.jpg',0)
f=np.fft.fft2(img1)
fshift=np.fft.fftshift(f)
#之所以要进行对数转换是因为傅里叶变换后的结果对于在显示器显示来讲范围比较大,这样的话对于一些小的变化或者是高的变换值不能进行观察
magnitude_spectrum=20*np.log(np.abs(fshift))
plt.subplot(1,2,1),plt.imshow(img1)
plt.title('input image by numpy'),plt.xticks([]),plt.yticks([])
plt.subplot(1,2,2),plt.imshow(magnitude_spectrum)
plt.title('magnitude spectrum by numpy'),plt.xticks([]),plt.yticks([])
plt.show()

opencv教程(基于python)----图象傅里叶变换_第1张图片
当然用opencv的函数速度会更快一点。

cv2.dft(src, dst=None, flags=None, nonzeroRows=None)

  • 第一个参数是输入图象。
  • dst是输出的大小和尺寸
  • flags是转换的标志
    • DFT _INVERSE执行反向一维或二维转换,而不是默认的正向转换
    • DFT _SCALE缩放结果:由阵列元素的数量除以它。通常情况下,它是结合在一起的
    • DFT _ROWS执行正向或反向变换所述输入矩阵的每个单独的行的; 该标志使您能够同时转换多个矢量,并可用于减少开销(有时甚至比处理本身大几倍)以执行3D和更高维度的转换等等
    • DFT _COMPLEX_OUTPUT执行1D或2D实数组的正向转换; 结果虽然是一个复杂的数组,但具有复共轭对称性,这样的数组可以打包成一个与输入大小相同的实数组,这是最快的选择,这是默认的功能。然而,你可能希望得到一个完整的复杂数组(为了更简单的频谱分析) - 传递该标志以使该函数能够产生全尺寸的复数输出数组
    • DFT _REAL_OUTPUT执行一维或二维复数阵列的逆变换; 结果通常是相同大小的复数数组,但是,如果输入数组具有共轭复数对称性(例如,它是带有 标志的正向变换的结果 ),则输出为真实数组; 而函数本身并不检查输入是否对称,可以通过标志,然后函数将假设对称,并产生实际的输出数组(注意,当输入被打包成一个实数组,并且逆变换为该函数将输入视为一个打包的复共轭对称数组,输出也将是一个实数组)
  • nonzeroRows - 当参数不为零时,函数假定只有nonzeroRows输入数组的第一行(未设置)或者只有输出数组的第一个(设置)包含非零,因此函数可以处理其余的行更有效率,并节省一些时间; 这种技术对计算阵列互相关或使用DFT卷积非常有用
import cv2
import numpy as np
import matplotlib.pyplot as plt
img1=cv2.imread('C:/Users/dell/Desktop/00.jpg',0)
dft=cv2.dft(np.float32(img1),flags=cv2.DFT_COMPLEX_OUTPUT)
dft_shift=np.fft.fftshift(dft)
magnitude_spectrum=20*np.log(cv2.magnitude(dft_shift[:,:,0],dft_shift[:,:,1]))
plt.subplot(1,2,1),plt.imshow(img1)
plt.title('input image'),plt.xticks([]),plt.yticks([])
plt.subplot(1,2,2),plt.imshow(magnitude_spectrum)
plt.title('magnitude spectrum'),plt.xticks([]),plt.yticks([])
plt.show()

opencv教程(基于python)----图象傅里叶变换_第2张图片
其实图片的效果是一样的。


我们要在画出频谱图的基础上对图象在频域上进行操作,然后在傅里叶逆变换回去。第一个了解的是高通滤波去除低频部分,通常可以求出边界来

import cv2
import numpy as np
import matplotlib.pyplot as plt
img1=cv2.imread('C:/Users/dell/Desktop/00.jpg',0)
f=np.fft.fft2(img1)
fshift=np.fft.fftshift(f)
rows,cols=img1.shape
crow,ccol=np.ceil(rows/2),np.ceil(cols/2)
crow,ccol=np.int(crow),np.int(ccol)
#注意fshift是用来与原图像进行掩模操作的但是具体的,我也看着很抽象。这一部分与低通的有些相对的意思。
fshift[crow-30:crow+30,ccol-30:ccol+30]=0
f_ishift=np.fft.ifftshift(fshift)
img_back=np.fft.ifft2(fshift)
img_back=np.abs(img_back)
plt.subplot(1,2,1),plt.imshow(img1)
plt.title('input image'),plt.xticks([]),plt.yticks([])
plt.subplot(1,2,2),plt.imshow(img_back)
plt.title('image after HPF'),plt.xticks([]),plt.yticks([])
plt.show()

opencv教程(基于python)----图象傅里叶变换_第3张图片
接下来我们实现的是低通滤波将gapin部分除去,实际上就是对图象进行模糊操作。

import cv2
import numpy as np
import matplotlib.pyplot as plt
img1=cv2.imread('C:/Users/dell/Desktop/00.jpg',0)
dft=cv2.dft(np.float32(img1),flags=cv2.DFT_COMPLEX_OUTPUT)
dft_shift=np.fft.fftshift(dft)
magnitude_spectrum=20*np.log(cv2.magnitude(dft_shift[:,:,0],dft_shift[:,:,1]))
rows,cols=img1.shape
#下面有对数据的取整还有数据类型转换的操作,否则mask会出问题
crow,ccol=np.ceil(rows/2),np.ceil(cols/2)
crow,ccol=np.int(crow),np.int(ccol)
mask=np.zeros((rows,cols,2),np.uint8)
mask[crow-30:crow+30,ccol-30:ccol+30]=1
fshift=dft_shift*mask
f_ishift=np.fft.ifftshift(fshift)
img_back=cv2.idft(f_ishift)
img_back=cv2.magnitude(img_back[:,:,0],img_back[:,:,1])
plt.subplot(1,2,1),plt.imshow(img1)
plt.title('input image'),plt.xticks([]),plt.yticks([])
plt.subplot(1,2,2),plt.imshow(img_back)
plt.title('magnitude spectrum'),plt.xticks([]),plt.yticks([])
plt.show()

opencv教程(基于python)----图象傅里叶变换_第4张图片

你可能感兴趣的:(opencv教程(基于python)----图象傅里叶变换)