3.2 Python图像的频域图像增强-高通和低通滤波器
3.2 Python图像的频域图像增强-高通和低通滤波器文章目录3.2 Python图像的频域图像增强-高通和低通滤波器1 算法原理1.1理想滤波器1.2巴特沃斯滤波器1.3指数滤波器2 代码3 效果1 算法原理高通和低通滤波器(分别考虑:理想滤波器、巴特沃斯滤波器,指数滤波器)1.1理想滤波器顾名思义,高通滤波器为:让高频信息通过,过滤低频信息;低通滤波相反。低频滤波器,顾名思义,就是过滤掉或者
3.2 Python图像的频域图像增强-高通和低通滤波器
1 算法原理
高通和低通滤波器(分别考虑:理想滤波器、巴特沃斯滤波器,指数滤波器)
1.1理想滤波器
顾名思义,高通滤波器为:让高频信息通过,过滤低频信息;低通滤波相反。低频滤波器,顾名思义,就是过滤掉或者大幅度衰减图像的高频成分,让图像的低频成分通过。低频滤波器可以平滑图像,虑去图像的噪声。而与此相反的高频滤波器,则是过滤低频成分,通过高频成分,可以达到锐化图像的目的。理想低通滤波器的滤波非常尖锐,而高斯低通滤波器的滤波则非常平滑。
Butterworth 低通滤波器则介于两者之间,当 Butterworth 低通滤波器的阶数较高时,接近于理想低通滤波器,阶数较低时,则接近于高斯低通滤波器。理想低通滤波器在以原点为圆心、D0 为半径的园内,通过所有的频率,而在圆外截所有的频率。(圆心的频率最低,为变换的直流(dc)分量)。理想的低通滤波器模板为:
其中,D0 表示通带半径,D(u,v)是到频谱中心的距离(欧式距离),计算
公式如下:
M 和 N 表示频谱图像的大小,(M/2,N/2)即为频谱中心。理想的高通滤波器与此相反,1 减去低通滤波模板即可。
1.2巴特沃斯滤波器
巴特沃斯低通滤波器公式:
D0 为截至频率距原点的距离,D(u,v)是点(u,v)距原点的距离不同于 ILPF,BLPF 变换函数在通带与被滤除的频率之间没有明显的截断。当 D(u,v)=D0 时,H(u,v)=0.5(最大值是 1,当 D(u,v)=0)。随着次数的增加,振铃现象会越来越明显。巴特沃斯高通滤波器的形状与巴特沃斯低通滤波器的形状相反,因为高低频率间平滑过渡,因此振铃现象不明显。
巴特沃斯高通滤波器公式:
在公式中,D(u,v)代表频域当中,点(u,v)到中心点的距离,所以中心点也就是 (M/2,N/2),M 和 N 代表图像的长和宽,那么 D(u,v)就可以用下面的式子来表示了:
而 D0 就是截止距离了,就相当于在频域当中画一个圈,对圈内或者圈外保留就可以达到所谓的低通和高通了,这个 D0 就相当于一维当中的截止频率。
1.3指数滤波器
指数低通滤波器公式为:
指数高通滤波器公式为:
2 代码
运行代码说明
1.要改变代码中的图片地址(地址不能有中文)
更改
put(path)
函数中的路径put(r'../image/image1.jpg')
2.注意最后的
plt.savefig('1.new.jpg')
是保存plt图像,如果不使用可以注释掉
import os
import numpy as np
import cv2
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 理想低通滤波器
def LowPassFilter(img):
"""
理想低通滤波器
"""
# 傅里叶变换
dft = cv2.dft(np.float32(img), flags=cv2.DFT_COMPLEX_OUTPUT)
fshift = np.fft.fftshift(dft)
# 设置低通滤波器
rows, cols = img.shape
crow, ccol = int(rows / 2), int(cols / 2) # 中心位置
mask = np.zeros((rows, cols, 2), np.uint8)
mask[crow - 20:crow + 20, ccol - 20:ccol + 20] = 1
# 掩膜图像和频谱图像乘积
f = fshift * mask
# 傅里叶逆变换
ishift = np.fft.ifftshift(f)
iimg = cv2.idft(ishift)
res = cv2.magnitude(iimg[:, :, 0], iimg[:, :, 1])
return res
# 理想高通滤波器
def HighPassFilter(img):
"""
理想高通滤波器
"""
# 傅里叶变换
f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)
# 设置高通滤波器
rows, cols = img.shape
crow, ccol = int(rows / 2), int(cols / 2)
fshift[crow - 2:crow + 2, ccol - 2:ccol + 2] = 0
# 傅里叶逆变换
ishift = np.fft.ifftshift(fshift)
iimg = np.fft.ifft2(ishift)
iimg = np.abs(iimg)
return iimg
# 巴特沃斯低通滤波器
def ButterworthLowPassFilter(image, d, n, s1):
"""
Butterworth低通滤波器
"""
f = np.fft.fft2(image)
fshift = np.fft.fftshift(f)
def make_transform_matrix(d):
transform_matrix = np.zeros(image.shape)
center_point = tuple(map(lambda x: (x - 1) / 2, s1.shape))
for i in range(transform_matrix.shape[0]):
for j in range(transform_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))
transform_matrix[i, j] = 1 / (1 + (dis / d) ** (2 * n))
return transform_matrix
d_matrix = make_transform_matrix(d)
new_img = np.abs(np.fft.ifft2(np.fft.ifftshift(fshift * d_matrix)))
return new_img
# 巴特沃斯高通滤波器
def ButterworthHighPassFilter(image, d, n, s1):
"""
Butterworth高通滤波器
"""
f = np.fft.fft2(image)
fshift = np.fft.fftshift(f)
def make_transform_matrix(d):
transform_matrix = np.zeros(image.shape)
center_point = tuple(map(lambda x: (x - 1) / 2, s1.shape))
for i in range(transform_matrix.shape[0]):
for j in range(transform_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))
transform_matrix[i, j] = 1 / (1 + (d / dis) ** (2 * n))
return transform_matrix
d_matrix = make_transform_matrix(d)
new_img = np.abs(np.fft.ifft2(np.fft.ifftshift(fshift * d_matrix)))
return new_img
# 指数滤波器
def filter(img, D0, W=None, N=2, type='lp', filter='exponential'):
'''
频域滤波器
Args:
img: 灰度图片
D0: 截止频率
W: 带宽
N: butterworth和指数滤波器的阶数
type: lp, hp, bp, bs即低通、高通、带通、带阻
Returns:
imgback:滤波后的图像
'''
# 离散傅里叶变换
dft = cv2.dft(np.float32(img), flags=cv2.DFT_COMPLEX_OUTPUT)
# 中心化
dtf_shift = np.fft.fftshift(dft)
rows, cols = img.shape
crow, ccol = int(rows / 2), int(cols / 2) # 计算频谱中心
mask = np.ones((rows, cols, 2)) # 生成rows行cols列的2纬矩阵
for i in range(rows):
for j in range(cols):
D = np.sqrt((i - crow) ** 2 + (j - ccol) ** 2)
if (filter.lower() == 'exponential'): # 指数滤波器
if (type == 'lp'):
mask[i, j] = np.exp(-(D / D0) ** (2 * N))
elif (type == 'hp'):
mask[i, j] = np.exp(-(D0 / D) ** (2 * N))
elif (type == 'bs'):
mask[i, j] = np.exp(-(D * W / (D ** 2 - D0 ** 2)) ** (2 * N))
elif (type == 'bp'):
mask[i, j] = np.exp(-((D ** 2 - D0 ** 2) / D * W) ** (2 * N))
else:
assert ('type error')
fshift = dtf_shift * mask
f_ishift = np.fft.ifftshift(fshift)
img_back = cv2.idft(f_ishift)
img_back = cv2.magnitude(img_back[:, :, 0], img_back[:, :, 1]) # 计算像素梯度的绝对值
img_back = np.abs(img_back)
img_back = (img_back - np.amin(img_back)) / (np.amax(img_back) - np.amin(img_back))
return img_back
def put(path):
img = cv2.imread(path, 1)
# img = cv2.imread(os.path.join(base, path), 1)
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)
# 取绝对值后将复数变化为实数 # 取对数的目的是将数据变换到0~255
s1 = np.log(np.abs(fshift))
# 用以中文显示
plt.subplot(331)
plt.axis('off')
plt.title('原始图像')
plt.imshow(img, cmap='gray')
plt.subplot(332)
plt.axis('off')
plt.title('理想低通20')
res1 = LowPassFilter(img)
plt.imshow(res1, cmap='gray')
plt.subplot(333)
plt.axis('off')
plt.title('理想高通2')
res2 = HighPassFilter(img)
plt.imshow(res2, cmap='gray')
plt.subplot(334)
plt.axis('off')
plt.title('原始图像')
plt.imshow(img, cmap='gray')
plt.subplot(335)
plt.axis('off')
plt.title('巴特沃斯低通20')
butter_10_1 = ButterworthLowPassFilter(img, 20, 1, s1)
plt.imshow(butter_10_1, cmap='gray')
plt.subplot(336)
plt.axis('off')
plt.title('巴特沃斯高通2')
butter_2_1_1 = ButterworthHighPassFilter(img, 2, 1, s1)
plt.imshow(butter_2_1_1, cmap='gray')
plt.subplot(337)
plt.axis('off')
plt.title('指数原始图像')
plt.imshow(img, cmap='gray')
plt.subplot(338)
plt.axis('off')
plt.title('指数低通图像20')
img_back = filter(img, 30, type='lp')
plt.imshow(img_back, cmap='gray')
plt.subplot(339)
plt.axis('off')
plt.title('指数高通图像2')
img_back = filter(img, 2, type='hp')
plt.imshow(img_back, cmap='gray')
# plt.savefig('2.new.jpg')
plt.show()
# 处理函数,要传入路径
put(r'../image/image3.jpg')
3 效果
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)