傅里叶变换和其图像处理中的应用

以下部分文字资料整合于网络,本文仅供自己学习用!

一、为什么要在频域进行图像处理?

一些在空间域表述困难的增强任务,在频率域中变得非常普通

滤波在频率域更为直观,你想想嘛,所谓滤波,就是把二维图像信号种某个频率信号给去掉。如果定义域是频率,值域是该频率信号的强度(这个坐标体系其实就是频域),直接把对应频率的强度弄为0不就行了,省的还去做卷积(联想空间域的滤波器!是不是得沿着图像走一遭。频域直接啪的一下把这个频率对应的图像信号置为0 ,多简单!)

二、理论知识:傅里叶变换

2.1:先从欧拉公式说起

🍊请记住,我们下面在做的目的都是在理解的基础上,说明下面这个,也就是欧拉公式,表示的是以以频率为f的在复平面上的一种圆周旋转,这对我们后面利用这点理解傅里叶变换至关重要

e i w t / e i 2 Π f e^{iwt}/e^{i2Πf} eiwt/eif

2.1.1:e的起源——复利问题

💸问题背景:
“李华有1单位的本金,年利率为r,银行一年结算n次,则一年后李华得到:”
在这里插入图片描述

我们发现,当r=1,即年利率为100%时,这个极限刚好是e。关键在于,当n趋于无穷时,每期的收益1/n也在减小,最后二者抵消,恰好收敛到了一个确定的值——e,
在这里插入图片描述
当原本要变换r时,我们把这个变换细分成n份,即每一次都变化r的1/n,那么最后得到:

在这里插入图片描述

2.1.2:复数乘法的意义

在继续深入之前,我们必须要理解复数乘法的意义。

🍊复数一共有四种表示形式,这里我们讲的集合意义是从极坐标形式出发的,而推出复数乘法的几何意义,又是从代数形式和三角形式推出的:
在这里插入图片描述
💐推导过程:
在这里插入图片描述

🍊复数的几何意义:
在这里插入图片描述
首先复数本身的极坐标的几何意义如上,通过推导过程可知,两个复数相乘,相当于:模长相乘,幅角相加

在这里插入图片描述

2.1.3:欧拉公式

在回到这个公式,再思考一下它的意义:初始值为1(n=0),每次变化(在原有基础上)r/n,总的变换是r,这里可能不是很哈理解,需要结合复利来理解
在这里插入图片描述
当我们把r换做,如下图
在这里插入图片描述
右边变成了什么?对,复数的乘积!这里带了个n,可能不是很好理解,我们先暂时把n具体花为4,来帮助我们理解:
在这里插入图片描述
上图可以看到,两个规律:1、每次变换的是角度的累加和模长相乘,角度总变化是Π。2、当n趋向于∞,此时左侧不断收拢。如下图所示
在这里插入图片描述
在这里插入图片描述
至此,我们达到了我们的目的:对下面公式的理解为:一个在复平面以w为角速度或f为角速度,模长为1旋转的矢量!这对于我们从旋转矢量的角度进行傅里叶变换的理解至关重要的。
在这里插入图片描述
同时也不要忘记它的三角形式
在这里插入图片描述
⭐还有一点要记住的是,e前面的系数,表示的是这个旋转矢量的模长,对应到三角形式,也就是幅值!(这也是为什么后来求解赋值时,需要对复数形式的信号求绝对值!)

2.2:一维傅里叶变换

这里我们先做好公式中定义,方面后面对公式理解的讲解:

  • f(x):表示在时域上的原信号,定义域是时间x,值域是信号强度
  • F(u):频域表示,u表示的是频率,当u取不同值时,它是一个复数!

接下来的2.2.12.2.2将对一维的傅里叶公式进行理解和分析!(这些小节中对函数符号用法可能不一致,但是不要紧,清楚具体含义即可!)
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

傅里叶变换的本质就是将时域的非周期信号,转换为在频域的非周期信号

在这里插入图片描述

2.2.1:从旋转向量的角度理解

这是下面讲解的定义:
在这里插入图片描述

🍊从几何意义理解公式的本质(它要表达什么?):

