傅里叶变换

图像一般分为空间域处理和频率域处理,空间域处理是直接对图像内的像素进行处理,主要划分为灰度变换、空间滤波两种形式。频率处理是先将图像变换到频率域,然后在频率域对图像进行处理,最后再通过反变换将图像从频率域变换到空间域。傅里叶变换是一种常见的频域变换,它可以实现图像增强、图像去噪、边缘检测、特征提取、图像压缩和加密等。

一:理论基础

法国数学家指出:任何周期函数都可以表示为不同频率的正弦函数和的形式。它有三个关键的要素:频率、振幅、相位。

二:Numpy实现傅里叶变换

1、傅里叶变换

dst=numpy.fft.fft2(src)
dst:返回的复数数组
src:灰度图像

经过上述函数处理后,得到的频谱信息的零频分量位于频谱图像的左上角,为了便于观察,常用numpy.fft.fftshift()函数将零频率成分移动到频谱图像的中心位置。

对图像进行傅里叶变换后,得到的是一个复数数组,为了显示图像,需要将其值调整到[0,255]的灰度空间内,使用公式:新像素值=20*np.log(np.abs(频谱值))

import numpy as np
import cv2
import matplotlib.pyplot as plt

img=cv2.imread("img/13.jpg",0)
f=np.fft.fft2(img)
fshift=np.fft.fftshift(f)
magnitude_spectrum=20*np.log(np.abs(fshift))
plt.subplot(121)
plt.imshow(img,"gray")
plt.title("original")
plt.axis("off")
plt.subplot(122)
plt.imshow(magnitude_spectrum,cmap="gray")
plt.title("result")
plt.axis("off")
plt.show()

傅里叶变换_第1张图片
2、实现逆傅里叶变换

如果在傅里叶变换中使用了numpy.fft.fftshift()函数移动零频率分量,那么在逆傅里叶变换的过程中,需要先使用numpy.fft.ifftshift()函数将零频率分量移动到原来的位置,再进行逆傅里叶变换。而函数numpy.fft.ifft2()可以实现逆傅里叶变换,它返回的是空间域复数数组,我们需要使用np.abs(逆傅里叶变换结果)将其信息调整到[0,255]灰度空间内。

import numpy as np
import cv2
import matplotlib.pyplot as plt

img=cv2.imread("img/13.jpg",0)
f=np.fft.fft2(img)
fshift=np.fft.fftshift(f)
ishift=np.fft.ifftshift(fshift)
img1=np.fft.ifft2(ishift)
img2=np.abs(img1)

plt.subplot(131)
plt.imshow(img,"gray")
plt.title("original")
plt.axis("off")
plt.subplot(132)
plt.imshow(img2,cmap="gray")
plt.title("result")
plt.axis("off")
plt.subplot(133)
img3=img2-img
plt.imshow(img3,"gray")
plt.title("result-original")
plt.axis("off")
plt.show()

傅里叶变换_第2张图片
通过逆傅里叶变换的图片会与原图存在一定的差异(应该是由精度差造成的的),其差值如图result-original

3、高通滤波示例

傅里叶变换_第3张图片
如上图所示,original为原图,中间的result为原图进行傅里叶变换后的频谱图,右侧为对result进行高通滤波后的结果,将傅里叶变换结果图像中的低频信息都替换为0,从而实现高通滤波。

低频信号:图像内变换缓慢的灰度分量
高频信号:图像内变换较快的灰度分量,是由灰度的尖锐过渡造成的。

#############如下所示#################

import numpy as np
import cv2
import matplotlib.pyplot as plt

img=cv2.imread("img/5.jpg",0)
f=np.fft.fft2(img)
fshift=np.fft.fftshift(f)
h,w=img.shape

plt.subplot(121)
plt.imshow(img,"gray")
plt.title("original")
plt.axis("off")

