注意:文章代码基于notebook实现,也可修改后用于pycharm等编译器。
文章目录
前言一、频域滤波与傅里叶变换二、skimage代码实现1.简单的傅里叶变换:2.不同种类的正弦波及其傅里叶变换频谱图3.二维傅里叶变换4.二维傅里叶变换的性质①可分离性②旋转特性总结前言
本次学习的大致内容:
频域滤波的概念;
傅里叶变换在图像处理中的应用意义;
通过python编程实现对图像的简单傅里叶变换,并显示其频谱图。
代码大多基于skimage实现,所以先在notebook或pycharm中下载安装skimage。
在notebook中执行代码:!pip install scikit-image
即可实现skimage的安装
一、频域滤波与傅里叶变换
著名的法国数学家傅里叶在其著作《热分析理论》中指出:任何周期函数都可以分解为不同频率的正弦或余弦级数的形式,即傅里叶级数。
傅里叶变换从本质上完成了空间信息到频域信息的变换,通过变换将空域信号处理问题转化为频域信号处理。
二、skimage代码实现
1.简单的傅里叶变换:
代码如下:
# 初始化,导入绘图库及工具包import numpy as npimport matplotlib.pyplot as pltx=np.arange(0,4*np.pi,0.01)plt.figure(figsize=(12,16)) # 规定整体图像的大小plt.subplot(421) # 输出图像分块显示,该图为四行两列中的第一张图像y=np.sin(x)*3plt.plot(x,y)plt.title('A')plt.subplot(422)y1=np.sin(3*x)plt.plot(x,y1)plt.title('B')plt.subplot(423)y2=np.sin(x)*3+np.sin(3*x)plt.plot(x,y2)plt.title('A+B')plt.subplot(424)y3=np.sin(5*x)*0.8plt.plot(x,y3)plt.title('C')plt.subplot(425)y3_2=3*np.sin(x)+np.sin(3*x)+np.sin(5*x)*0.8plt.plot(x,y3_2)plt.title('A+B+C')plt.subplot(426)y4=np.sin(7*x)*0.4plt.plot(x,y4)plt.title('D')plt.subplot(427)y4_1=3*np.sin(x)+np.sin(3*x)+np.sin(5*x)*0.8+np.sin(7*x)*0.4plt.plot(x,y4_1)plt.title('A+B+C+D')plt.show()
结果显示如下:
2.不同种类的正弦波及其傅里叶变换频谱图
代码如下:
import numpy as npimport matplotlib.pyplot as plt#导入字体库from matplotlib.font_manager import FontProperties# 此处笔者没有提供simhei.ttf文件,该文件为自行导入的文件font = FontProperties(fname='simhei.ttf', size=13) # 创建字体对象,设置字体大小plt.rcParams['axes.unicode_minus'] = False#字符显示def show(ori_func, ft, sampling_period = 5):n = len(ori_func)interval = sampling_period / n# 绘制原始函数plt.figure(figsize=(16,8))plt.subplot(221)plt.plot(np.arange(0, sampling_period, interval), ori_func, 'black')plt.xlabel('时间/s',fontproperties=font)plt.ylabel('振幅',fontproperties=font)plt.title('原始信号',fontproperties=font)# 绘制变换后的函数plt.subplot(222)frequency = np.arange(n/2) / (n*interval)nfft = abs(ft[range(int(n/2))]/n)plt.plot(frequency, nfft, 'red')plt.xlabel('频率/Hz',fontproperties=font)plt.ylabel('频谱',fontproperties=font)plt.title('傅里叶变换结果',fontproperties=font)plt.show()# 单一正弦波傅里叶变换time = np.arange(0, 5, .005)x = np.sin(2 * np.pi * 1 * time) # 生成频率为1的正弦波y = np.fft.fft(x) # 对其进行傅里叶变换show(x,y)# 对三个正弦波进行叠加,然后进行傅里叶变换x2 = np.sin(2 * np.pi * 20 * time) x3 = np.sin(2 * np.pi * 60 * time)x += x2 + x3 # 将上面频率为1的正弦波与频率为20和60的正弦波叠加起来y = np.fft.fft(x) # 将叠加后的结果进行傅里叶变换show(x,y)# 进行方波的傅里叶变换# 生成方波,振幅是1,频率为10Hz# 由于间隔是0.05s,每秒有200个点,所以需要每隔20个点设为1x = np.zeros(len(time))x[::20] = 1y = np.fft.fft(x)show(x,y)# 进行脉冲波的傅里叶变换x = np.zeros(len(time))x[380:400] = np.arange(0, 1, .05)x[400:420] = np.arange(1, 0, -.05)y = np.fft.fft(x)show(x,y)
结果显示如下:
单一正弦波及其傅里叶变换结果:
3个正弦波叠加波形及其傅里叶变换结果:
方波及其傅里叶变换结果:
脉冲波及其傅里叶变换结果:
3.二维傅里叶变换
在一维傅里叶变换上进行简单扩展。
代码如下:
from skimage import dataimport numpy as np from matplotlib import pyplot as plt # 导入字体库from matplotlib.font_manager import FontPropertiesfont = FontProperties(fname='simhei.ttf', size = 14) #创建字体对象,设置字体大小plt.rcParams['axes.unicode_minus'] = False #字符显示# 导入测试图片img = data.camera()f = np.fft.fft2(img) # 快速傅里叶变换算法得到频率分布fshift = np.fft.fftshift(f) # 默认结果中心点位置是左上角,将其转移到中间位置fimg = np.log(np.abs(fshift)) # fft结果是复数,求其绝对值之后才是振幅# 展示结果plt.figure(figsize=(10,10))plt.subplot(121)plt.imshow(img, 'gray')plt.title('原始图像', FontProperties = font)plt.subplot(122)plt.imshow(fimg, 'gray')plt.title('傅里叶变换图像', FontProperties = font)plt.show()
结果显示如下:
4.二维傅里叶变换的性质
①可分离性
二维离散傅里叶变换可视为由沿x,y方向的两个一维傅里叶变换所构成。
代码如下:
from skimage import io, transform, data, colorimport numpy as np from matplotlib import pyplot as plt # 导入字体库from matplotlib.font_manager import FontProperties# 创建字体对象,设置字体大小font = FontProperties(fname = 'simhei.ttf', size = 16)plt.rcParams['axes.unicode_minus'] = False #显示字符# 导入图像img = data.coffee()img1=imgimg=color.rgb2gray(img)#在x方向实现傅里叶变换m,n=img.shapefx=imgfor x in range(n):fx[:,x]=np.fft.fft(img[:,x])for y in range(m):fx[y,:]=np.fft.fft(img[y,:])fshift = np.fft.fftshift(fx)# 默认结果中心点位置是在左上角,转移到中间位置fimg = np.log(np.abs(fshift)) # fft 结果是复数,求绝对值结果才是振幅# 展示结果plt.subplot(121)plt.imshow(img1, 'gray')plt.title('原图像',fontproperties=font)plt.subplot(122)plt.imshow(fimg, 'gray')plt.title('傅里叶变换图像',fontproperties=font)plt.show()
结果显示如下:
(使用两次一维傅里叶变换代替二维傅里叶变换的结果)
②旋转特性
图像旋转一定角度之后,频谱图像也会得到相应旋转。
根据下面的提示和要求,完成图像的旋转特性的效果展示:
(1)利用函数(np.zero) 生成一个600* 600的单通道图像,并在该图中心生成一个高400宽40的白色矩形;
(2)实现上步中图像的傅里叶变换,并显示其频谱图;
(3)利用旋转函数把第一张图像顺时针旋转45度;
(4)实现旋转后图像的傅里叶变换,并显示其频谱图。
代码如下:
# 初始化,导入包from skimage import io, transform, data, colorimport numpy as np from matplotlib import pyplot as plt # 导入字体库from matplotlib.font_manager import FontProperties# 创建字体对象,设置字体大小font = FontProperties(fname = 'simhei.ttf', size = 16)plt.rcParams['axes.unicode_minus'] = False #显示字符# 利用函数(np.zero)生成一个600* 600的单通道图像,并在该图中心生成一个高400宽100的白色矩形image=np.zeros((600,600),dtype='uint8')for i in range(100,501):for j in range(250,351):image[i,j]=255f=np.fft.fft2(image)fshift = np.fft.fftshift(f)# 默认结果中心点位置是在左上角,转移到中间位置fimg = np.log(np.abs(fshift)) # fft 结果是复数,求绝对值结果才是振幅# 展示结果plt.figure(figsize=(6,8))plt.subplot(121)plt.imshow(image, 'gray')plt.title('单通道图像',fontproperties=font)plt.subplot(122)plt.imshow(fimg, 'gray')plt.title('傅里叶变换图像',fontproperties=font)plt.show()image2 =transform.rotate(image,-45) f=np.fft.fft2(image2)fshift = np.fft.fftshift(f) # 默认结果中心点位置是在左上角,转移到中间位置fimg = np.log(np.abs(fshift)) # fft 结果是复数,求绝对值结果才是振幅# 展示结果plt.figure(figsize=(6,8))plt.subplot(121)plt.imshow(image2, 'gray')plt.title('旋转图像',fontproperties=font)plt.subplot(122)plt.imshow(fimg, 'gray')plt.title('傅里叶变换图像',fontproperties=font)plt.show()
结果显示如下:
总结
以上就是今天要讲的内容,本文简单介绍了图像傅里叶变换基于skimage的代码实现,小伙伴们也可以自行探索,欢迎讨论。