首先,通过对指数e表示的复数那一节,我们对复数可以表示矢量进行周期旋转有了很好的理解。

当我们把原信号乘以一个这样的旋转向量时,我们就可以看作把原信号按照频率f进行缠绕(时间是无穷到无穷,但是缠绕的频率是就是旋转向量旋转的频率f是不变的!)
在这里插入图片描述
在这个旋转频率f下,我们会得到这个缠绕图像的质心如下图所示:

在这里插入图片描述
正如上图所言,整个表达式的结果只是表示按照f为频率进行缠绕(旋转)时,对应的质心,它是一个复数,由实部x和虚部y组成。这其实就是傅里叶频域!简单来说,它就是一个频率对应一个质心(复数)! 就是g(f)这个函数

这个时候你可能就想,欸对,这个式子我理解了,表示这么个东西,然后呢?然后呢?是不是感觉明白了又没明白。我们上面只是从几何意义上理解了,下面我们将从傅里叶变换的作用出发,为什么这个表达式能分离出不同的频率的信号呢?

🍊从作用出发,对公式进行分析(为什么它能分离出不同频率的信号):

大家注意到没,上面所讲,其实涉及到两个频率

  • 原信号有哪些频率的正弦波组成
  • 旋转频率——对应了质心坐标

⭐当复合原信号进行傅里叶变换时(就是把原信号进行上面那样的进行旋转缠绕,不同旋转缠绕f得到不同的质心坐标),假设这个复合原信号由a、b、c三个频率的正弦波复合而成,那么当旋转频率为a、b、c时,这时的质心复数的模会比其他任何旋转频率下对应的质心的模都要大
由于这种规律的存在,我们只需要在频域图像中找到质心的模或者实部或者虚部处于峰值对应的那个频率f,是不是就找到了这个复合信号有哪些频率的信号组成!

如下图所示
在这里插入图片描述

🍊傅里叶变换公式原理总结

  • 旋转的矢量:一个复数,表示模长为1的矢量以频率为f进行逆时针旋转
    e ( i ∗ 2 ∗ π ∗ f ∗ t ) e^{(i*2 * \pi *f * t)} e(i2πft)
    由于傅里叶变换表示的旋转矢量是从顺时针进行旋转,于是我们加个负号
    e − ( 2 ∗ π ∗ i ∗ t ∗ f ) e^{-(2 * \pi * i * t * f)} e(2πitf)

  • 为了表示我们的原始时域复合信号g(t)以这样的频率进行旋转,我们将其相乘

g ( t ) × e ( 2 ∗ π ∗ i ∗ t ∗ f ) g(t)×e^{(2∗π∗i∗t∗f)} g(t)×e(2πitf)

  • 计算对应旋转频率f下的质心坐标,我们可以进行一个估计,在波形图上取n个点,进行坐标相加然后除n取平均,n越大,坐标越精确。基于这种思想,我们对时间进行积分
    在这里插入图片描述
    在这里插入图片描述

如果某频率信号的持续时间很长,那么旋转矢量的模长就会被放大

2.2.2:进一步从正交性的角度理解

下面讲解一下为什么这样做能分解出频率信号,从正交性的角度分析,先看下面三个正余弦相乘的公式:
在这里插入图片描述
联想到之前我们说复数的三角形式:
在这里插入图片描述
不难理解这个公式:

g ( t ) × e ( − 2 ∗ π ∗ i ∗ t ∗ f ) g(t)×e^{(-2∗π∗i∗t∗f)} g(t)×e(2πitf)

因为只有当g(t)中含有f的信号时,基于正交性,才能得到非0值,这也是为什么旋转频率f选择对了,质心距离远点(其实就是表达式的值)会大一些!

2.2.3:一维傅里叶反变换的理解

在这里插入图片描述
将其理解为一个信号叠加的过程F(u)是质心,把不同频率u的信号进行累加,得到x对应的原信号

2.3:二维傅里叶变换

二维傅里叶变换是在一维基础之上的,我们一般使用二维傅里叶变换进行图像处理(图像信息就是二维离散信号),实现空间域到频域的转换,在频域进行一些操作从而对图像进行处理

🌺一维信号&二维信号类比

