04 数字图像技术——图像特征提取之实验结果与分析
03 数字图像技术——频域滤波实验结果与分析
02 数字图像技术——颜色空间转换与颜色空间分割实验结果与分析
01 数字图像基本操作——图像采样、量化、算术运算、点运算实验结果及分析
1.了解图像变换的意义和手段;
2.熟悉傅里叶变换的基本性质;
3.熟练掌握FFT变换方法及应用;
4.通过实验了解二维频谱的分布特点;
5.通过本实验掌握利用python编程实现数字图像的傅里叶变换。
1. 实现数字图像的FFT变换。
2. 掌握图像FFT变换的性质。
3. 图像FFT变换的性质体现规律和特点分析。
4. 实现低通滤波器。
电脑、编程语言(Matlab或Python)、图像数据和存储器。
1.应用傅里叶变换进行图像处理
傅里叶变换是线性系统分析的一个有力工具,它能够定量地分析诸如数字化系统、采样点、电子放大器、卷积滤波器、噪音和显示点等的作用。通过实验培养这项技能,将有助于解决大多数图像处理问题。对任何想在工作中有效应用数字图像处理技术的人来说,把时间用在学习和掌握博里叶变换上是很有必要的。
2.傅里叶(Fourier)变换的定义
对于二维信号,二维Fourier变换定义为:
图像的傅立叶变换与一维信号的傅立叶变换变换一样,有快速算法,具体参见参考书目,有关傅立叶变换的快速算法的程序不难找到。实际上,现在有实现傅立叶变换的芯片,可以实时实现傅立叶变换。
代码如下:
import matplotlib.pyplot as plt
import numpy as np
"""中文显示工具函数"""
def set_ch():
from pylab import mpl
mpl.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)
代码如下:
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 mpl
mpl.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 mpl
mpl.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 mpl
mpl.rcParams['font.sans-serif'] = ['FangSong']
mpl.rcParams['axes.unicode_minus'] = False
set_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()
代码如下:
#导入相关库
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 mpl
mpl.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设置得越大时,中心频谱的范围越大,即更多的频率分量可以完全无损的通过,图像越清晰。当D设置得越小时,滤波后的图像越模糊。
代码如下:
import numpy as np
import matplotlib.pyplot as plt
import numpy as np
from skimage import data,color,io
if __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-255
s1 = 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 sqrt
dis = sqrt((pa[0] - pb[0]) ** 2 + (pa[1] - pb[1]) ** 2)
return dis
dis = cal_distance(center_point, (i, j))
transfor_matrix[i, j] = 1 / (1 + (dis / d) ** (2*n))
return transfor_matrix
d_matrix = make_transform_matrix(d)
new_img = np.abs(np.fft.ifft2(np.fft.ifftshift(fshift * d_matrix)))
return new_img
plt.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时,图像的结果如下: