离散傅里叶变换
opencv常见的图像变换: 本质上是从输入图像到输出图像的映射,既输出仍然是一副图像。
本章将图像转换为完全不同的表现方式: 新的表现方式仍然是一些数组,只是这些数组中的值在含义上将与原图像中的强度值大不相同,比如离散傅里叶变换,它的输出图像仍然是数组,只不过是输入图像的频域表示( 时域图像转换到频域时是以复数的形式存在,变换后的结果需要使用实数图像和虚数图像,或幅度图像加相位图像的形式)。
对于任意以离散参数为索引的数值集合,都可以通过与连续傅里叶变换相似的方法来定义离散傅里叶变换(DFT)。一般项数为N的变换预计需要O(N**2)次运算。实际上有几种快速傅里叶变换(FFT)算法可以在低复杂度下做计算。
常用的图像变换:傅里叶变换、离散余弦变换。(两者都属于正交变换,正交变换可将任意周期波形分解为正弦波的加权和,将非周期变换分解成正弦波和余弦波的加权)
一、傅里叶变换
1.1 离散傅里叶变换cv2.dft()
cv2.dft()可以计算一维和二维输入数组的FFT(快速傅里叶变换)。
dst= cv2. dft(src, flags=None, nonzeroRows=None)
FFT变换默认生成CCS格式(复数共轭对)的输出,输出数组的大小与输入数组完全相同,但是深度为2。但是可以通过使用标识flags=cv2.DFT_COMPLEX_OUTPUT获得一个复数组。使用复数组进行逆变换时,结果也是一个复数组
参数 | 含义 |
---|---|
src | 输入图像数组,必须为浮点型 |
flags=None | 指明要完成的操作.cv2.DFT_COMPLEX_OUTPUT |
nonzeroRows=None | 指明有效数据的行数来节省计算时间。因为有时可能输入数组是经过0填充的 |
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 第一步读取图片
img = cv2.imread('D:\Project\Opencv\Learning03\image04.jpg', 0)
# 第二步:进行float32形式转换
float32_img = np.float32(img)
# 第三步: 使用cv2.dft进行傅里叶变化
dft_img = cv2.dft(float32_img, flags=cv2.DFT_COMPLEX_OUTPUT)
# 第四步:使用np.fft.shiftfft()将变化后的图像的低频转移到中心位置
dft_img_ce = np.fft.fftshift(dft_img)
# 第五步:使用cv2.magnitude将实部和虚部转换为实部(矩阵平方根),乘以20是为了使得结果更大
img_dft = 20 * np.log(cv2.magnitude(dft_img_ce[:, :, 0], dft_img_ce[:, :, 1]))
# 第六步:进行画图操作
plt.subplot(121)
plt.imshow(img, cmap='gray')
plt.subplot(122)
plt.imshow(img_dft, cmap='gray')
plt.show()
1.2 离散傅里叶逆变换cv2.idft()
cv2.dft()可以计算一维和二维输入数组的FFT(快速傅里叶变换)。
dst= cv2. idft(src, flags=None, nonzeroRows=None)
参数 | 含义 |
---|---|
src | |
flags=None | 指明要完成的操作 |
nonzeroRows=None | 指明有效数据的行数来节省计算时间。因为有时可能输入数组是经过0填充的 |
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 第一步读取图片
img = cv2.imread('D:\Project\Opencv\Learning03\image04.jpg', 0)
# 第二步:进行float32形式转换
float32_img = np.float32(img)
# 第三步: 使用cv2.dft进行傅里叶变化
dft_img = cv2.dft(float32_img, flags=cv2.DFT_COMPLEX_OUTPUT)
# 第四步:使用np.fft.shiftfft()将变化后的图像的低频转移到中心位置
dft_img_ce = np.fft.fftshift(dft_img)
# 第五步:使用cv2.magnitude将实部和虚部转换为实部,乘以20是为了使得结果更大
magnitude_spectrum= 20 * np.log(cv2.magnitude(dft_img_ce[:, :, 0], dft_img_ce[:, :, 1]))
'''离散傅里叶逆变换'''
rows,cols = img.shape
crow,ccol = int(rows/2),int(cols/2)
mask = np.zeros((rows,cols,2),np.uint8)
mask[crow-30:crow+30,ccol-30:ccol+30] = 1
fshift = dft_img_ce*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(121),plt.imshow(img,cmap = 'gray')
plt.title('Input Image'),plt.xticks([]),plt.yticks([])
plt.subplot(122),plt.imshow(img_back,cmap = 'gray')
plt.title('cv2.idft()'),plt.xticks([]),plt.yticks([])
plt.show()
二、频谱乘法cv2.mulSpectrums()
大多数傅里叶变换中,必须计算两个频谱的逐元素乘积,傅里叶变换的结果一般是复数,通常为高密度的CCS格式,这种情况下要进行解析并进行矩阵乘法是很频繁的。cv2.mulSpectrums()函数实现了这个功能。
dst= cv2.mulSpectrums(a, b, flags, conjB=None)
参数 | 含义 |
---|---|
a | 第1个输入数组,必须为CCS格式单通道频谱或双通道复数频谱,可从cv2.dft得到。 |
b | 第2个输入数组,必须为CCS格式单通道频谱或双通道复数频谱,可从cv2.dft得到。 |
flags=None | 支持的唯一标志是cv :: DFT_ROWS,它指示src1和src2的每一行都是独立的一维傅立叶频谱。 如果您不想使用该标志,则只需添加一个“ 0” |
conjB=None | 设置为False实现了源数组的乘法,设置为True实现了前一个数组的元素与第二个数组的复共轭的乘法。 |
三、使用傅里叶变换进行卷积
首先计算图像的傅里叶变换,然后计算卷积滤波器的傅里叶变换,一旦完成在变换空间中完成卷积的时间就能缩减到与图像像素成线性。
四、离散余弦变换
4.1 离散余弦变换cv2. dct()
dst= cv2. dct(src, flags=None)
参数 | 含义 |
---|---|
src | 输入数组,浮点类型,并且输入数组的大小必须是偶数,如果不是偶数可以在数组最后补0使其变为偶数。 |
flags=None | 转换标志 |
4.2 离散余弦逆变换cv2. idct()
dst= cv2. idct(src, flags=None)
参数 | 含义 |
---|---|
src | 输入浮点类型的单通道数组。 |
flags=None | 操作标志 |