下面对比的都是在转换成频域之前的那一套

  • 定义域
    • 一维:时域(横坐标是时间)
    • 二维:空间域(二维坐标表示的是信号所在位置)
  • 值域(信号强度
    • 一维就是时域的那个纵坐标值,一般就是声音信号的强度。
    • 二维也就是灰度值呗

这里先抛出公式:在这里插入图片描述

2.3.1:大致上理解

由于下面这个图文讲的实在通俗易懂,我就不必重复造轮子,相信大家看完一定对二维傅里叶变换及其频谱图有一个很好的大体上理解
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.3.2:深入分析:

看完上面的描述,有一个大致理解,但是这之中的变换过程具体又是如何进行的,有点说不清道不明的感觉,但是能确定的是,频谱图的含义是什么
频域图中的一个(X,Y)点表示一张表示正弦波的灰度图像,该点亮度表示该灰度图像的正弦波的幅值,到中心的距离(Len=sqrt(XX+YY))表该灰度图像中该正弦波的频率,到中心点的方向(Dir=y/x)表示灰度图像中该正弦波的方向(注意是垂直正交的)。相位图中每一个点表示对应灰度图像中正弦波的相位。然后该频域图(相位图)所有(X,Y)点表示的正弦波灰度图像的叠加就得到了我们看到的灰度图像。
在这里插入图片描述

我们基于上面的讲解以及一维傅里叶变换,进行再深入分析和理解

🌺为什么要进行频谱中心化?
在这里插入图片描述

以参考一维傅里叶变换。中心化之前的频谱从左到右是从0到采样频率Fs(Fs = ),假如N个点,则第n个点的频率f=(n-1)(n-1)/N。
由于Fs能采样的最大信号频率为Fs/2,由此右半部分和左半部分是对称的。一般频谱图只画出左半部分,称之为单边带。
由于左半部分和右半部分对称,因此可采集的最高信号频率为Fs/2,左边从0增加到Fs/2,右边从Fs/2下降到0。

在这里插入图片描述

三、傅里叶变换在图像处理中的应用

3.1傅立叶变换基本操作

傅立叶变换的相应操作
包括了:变换与逆变换,变换后得到频域上的图像的幅值、相位。

# 傅立叶变换 相应操作
# 得到频域上的图像,其幅值、相位
# 变换再逆变换得到原图import cv2
import numpy as np
import matplotlib.pyplot as pltimg = cv2.imread('test_img/lena.jpg', 0)  # 直接读为灰度图像
f = np.fft.fft2(img)  # 将二维的离散数字图像进行傅里叶变换,变换后的频域图像存储在变量f中
fshift = np.fft.fftshift(f)  # 对评语图像进行中心化操作,将频域远点移动到图像中心,方便后续处理# 取绝对值.:将复数变化成实数
# 取对数的目的为了将数据变化到较小的范围(比如0-255)
c1 = np.log(np.abs(f))  # 频域后图像的振幅信息
c2 = np.log(np.abs(fshift))  # 中心化操作ph_f = np.angle(f)  # 图像上每个像素点对应的相位图
ph_fshift = np.angle(fshift)  # 中心化操作# 逆变换,获得原始图像
f0shift = np.fft.ifftshift(fshift)  # 曲线频谱中心化,获得原始频谱
img_back = np.fft.ifft2(f0shift)  # 基于二维图像的逆傅里叶变换
img_back = np.abs(img_back)  # 出来的是复数,无法显示,于是取绝对值# 逆变换方法2--取绝对值就是振幅
f1shift = np.fft.ifftshift(np.abs(fshift))
img_back1 = np.fft.ifft2(f1shift)
img_back1 = np.abs(img_back1)
img_back1 = (img_back1-np.amin(img_back1))/(np.amax(img_back1)-np.amin(img_back1))# 逆变换方法3--取相位
f2shift = np.fft.ifftshift(np.angle(fshift))
img_back2 = np.fft.ifft2(f2shift)
# 出来的是复数,无法显示
img_back2 = np.abs(img_back2)
# 调整大小范围便于显示
img_back2 = (img_back2-np.amin(img_back2))/(np.amax(img_back2)-np.amin(img_back2))# 逆变换方法4--两者合成
s1 = np.abs(fshift)  # 取振幅
s1_angle = np.angle(fshift)  # 取相位
s1_real = s1*np.cos(s1_angle)  # 取实部
s1_imag = s1*np.sin(s1_angle)  # 取虚部
s2 = np.zeros(img.shape, dtype=complex)
s2.real = np.array(s1_real)  # 重新赋值s1给s2
s2.imag = np.array(s1_imag)
f3shift = np.fft.ifftshift(s2)  # 对新的进行逆变换
img_back3 = np.fft.ifft2(f3shift)
# 出来的是复数,无法显示
img_back3 = np.abs(img_back3)
# 调整大小范围便于显示
img_back3 = (img_back3-np.amin(img_back3))/(np.amax(img_back3)-np.amin(img_back3))plt.subplot(421), plt.imshow(img, 'gray'), plt.title('original')
plt.subplot(422), plt.imshow(c1, 'gray'), plt.title('Amplitude')
plt.subplot(423), plt.imshow(c2, 'gray'), plt.title('center')
plt.subplot(424), plt.imshow(ph_f, 'gray'), plt.title('phases')
plt.subplot(425), plt.imshow(img_back, 'gray'), plt.title('img_back')
plt.show()

在这里插入图片描述

3.2:低通滤波

频域上的低通滤波相当于平滑滤波处理。
这段代码主要实现了两种低通滤波器(ideal lowpass filter和gaussian lowpass filter)的图像处理。
下面给出了三种在频域上的低通滤波方法

  • lowPassFilter(image, d)
# ideal lowpass filter
# 定义ideal lowpass filter函数,接受图像image和截止频率d作为参数
def lowPassFilter(image, d):f = np.fft.fft2(image)  # 首先,对输入图像进行二维傅里叶变换fshift = np.fft.fftshift(f)  # 频谱图像中心化"""内部函数make_transform_matrix:操作在频率域上的低通滤波器原理:创建一个变换矩阵,通过计算每个频率点与中心点的距离(这个距离就是频率),将距离(频率)小于或等于频率阈值d的点置为1,其他点置为0"""def make_transform_matrix(d):transfor_matrix = np.zeros(image.shape)center_point = tuple(map(lambda x: (x - 1) / 2, image.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))if dis <= d:transfor_matrix[i, j] = 1else:transfor_matrix[i, j] = 0return transfor_matrix# 在lowPassFilter内部调用make_transform_matrix函数,得到变换矩阵d_matrixd_matrix = make_transform_matrix(d)# 将频率域中心重新移动到原来位置,并且将其与傅里叶变换相乘(低通滤波),然后进行逆变换,获取低通滤波后的图像new_img = np.abs(np.fft.ifft2(np.fft.ifftshift(fshift * d_matrix)))return new_img
  • GaussianLowFilter(image, d)
# gaussian lowpass filter
def GaussianLowFilter(image, d):f = np.fft.fft2(image)fshift = np.fft.fftshift(f)"""内部函数make_transform_matrix:操作在频率域上的低通滤波器原理:创建一个变换矩阵(使用高斯函数来表示),通过计算每个频率点与中心点的距离(这个距离就是频率),将距离(频率)小于或等于频率阈值d的点置为1,其他点置为0"""def make_transform_matrix(d):transfor_matrix = np.zeros(image.shape)center_point = tuple(map(lambda x: (x-1)/2, image.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] = np.exp(-(dis**2)/(2*(d**2)))return transfor_matrixd_matrix = make_transform_matrix(d)new_img = np.abs(np.fft.ifft2(np.fft.ifftshift(fshift*d_matrix)))return new_img
  • 掩膜方法
img_man = cv2.imread('test_img/lena.jpg', 0)  # 直接读为灰度图像
plt.subplot(121), plt.imshow(img_man, 'gray'), plt.title('origial')
plt.xticks([]), plt.yticks([])
# --------------------------------
"""计算图像的行数和列数,并创建一个与图像大小相同的全0矩阵mask将mask中心位置周围范围像素值设置为1,以创建一个掩膜
"""
rows, cols = img_man.shape
mask = np.zeros(img_man.shape, np.uint8)
mask[int(rows/2-20):int(rows/2+20), int(cols/2-20):int(cols/2+20)] = 1
# --------------------------------
f1 = np.fft.fft2(img_man)  # 对原始图像进行二维傅里叶变换
f1shift = np.fft.fftshift(f1)  # 中心化
f1shift = f1shift*mask  # !将中心化结构和掩膜mask相乘,实现低通滤波
f2shift = np.fft.ifftshift(f1shift)  # 对新的进行逆变换
img_new = np.fft.ifft2(f2shift)
# 出来的是复数,无法显示
img_new = np.abs(img_new)
# 调整大小范围便于显示
img_new = (img_new-np.amin(img_new))/(np.amax(img_new)-np.amin(img_new))plt.subplot(122), plt.imshow(img_new, 'gray'), plt.title('Lowpass')
plt.xticks([]), plt.yticks([])
plt.show()

在这里插入图片描述

3.3:高通滤波

频域上的高通滤波相当于边缘检测算子,提取边缘。

# 高通滤波
# 有利于提取图像的轮廓import cv2
import numpy as np
import matplotlib.pyplot as plt# ideal highpass filter
def highPassFilter(image, d):  # D为阈值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, image.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))if dis <= d: # 距离小于d的频率成分置为1(高频)transfor_matrix[i, j] = 0else:transfor_matrix[i, j] = 1return transfor_matrixd_matrix = make_transform_matrix(d)# 将变换矩阵应用于频域结果,再进行逆傅里叶变换new_img = np.abs(np.fft.ifft2(np.fft.ifftshift(fshift*d_matrix)))return new_img# gaussian highpass
def GaussianHighFilter(image, d):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, image.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))# 在高斯滤波器种,距中心点的距离越大,变换矩阵的值越接近于1;距离越小,变换矩阵的值越接近于0transfor_matrix[i, j] = 1-np.exp(-(dis**2)/(2*(d**2)))return transfor_matrixd_matrix = make_transform_matrix(d)new_img = np.abs(np.fft.ifft2(np.fft.ifftshift(fshift*d_matrix)))return new_imgimg_man = cv2.imread('test_img/lena.jpg', 0)  # 直接读为灰度图像
plt.subplot(221), plt.imshow(img_man, 'gray'), plt.title('origial')
plt.xticks([]), plt.yticks([])
# --------------------------------
# 生成一个和图像大小相同的掩膜
rows, cols = img_man.shape
mask = np.ones(img_man.shape, np.uint8)
# 掩膜将图像中心的一个正方形区域置为0,其余部分置为1
mask[int(rows/2-30):int(rows/2+30), int(cols/2-30):int(cols/2+30)] = 0
# --------------------------------
f1 = np.fft.fft2(img_man)
f1shift = np.fft.fftshift(f1)
# 将频域图与掩膜相乘
f1shift = f1shift*mask
f2shift = np.fft.ifftshift(f1shift)  # 对新的进行逆变换
img_new = np.fft.ifft2(f2shift)
# 出来的是复数,无法显示
img_new = np.abs(img_new)
# 调整大小范围便于显示
img_new = (img_new-np.amin(img_new))/(np.amax(img_new)-np.amin(img_new))out = GaussianHighFilter(img_man, 60)
out2 = highPassFilter(img_man, 60)
plt.subplot(222), plt.imshow(out2, 'gray'), plt.title('highPassFilter')
plt.subplot(223), plt.imshow(out, 'gray'), plt.title('GaussianHighFilter')
plt.subplot(224), plt.imshow(img_new, 'gray'), plt.title('mask_method')plt.show()