fshift[int(h/2)-5:int(h/2)+5,int(w/2)-5:int(w/2)+5]=0
ifshift=np.fft.ifftshift(fshift)
image=np.fft.ifft2(ifshift)
image=np.abs(image)
plt.subplot(122)
plt.imshow(image,cmap="gray")
plt.title("result")
plt.axis("off")

傅里叶变换_第4张图片

三:Opencv实现傅里叶变换

1、实现傅里叶变换

dst=cv2.dft(src,flags=None)
dst:原始图像的频谱信息
src:"原始图像”,要先使用np.float32()函数将其转换为np.float32格式
flage:通常为"cv2.DFT_COMPLEX_OUTPUT",用于输出一个复数阵列

函数cv2.dft()返回的结果与使用numpy进行傅里叶变换得到的结果是一致的,但它返回的值是双通道的,第一个通道是结果的实数部分,第二个是虚数部分。同时需要使用函数numpy.fft.fftshift()将其零频分量移至频谱中心。此外,为了便于显示以及计算频谱信息幅度,需要使用以下公式进行转换:result=20*np.log(cv2.magnitude(实部,虚部))

import cv2
import numpy as np
import matplotlib.pyplot as plt

img=cv2.imread("img/5.jpg",0)
dft=cv2.dft(np.float32(img),flags=cv2.DFT_COMPLEX_OUTPUT)
dftshift=np.fft.fftshift(dft)
result=20*np.log(cv2.magnitude(dftshift[:,:,0],dftshift[:,:,1]))

plt.subplot(1,2,1)
plt.imshow(img,cmap="gray")
plt.title("original")
plt.axis("off")

plt.subplot(1,2,2)
plt.imshow(result,cmap="gray")
plt.title("result")
plt.axis("off")
plt.show()

傅里叶变换_第5张图片
2、实现逆傅里叶变换

dst=cv2.idft(src)
注:在进行傅里叶变换后,如果使用函数numpy.fft.fftshift()移动了零频率分量,则在进行逆傅里叶变换前,要使用函数numpy.fft.ifftshift()将零频率分量恢复到原来位置。同时,在进行逆傅里叶变换后,得到的仍旧是复数,需要使用函数cv2.magnitude()计算其幅度。

import cv2
import numpy as np
import matplotlib.pyplot as plt

img=cv2.imread("img/5.jpg",0)
dft=cv2.dft(np.float32(img),flags=cv2.DFT_COMPLEX_OUTPUT)
dftshift=np.fft.fftshift(dft)
ishift=np.fft.ifftshift(dftshift)
image=cv2.idft(ishift)
image=cv2.magnitude(image[:,:,0],image[:,:,1])
plt.subplot(1,2,1)
plt.imshow(img,cmap="gray")
plt.title("original")
plt.axis("off")

plt.subplot(1,2,2)
plt.imshow(image,cmap="gray")
plt.title("result")
plt.axis("off")
plt.show()

傅里叶变换_第6张图片
2、低通滤波器示例

import cv2
import numpy as np
import matplotlib.pyplot as plt

img=cv2.imread("img/5.jpg",0)
dft=cv2.dft(np.float32(img),flags=cv2.DFT_COMPLEX_OUTPUT)
dftshift=np.fft.fftshift(dft)
h,w=img.shape
mask=np.zeros((h,w,2),np.uint8)
mask[(int(h/2)-30):(int(h/2)+30),(int(w/2)-30):(int(w/2)+30)]=1
fshift=dftshift*mask

ishift=np.fft.ifftshift(fshift)
image=cv2.idft(ishift)
image=cv2.magnitude(image[:,:,0],image[:,:,1])
plt.subplot(1,2,1)
plt.imshow(img,cmap="gray")
plt.title("original")
plt.axis("off")

plt.subplot(1,2,2)
plt.imshow(image,cmap="gray")
plt.title("result")
plt.axis("off")
plt.show()

傅里叶变换_第7张图片

你可能感兴趣的:(opencv)