04 数字图像技术——图像特征提取之实验结果与分析
03 数字图像技术——频域滤波实验结果与分析
02 数字图像技术——颜色空间转换与颜色空间分割实验结果与分析
01 数字图像基本操作——图像采样、量化、算术运算、点运算实验结果及分析
一、实验目的
1.了解图像变换的意义和手段;
2.熟悉傅里叶变换的基本性质;
3.熟练掌握FFT变换方法及应用;
4.通过实验了解二维频谱的分布特点;
5.通过本实验掌握利用python编程实现数字图像的傅里叶变换。
二、实验内容
1. 实现数字图像的FFT变换。
2. 掌握图像FFT变换的性质。
3. 图像FFT变换的性质体现规律和特点分析。
4. 实现低通滤波器。
三、实验设备/仪器
电脑、编程语言(Matlab或Python)、图像数据和存储器。
四、实验原理
1.应用傅里叶变换进行图像处理
傅里叶变换是线性系统分析的一个有力工具,它能够定量地分析诸如数字化系统、采样点、电子放大器、卷积滤波器、噪音和显示点等的作用。通过实验培养这项技能,将有助于解决大多数图像处理问题。对任何想在工作中有效应用数字图像处理技术的人来说,把时间用在学习和掌握博里叶变换上是很有必要的。
2.傅里叶(Fourier)变换的定义
对于二维信号,二维Fourier变换定义为:
逆变换:
二维离散傅里叶变换为:
逆变换:
图像的傅立叶变换与一维信号的傅立叶变换变换一样,有快速算法,具体参见参考书目,有关傅立叶变换的快速算法的程序不难找到。实际上,现在有实现傅立叶变换的芯片,可以实时实现傅立叶变换。
五、实验步骤与要求
- 编写python代码,实现一维信号的傅里叶变换;
- 编写python代码,实现图像的二维傅里叶变换;
- 编写python代码,实现理想低通滤波器;
- 编写python代码,实现巴特沃斯低通滤波器。
- 记录和整理实验报告。
六、各实验流程图、结果及分析
1. 编写python代码,实现一维信号的傅里叶变换;
代码如下:
import matplotlib.pyplot as plt
import numpy as np
"""中文显示工具函数"""
def set_ch():from pylab import mplmpl.rcParams['font.sans-serif']=['FangSong']mpl.rcParams['axes.unicode_minus']=False
set_ch()
def show(ori_func, ft, sampling_period = 5):n = len(ori_func)interval = sampling_period / n# 绘制原始函数plt.subplot(2, 1, 1)plt.plot(np.arange(0, sampling_period, interval), ori_func, 'black')plt.xlabel('时间'), plt.ylabel('振幅')plt.title('原始信号')# 绘制变换后的函数plt.subplot(2,1,2)frequency = np.arange(n / 2) / (n * interval)nfft = abs(ft[range(int(n / 2))] / n )plt.plot(frequency, nfft, 'red')plt.xlabel('频率 (Hz)'), plt.ylabel('频率谱')plt.title('傅里叶变换结果')plt.show()#生成频率为 1(角速度为 2 * pi)的正弦波
time = np.arange(0, 5, .005)
x = np.sin(2 * np.pi * 1 * time)
y = np.fft.fft(x)
show(x, y)
x2 = np.sin(2 * np.pi * 10 * time)
x3 = np.sin(2 * np.pi * 40 * time)
x+=x2+x3
y = np.fft.fft(x)
show(x, y)
从图中可以看出,这三个正弦波形进行叠加得出的图像都具备了各自波形的特点,当进行傅里叶变化时,每个基函数都是一个单频率谐波。
2. 编写python代码,实现图像的二维傅里叶变换;
代码如下:
from skimage import data,io,color
import numpy as np
from matplotlib import pyplot as plt
import cv2 as cv
"""中文显示工具函数"""
def set_ch():from pylab import mplmpl.rcParams['font.sans-serif']=['FangSong']mpl.rcParams['axes.unicode_minus']=False
set_ch()
# img = data.camera()
#img = io.imread('D:\shuzi_image\cat.jpg')
img = cv.imread('D:\shuzi_image\cat.jpg')
img=color.rgb2gray(img)
f = np.fft.fft2(img) # 快速傅里叶变换算法得到频率分布
fshift = np.fft.fftshift(f) # 默认结果中心点位置是在左上角,转移到中间位置
fimg = np.log(np.abs(fshift)) # fft 结果是复数,求绝对值结果才是振幅
# 展示结果
plt.subplot(121), plt.imshow(img, 'gray'), plt.title('原始图像')
#plt.subplot(122), plt.imshow(fimg, 'gray'), plt.title('傅里叶频谱')
plt.subplot(122)
fimg=fimg.astype(np.uint8)
cv.namedWindow('image')
cv.imshow("image",fimg*23)
cv.waitKey()
plt.show()
当默认结果中心点位置是在左上角时,结果如下:
默认结果中心点位置是在左上角,转移到中间位置时的结果如下:
可得到:变换之后的图像在原点平移之前四角是低频,最亮,平移之后中间部分是低频,最亮,亮度大说明低频的能量大。
棋盘图像对应的傅里叶变换代码如下:
from skimage import data
import numpy as np
from matplotlib import pyplot as plt
"""中文显示工具函数"""
def set_ch():from pylab import mplmpl.rcParams['font.sans-serif']=['FangSong']mpl.rcParams['axes.unicode_minus']=False
set_ch()img = data.checkerboard()
f = np.fft.fft2(img) # 快速傅里叶变换算法得到频率分布
fshift = np.fft.fftshift(f) # 默认结果中心点位置是在左上角,转移到中间位置
fimg = np.log(np.abs(fshift)) # fft 结果是复数,求绝对值结果才是振幅
# 展示结果
plt.subplot(121), plt.imshow(img, 'gray'), plt.title('原始图像')
plt.subplot(122), plt.imshow(fimg, 'gray'), plt.title('傅里叶频谱')
plt.show()
使用两次一维傅里叶变换代替二维傅里叶变换的代码如下:
from matplotlib import pyplot as plt
import numpy as np
from skimage import data, color,io
import cv2 as cv# 中文显示工具函数
def set_ch():from pylab import mplmpl.rcParams['font.sans-serif'] = ['FangSong']mpl.rcParams['axes.unicode_minus'] = Falseset_ch()
img1 = io.imread('D:\shuzi_image\cat.jpg')
img = color.rgb2gray(img1)
# 在X方向实现傅里叶变换
m, n = img.shape
fx = img
for 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)
# fft结果是复数,求绝对值结果才是振幅
fimg = np.log(np.abs(fshift))# 展示结果
plt.subplot(121), plt.imshow(img1, 'gray'), plt.title('原始图像')
plt.subplot(122), plt.imshow(fimg, 'gray'), plt.title('两次一维傅里叶变换的图像')
plt.show()
分析:图像经傅里叶变换后,直流分量与图像均值成正比,高频分量则表明了图像中目标边缘的强度及方向。二维离散傅里叶变换,可视为由沿着x、y方向的两个一维傅里叶变换所构成。这一性质可有效降低二维傅里叶变换的计算复杂性,而且得到效果和一般图像的二维傅里叶变换结果一样。
3. 编写python代码,实现理想低通滤波器;
代码如下:
#导入相关库
from skimage import data,color,io
import numpy as np
import matplotlib.pyplot as plt
import cv2 as cv
"""中文显示工具函数"""
def set_ch():from pylab import mplmpl.rcParams['font.sans-serif']=['FangSong']mpl.rcParams['axes.unicode_minus']=False
set_ch()D=10
#读入图片
#new_img=data.coffee()new_img = io.imread('D:\shuzi_image\cat.jpg')
new_img=color.rgb2gray(new_img)#numpy中的傅里叶变化
f1=np.fft.fft2(new_img)
f1_shift=np.fft.fftshift(f1)
#np.fft.fftshift()函数来实现平移,让直流分量在输出图像的重心#实现理想低通滤波器
rows,cols=new_img.shape
crow,ccol=int(rows/2),int(cols/2) #计算频谱中心
mask=np.zeros((rows,cols),np.uint8) #生成rows行cols的矩阵,数据格式为uint8
for i in range(rows):for j in range(cols):if np.sqrt(i*i+j*j)<=D:# 将距离频谱中心小于D的部分低通信息 设置为1,属于低通滤波mask[crow - D:crow + D, ccol - D:ccol + D] = 1# img = np.zeros((200, 200), dtype = np.uint8) #创建黑色空白图像
# img[50:150, 50:150] = 255 # 图像中央放置白色方块f1_shift=f1_shift*mask
cv.imshow("mask",mask*255)
cv.waitKey(0)
#傅里叶逆变换
f_ishift=np.fft.ifftshift(f1_shift)
img_back=np.fft.ifft2(f_ishift)
img_back=np.abs(img_back)
img_back=(img_back-np.amin(img_back))/(np.amax(img_back)-np.amin(img_back))#plt.figure(figsize=(15,8))
plt.figure()
plt.subplot(121),plt.imshow(new_img,cmap='gray'),plt.title('原始图像')
plt.subplot(122),plt.imshow(img_back,cmap='gray'),plt.title('滤波后图像')
plt.show()
当截断频率D设置为100时:
当截断频率D设置为10时:
从实验可以看出当截断频率D设置得越大时,中心频谱的范围越大,即更多的频率分量可以完全无损的通过,图像越清晰。当D设置得越小时,滤波后的图像越模糊。
4. 编写python代码,实现巴特沃斯低通滤波器。
代码如下:
import numpy as np
import matplotlib.pyplot as plt
import numpy as np
from skimage import data,color,ioif __name__ == "__main__":#img = data.coffee()img = io.imread('D:\shuzi_image\cat.jpg')img=color.rgb2gray(img)#直接读为灰度图像f = np.fft.fft2(img)fshift = np.fft.fftshift(f)#取绝对值:将复数变化成实数#取对数的目的为了将数据变化到0-255s1 = np.log(np.abs(fshift))"""巴特沃斯低通滤波器"""def butterworthPassFilter(image, d, n):f = np.fft.fft2(image)fshift = np.fft.fftshift(f)def make_transform_matrix(d):transfor_matrix = np.zeros(image.shape)center_point = tuple(map(lambda x: (x - 1) / 2, s1.shape))for i in range(transfor_matrix.shape[0]):for j in range(transfor_matrix.shape[1]):def cal_distance(pa, pb):from math import sqrtdis = sqrt((pa[0] - pb[0]) ** 2 + (pa[1] - pb[1]) ** 2)return disdis = cal_distance(center_point, (i, j))transfor_matrix[i, j] = 1 / (1 + (dis / d) ** (2*n))return transfor_matrixd_matrix = make_transform_matrix(d)new_img = np.abs(np.fft.ifft2(np.fft.ifftshift(fshift * d_matrix)))return new_imgplt.subplot(221)plt.axis("off")plt.title('Original')plt.imshow(img,cmap='gray')plt.subplot(222)plt.axis('off')plt.title('Butter D=100 n=1')butter_100_1=butterworthPassFilter(img,100,1)plt.imshow(butter_100_1,cmap='gray')plt.subplot(223)plt.axis('off')plt.title('Butter D=40 n=1')butter_30_1=butterworthPassFilter(img,40,3)plt.imshow(butter_30_1,cmap='gray')plt.subplot(224)plt.axis('off')plt.title('Butter D=40 n=5')butter_30_5=butterworthPassFilter(img,40,5)plt.imshow(butter_30_5,cmap='gray')
plt.show()
当设置不同的截断频率D,和不同的函数的阶n时,图像的结果如下:
从实验中可以看出,用此滤波后的输出图像振铃现象不明显。n=1时,过渡最平滑,即尾部包含有大量的高频成分,所以一阶低通滤波器没有振铃现象;但随着n的增加,振铃现象会越来越明显,而且当截止频率D设置得越小时,滤波后的图像越模糊。
七、实验总结
- (1)傅里叶变换是一种正交数学变换,可以将一维信号或函数分解为具有不同频率、不同幅度的正弦信号或余弦信号的组合。几乎“所有”信号或函数都可以分解成简单的正弦波和余弦波之和。
- (2)二维傅里叶变换本质是将一维变换向二维进行拓展。图像经傅里叶变换后,直流分量与图像均值成正比,高频分量则表明了图像中目标边缘的强度及方向。二维离散傅里叶变换,可视为由沿着x、y方向的两个一维傅里叶变换所构成。这一性质可有效降低二维傅里叶变换的计算复杂性,而且得到效果和一般图像的二维傅里叶变换结果一样。
- (3)理想低通滤波器的含小于D的频率,即以D为半径的圆内的有频率分量可以完全无损地通过,而圆外的频率,即大于D的频率分量则完全被除掉。理想低通滤波器的平滑作用非常明显,当截断频率D设置得越大时,中心频谱的范围越大,即更多的频率分量可以完全无损的通过,图像越清晰。当D设置得越小时,出现了明显的振铃现象,滤波后的图像越模糊。
- (4)与理想低通滤波器相比,高低频之间过渡较为平滑,用此滤波后的输出图像振铃现象不明显。n=1时,过渡最平滑,即尾部包含有大量的高频成分,所以一阶Butterworth低通滤波器没有振铃现象;但随着n的增加,振铃现象会越来越明显。