在这里插入图片描述

3.4:带通滤波

带通滤波处于高通和低通之间,可指定频率的范围。

# 带通滤波器import cv2
import numpy as np
import matplotlib.pyplot as pltimg_man = cv2.imread('test_img/lena.jpg', 0)  # 直接读为灰度图像
plt.subplot(121), plt.imshow(img_man, 'gray'), plt.title('origial')
plt.xticks([]), plt.yticks([])
# --------------------------------
"""定义两个掩膜矩阵mask1和mask2(和图像大小一致),用于在频域图上对图像进行带通滤波掩膜的作用是通过将图像中心的一个区域设置为0或者1来选择保留频率成分mask1:与原始图像具有相同形状的矩阵,初始值为1,将中心区域(16x16)置为0,抑制中心低频成分mask2:将中心(160x160)置为0,其余保持为1,选择一定范围的高频最后将mask1和mask2相乘,得到最终的带通掩膜
"""
rows, cols = img_man.shape
mask1 = np.ones(img_man.shape, np.uint8)
mask1[int(rows/2-8):int(rows/2+8), int(cols/2-8):int(cols/2+8)] = 0
mask2 = np.zeros(img_man.shape, np.uint8)
mask2[int(rows/2-80):int(rows/2+80), int(cols/2-80):int(cols/2+80)] = 1
mask = mask1*mask2
# --------------------------------
f1 = np.fft.fft2(img_man)
f1shift = np.fft.fftshift(f1)
f1shift = f1shift*mask
f2shift = np.fft.ifftshift(f1shift)  # 对新的进行逆变换
img_new = np.fft.ifft2(f2shift)
# 出来的是复数,无法显示
img_new = np.abs(img_new)
# 调整大小范围便于显示
img_new = (img_new-np.amin(img_new))/(np.amax(img_new)-np.amin(img_new))
plt.subplot(122), plt.imshow(img_new, 'gray'), plt.title('result')
plt.xticks([]), plt.yticks([])
plt.show()

