在学习本篇博客之前需要参考
https://blog.csdn.net/GiffordY/article/details/92838671
https://blog.csdn.net/qq_41821067/article/details/111143629
python的numpy中的fft()函数可以进行快速傅里叶变换,
import cv2
import numpy as np
from matplotlib import pyplot as plt
#读取图片的灰色图像
img=cv2.imread("F:/people.png",0)
#对图像进行傅里叶变换,输出结果是一个复杂的组
f=np.fft.fft2(img)
#print(f)
#进行频率变换,得到图像中心频率
fshift=np.fft.fftshift(f)
#构建振幅谱,输出数组绝对值的log
magnitude_spectrum=20*np.log(np.abs(fshift))
#把显示界面分割成1*2的网格,121将参数合起来写,1是行数,2是列数,最后一个1是标号
plt.subplot(121),plt.imshow(img,cmap="gray")#cmap是将标量数据映射成色彩图
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()
#快速傅里叶逆变换
#获取频谱图片的长宽
rows,cols=img.shape
#取频谱图像中心位置
crow,ccol=int(rows/2),int(cols/2)
#以中心为原点,上取30,下取30,设置为0
fshift[crow-30:crow+30,ccol-30:ccol+30]=0
#对图像逆平移,图像从中心变为左上角
f_ishift=np.fft.ifftshift(fshift)
#用快速傅里叶逆变换恢复为空间域图像
img_back=np.fft.ifft2(f_ishift)
#取绝对值?
img_back=np.abs(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()
a=np.zeros((1,2,2))
b=np.zeros((1,2))
print(a)
print(b)
openCV中的傅里叶变换的函数是cv2.dft()和cv2.idft()
import cv2
import numpy as np
from matplotlib import pyplot as plt
#读取图片的灰色图像
img=cv2.imread("F:/people.png",0)
#cv2
#dft函数的输出结果是双通道的,第一个参数是结果的实数部分,第二个是结果的叙述部分
dft=cv2.dft(np.float32(img),flags=cv2.DFT_COMPLEX_OUTPUT)
dft_shift=np.fft.fftshift(dft)
#将实部和虚部都转换为实部,乘以20是扩大值,投射到空间域
magnitude_spectrum=20*np.log(cv2.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()
#cv2的逆dft
rows,cols=img.shape
crow,ccol=int(rows/2),int(cols/2)
#创建一个有固定格式的数组
mask=np.zeros((rows,cols,2),np.uint8)
#中心上取30,下取30,左取30,右取30,设置为1
#与高频对应的部分设置为1
print(mask)
mask[crow-30:crow+30,ccol-30:ccol+30]=1
#与低频对应的地区设置为0
fshift=dft_shift*mask
#将低频区域转移到中间位置
f_ishift=np.fft.ifftshift(fshift)
img_back=cv2.idft(f_ishift)
#使用cv2.magnitude将实部和虚部投影到空间域,将实部和虚部转换为实部
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.subplot(122),plt.imshow(img_back,cmap="gray")
plt.show()
打印的mask的值
dft后的图
逆傅里叶后的图,这里是类似低通滤波器,模糊边缘
数组的大小对DFT的性能有一定的影响,当数组的大小是2的指数或2、3、5的倍数的时候DFT的效率最高。所以要修改输入图像的大小为以上才可以提高代码运行效率
以上可以被cv2.dft()和np.fft.fft2()使用
import cv2
img=cv2.imread('F:\people.png',0)
rows,cols=img.shape
print(rows,cols)
# 返回DFT 最优尺寸大小
nrows=cv2.getOptimalDFTSize(rows)
ncols=cv2.getOptimalDFTSize(cols)
print(nrows,ncols)
可看到数组的大小优原来的(144,93)变为2和3的倍数(144,96),此时数组变大,在Cv2中需要用zeros函数进行补0,在numpy中不需要补0,只需要指定fft运算的大小
import cv2
import numpy as np
img=cv2.imread('F:\people.png',0)
# cv2.imshow("img",img)
# cv2.waitKey()
rows,cols=img.shape
print(rows,cols)
# 返回DFT 最优尺寸大小
nrows=cv2.getOptimalDFTSize(rows)
ncols=cv2.getOptimalDFTSize(cols)
print(nrows,ncols)
#创建一个大小为(nrows,ncols)的0数组
nimg=np.zeros((nrows,ncols))
nimg[:rows,:cols]=img
print(nimg.shape)
我们可看到nimg的大小变为(144,96),说明已经填充0了
right=ncols-cols
bottom=nrows-rows
# 有颜色的常数值边界,还需要value
bordertype=cv2.BORDER_CONSTANT
#value:如果borderType为cv2.BORDER_CONSTANT时需要填充的常数值,这里是0就是填充0
nimg=cv2.copyMakeBorder(img,0,bottom,0,right,bordertype,value=0)
print(nimg)
from timeit import timeit
def test1():
fft1 = np.fft.fft2(img)
print(timeit(stmt=test1,number=1))
def test2():
fft2 = np.fft.fft2(img, [nrows, ncols])
print(timeit(stmt=test2,number=1))
#timeit(np.fft.fft2(img))
#%timeit fft2=np.fft.fft2(img,[nrows,ncols])
# 观察opencv
def test3():
dft1=cv2.dft(np.float32(img),flags=cv2.DFT_COMPLEX_OUTPUT)
def test4():
dft2=cv2.dft(np.float32(nimg),flags=cv2.DFT_COMPLEX_OUTPUT)
print(timeit(stmt=test3,number=1))
print(timeit(stmt=test4,number=1))