在这里插入图片描述

3.5:巴特沃兹滤波

一种常见并应用广泛的频域上的滤波器。
在巴特沃斯滤波器中,阈值(d)和阶数(n)对滤波效果有重要影响。

  1. 阈值(d):

    • 较小的阈值会保留更多低频成分,对应于图像中的平滑部分。因此,较小的阈值会导致图像较模糊的滤波效果。
    • 较大的阈值会抑制低频成分,对应于图像中的细节部分。因此,较大的阈值会导致图像较清晰但可能失去细节的滤波效果。
    • 不同的阈值选择会在频域上选择不同的频率范围,从而影响图像的频率特性。
  2. 阶数(n):

    • 较小的阶数会产生较为平缓的滤波曲线,对应于相对平滑的滤波效果。这意味着低频和高频成分的抑制相对均匀。
    • 较大的阶数会产生较为陡峭的滤波曲线,对应于较强的抑制效果。这意味着滤波器对低频和高频成分的抑制会更加明显。
    • 阶数越高,滤波曲线的变化越快,滤波器通过选择性地抑制频率成分来实现更精细的滤波效果。

因此,选择适当的阈值和阶数可以控制滤波器的频率选择性和抑制效果。较小的阈值和较小的阶数通常用于保留图像的整体特征和平滑图像,而较大的阈值和较大的阶数则用于强调图像的边缘和细节。具体的选择需要根据应用场景和期望的滤波效果进行调整。

# 巴特沃斯滤波器import cv2
import numpy as np
import matplotlib.pyplot as pltdef 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, image.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 + (d / dis)) ** n)return transfor_matrixd_matrix = make_transform_matrix(d)new_img = np.abs(np.fft.ifft2(np.fft.ifftshift(fshift * d_matrix)))return new_imgimg = cv2.imread('test_img/lena.jpg', 0)
plt.subplot(231)
butter_100_1 = butterworthPassFilter(img, 100, 1)
plt.imshow(butter_100_1, cmap="gray")
plt.title("d=100,n=1")
plt.axis("off")
plt.subplot(232)
butter_100_2 = butterworthPassFilter(img, 100, 2)
plt.imshow(butter_100_2, cmap="gray")
plt.title("d=100,n=2")
plt.axis("off")
plt.subplot(233)
butter_100_3 = butterworthPassFilter(img, 100, 3)
plt.imshow(butter_100_3, cmap="gray")
plt.title("d=100,n=3")
plt.axis("off")
plt.subplot(234)
butter_100_1 = butterworthPassFilter(img, 30, 1)
plt.imshow(butter_100_1, cmap="gray")
plt.title("d=30,n=1")
plt.axis("off")
plt.subplot(235)
butter_100_2 = butterworthPassFilter(img, 30, 2)
plt.imshow(butter_100_2, cmap="gray")
plt.title("d=30,n=2")
plt.axis("off")
plt.subplot(236)
butter_100_3 = butterworthPassFilter(img, 30, 3)
plt.imshow(butter_100_3, cmap="gray")
plt.title("d=30,n=3")
plt.axis("off")
plt.show()

在这里插入图片描述


参考:

  • 傅里叶分析之掐死教程(完整版)
  • 图像预处理之傅里叶变换与频谱滤波
  • 图像处理(5)–图像的傅里叶变换
  • 通俗讲解:图像傅里叶变换

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/160030.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring Boot Bean 注入的常用方式教程

Spring Boot Bean 注入是一种将依赖对象引入到应用程序组件中的机制&#xff0c;它有助于实现松耦合和可测试的代码。这种注入方式允许我们将依赖关系委托给 Spring 容器来管理&#xff0c;从而提高了代码的可维护性和可读性。Spring Boot 提供了多种 Bean 注入方式&#xff0c…

Linux-CentOS8-Oracle19c 安装详解

Linux-CentOS8-Oracle19c安装图解 文章目录 Linux-CentOS8-Oracle19c安装图解预备1. Oracle19c 安装手册&#xff1a;2. 安装虚拟机&#xff1a;4G内存&#xff0c;2*2核心&#xff0c;30G3. 下载CentOS8镜像。4. 开始准备预安装5. 修改Oracle账户密码6. 修改SELINUX值在文件&a…

AWS SAP-C02教程2--存储资源

存储资源在架构设计中是一个少不了的环节,而在AWS中有不同类型的存储资源,对应会有不同用途不同价格,SAP考试中考察各种存储是少不了,以下是涉及到的存储 目录 1 非结构化存储1.1 EBS(块存储)1.1.1 基本限制1.1.2 类型1.1.3 RAID 配置选项1.1.4 Snapshot1.2 Local Insta…

thinkphp6 入门(8)-- Session

开启Session Session功能默认是没有开启的&#xff08;API应用通常不需要使用Session&#xff09; think\middleware\SessionInit// 添加引用 use think\facade\Session; 赋值 Session::set(name, thinkphp);取值 // 如果值不存在&#xff0c;返回null Session::get(name)…

CSS的布局 Day03

一、显示模式&#xff1a; 网页中HTML的标签多种多样&#xff0c;具有不同的特征。而我们学习盒子模型、使用定位和弹性布局把内容分块&#xff0c;利用CSS布局使内容脱离文本流&#xff0c;使用定位或弹性布局让每块内容摆放在想摆放的位置&#xff0c;让网站页面布局更合理、…

ESP32-IPS彩屏ST7789-Arduino-简单驱动

目的&#xff1a; 使ESP32能够驱动点亮ST7789显示屏 前提条件&#xff1a; ESP32 ST7789 &#xff08;240 x240&#xff0c;IPS&#xff09; 杜邦线 Arduino 过程&#xff1a; 0x00--接线 0x01--驱动&#xff1a; 彩屏驱动库 针对不同的彩屏驱动芯片&#xff0c;常用的 Arduino…

如何实现 Es 全文检索、高亮文本略缩处理(封装工具接口极致解耦)

如何实现 Es 全文检索、高亮文本略缩处理 前言技术选型JAVA 常用语法说明全文检索开发高亮开发Es Map 转对象使用核心代码 Trans 接口&#xff08;支持父类属性的复杂映射&#xff09;Trans 接口可优化的点高亮全局配置类如下真实项目落地效果为什么不用 numOfFragments、fragm…

深度强化学习 第 3 章 强化学习基本概念

本章讲解强化学习的基本概念。第 3.1 节介绍马尔可夫决策过程&#xff08;Markov decision process&#xff0c;简称 MDP&#xff09;&#xff0c;它是最常见的对强化学习建模的方法。第 3.2 节定义策略函数&#xff0c;包括随机策略和确定策略。第 3.3 节分析强化学习中的随机…

element树形控件编辑节点组装节点

需求功能&#xff1a; 编辑树节点&#xff0c;组装节点 <el-scrollbar class"scrollbar-wrapper"><el-tree :data"nodeList" ref"tree" :props"defaultProps" :expand-on-click-node"false"><template slot…

十三、队列的特性

1、队列(Queue)概述 队列可以用于"任务到任务"、"任务到中断"、"中断到任务"直接传输信息。队列涉及内容如下: 怎么创建、清楚、删除队列队列中消息如何保存怎么向队列发送数据、怎么从队列读取数据、怎么覆盖队列的数据在队列上阻塞式什么意思…

计算机毕业设计-开题报告答辩常见问题!Javaweb项目答辩

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…

尚硅谷Flink(一)

目录 ☄️前置工作 fenfa脚本 &#x1f30b;概述 ☄️Flink是什么 ☄️特点&#xff08;多nb&#xff09; ☄️应用场景&#xff08;不用看&#xff09; ☄️分层API &#x1f30b;配环境 ☄️wordcount ☄️WcDemoUnboundStreaming &#x1f30b;集群部署 ☄️集…

计算机毕业设计 基于协同过滤算法的白酒销售系统的设计与实现 Javaweb项目 Java实战项目 前后端分离 文档报告 代码讲解 安装调试

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…

IP 协议的相关特性(部分)

IP 协议的报文格式 4位版本号&#xff1a; 用来表示IP协议的版本&#xff0c;现有的IP协议只有两个版本&#xff0c;IPv4&#xff0c;IPv6。 4位首部长度&#xff1a; 设定和TCP的首部长度一样 8位服务类型&#xff1a; &#xff08;真正只有4位才有效果&#xff09;&#xf…

【LeetCode 算法专题突破】双指针(⭐)

文章目录 前言1. 移动零题目描述代码 2. 复写零题目描述代码 3. 快乐数题目描述代码 4. 盛最多水的容器题目描述代码 5. 有效三角形的个数题目描述代码 6. 三数之和题目描述代码 7. 四数之和题目描述代码 总结 前言 学算法入门必学的一个章节&#xff0c;双指针算法&#xff0…

2023/10/15总结

学习总结 最近开始写项目了&#xff0c;然后写的过程中遇到了跨域问题。 为什么会出现跨域问题 由于浏览器的同源策略限制。同源策略是一种约定&#xff0c;它是浏览器最核心也是最基本的安全功能。如果缺少了同源策略&#xff0c;那么浏览器的正常功能可能都会收到影响。所谓…

雷电模拟器上使用第一个frida(四)第一个HOOK

经过上述三篇&#xff0c;已经可以使用python3.8.10编写代码&#xff0c;利用frida14.2.18和雷电模拟器9.0.60(9)&#xff0c;Android 9交互。 雷电模拟器上使用第一个frida&#xff08;一&#xff09;之安装-CSDN博客 雷电模拟器上使用第一个frida&#xff08;二&#xff09…

【git的使用方法】——上传文件到gitlab仓库

先进入到你克隆下来的仓库的目录里面 比如&#xff1a;我的仓库名字为zhuox 然后将需要上传推送的文件拷贝到你的克隆仓库下 这里的话我需要拷贝的项目是t3 输入命令ls&#xff0c;就可以查看该文件目录下的所有文件信息 然后输入git add 文件名 我这边输入的是 &#x…

windows内网渗透正向代理

内网渗透正向代理 文章目录 内网渗透正向代理1 正向代理图2 环境准备2.1 正向代理需求&#xff1a; 3 网卡配置3.1 【redream】主机3.2 【base】主机双网卡3.3 【yvkong】网卡设置 4 启动4.1【redream】网卡配置&#xff1a;4.2【base】网卡配置&#xff1a;4.3【yvkong】网卡地…

MQTT整合

MQTT整合 MQTT服务器软件筛选MQTT服务器软件mosquitto下载修改mosquitto配置,并启动mosquitto服务利用mosquitto工具测试订阅与发布可视化MQTT客户端工具MQTTX使用SpringBoot整合MQTT1.2.3.4.5.6.MQTT服务器软件筛选 MQ遥测传输(MQTT)是轻量级基于代理的发布/订阅的消息传输…