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

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

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

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

滤波在频率域更为直观,你想想嘛,所谓滤波,就是把二维图像信号种某个频率信号给去掉。如果定义域是频率,值域是该频率信号的强度(这个坐标体系其实就是频域),直接把对应频率的强度弄为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.mzph.cn/news/105894.shtml

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

相关文章

KOSMOS-2.5:密集文本的多模态读写模型

Overview 总览摘要1 引言2 KOSMOS-2.52.1 模型结构2.1 图像和文本表征2.3 预训练数据2.4 数据处理2.5 过滤与质量控制 3 实验3.1 评估3.2 实现细节3.3 结果3.4 讨论 4 相关工作4.1 多模态大语言模型4.2 图文理解 5 总结与展望 总览 题目: KOSMOS-2.5: A Multimodal Literate M…

通过jsoup抓取谷歌商店评分

文章目录 背景实现是否下架预警评分 总的工具类,测试 背景 在谷歌上面发布包,有时候要看看评分,有时候会因为总总原因被下架,希望后台能够对评分进行预警,和下架预警 实现 测试地址: https://play.google.com/store/apps/details?idcom.tencent.mm 通过jsoup解析页面,然后获…

Python学习----Day07

函数 函数是组织好的&#xff0c;可重复使用的&#xff0c;用来实现单一&#xff0c;或相关联功能的代码段。函数能提高应用的模块性&#xff0c;和代码的重复利用率。你已经知道Python提供了许多内建函数&#xff0c;比如print()。但你也可以自己创建函数&#xff0c;这被叫做…

苍穹外卖(五) 微信小程序

项目应用: 使用微信小程序完成客户端开发并基于微信登录实现小程序的登录功能如果是新用户需要自动完成注册 微信小程序开发 介绍 小程序是一种新的开放能力&#xff0c;开发者可以快速地开发一个小程序。可以在微信内被便捷地获取和传播&#xff0c;同时具有出色的使用体验…

C# 图解教程 第5版 —— 第3章 C# 编程概述

文章目录 3.1 一个简单的 C# 程序&#xff08;*&#xff09;3.2 标识符3.3 关键字3.4 Main&#xff1a;程序的起始点&#xff08;*&#xff09;3.5 空白3.6 语句&#xff08;*&#xff09;3.7 从程序中输出文本3.7.1 Write&#xff08;*&#xff09;3.7.2 WriteLine&#xff08…

【C++进阶】:C++类型转换

C类型转换 一.C语言里的类型转换二.C语音类型转换的一些弊端三.C的四种类型转换1.static_cast2.reinterpret_cast3.const_cast4.dynamic_cast 一.C语言里的类型转换 在C语言中&#xff0c;如果赋值运算符左右两侧类型不同&#xff0c;或者形参与实参类型不匹配&#xff0c;或者…

Python实验三

1&#xff1a;编程统计英文句子中的单词出现的次数。 要求&#xff1a;输出结果为按照单词在句子中出现的次数降序排列。 提示&#xff1a;用split&#xff08;&#xff09;拆分字符串 # 1&#xff1a;编程统计英文句子中的单词出现的次数。 # 要求&#xff1a;输出结果为按照…

Dijkstra求最短路(图解)

你好&#xff0c;我是Hasity。 今天分享的内容&#xff1a;Dijkstra求最短路这个题目 Dijkstra求最短路I 题目描述 给定一个 n个点 m 条边的有向图&#xff0c;图中可能存在重边和自环&#xff0c;所有边权均为正值。 请你求出 1 号点到 n号点的最短距离&#xff0c;如果无…

Windows 中环境变量的查看与设置

接触了LLM应用开发后&#xff0c;经常要用到环境变量的设置&#xff08;openAI apikey啥的&#xff09; 但是老忘记&#xff0c;今天来学习和总结一下 主要用到以下几种&#xff1a;使用 PowerShell、CMD 和 Python 来查看和设置环境变量 文章目录 1. PowerShell查看环境变量&a…

【Linux】HTTP协议

文章目录 &#x1f4d6; 前言1. 认识URL && 引入http协议2. http协议格式2.1 宏观格式&#xff1a;2.2 实验演示&#xff1a; 3. http的方法3.1 GET方法&#xff1a;3.2 POST方法&#xff1a;3.3 GET vs POST&#xff1a; 4. HTTP的报头和状态码5. http的cookie5.1 htt…

估算总体标准差的极差均值估计法sigma = R/d2

总体标准差的估算值可以通过将平均极差除以合适的常数因子d2来计算。这个估算方法是用于估算总体标准差的一种常见方法&#xff0c;尤其在质量控制和过程监控中经常使用。 总体标准差的估算值 (平均极差) / d2 其中&#xff1a; "总体标准差的估算值" 表示用极差…

Floorplanning with Graph Attention

Floorplanning with Graph Attention DAC ’22 目录 Floorplanning with Graph Attention摘要1.简介2.相关工作3.问题公式化4. FLORA的方法4.1 解决方案概述4.2 C-谱聚类算法 4.3 基于GAT的模型4.4 合成训练数据集生成 摘要 布图规划一直是一个关键的物理设计任务&#xff0…

宝塔面板部署express以及MySql项目

第一次在宝塔面板上部署express和MySql项目&#xff0c;部署过程一直跑不通接口&#xff0c;特此记录一下。 在部署的时候&#xff0c;建议第一步把数据库MySql给跑通&#xff0c;中间好多原因是由于数据库的原因给引起的。 一.连接数据库 &#xff08;1&#xff09;在宝塔面…

深入promise

深入promise 我们可能知道如何使用 Promise&#xff0c;但是我们知道它们实际上是如何工作的吗&#xff1f; 为了让每个人都了解Promise&#xff0c;让我们从基础开始。如果我们知道 Promise 是什么以及如何使用它&#xff0c;我们可以跳过这一部分并直接跳到“魔法开始”的地…

RSA加密与解密原理

目录 一、什么是RSA加密 二、RSA加密原理 三、RSA加解密过程与算法代码 一、什么是RSA加密 RSA加密是一种非对称加密算法。 对称加密&#xff1a; 对称加密是一种加密方式&#xff0c;加密和解密使用同一个密钥&#xff0c;被加密的信息在传输前用预先协商好的密钥进行加密…

KUKA机器人如何强制输出或取消数字IO信号?

KUKA机器人如何强制输出或取消数字IO信号? 具体的操作方法和步骤可参考以下内容: 如下图所示,点击菜单—显示—输入/输出端,如下图所示,选择想要查看的信号,这里以数字输出端为例进行说明, 如下图所示,此时可以看到输出端信号的编号、名称和当前值,可以通过下拉滚动条…

河北专升本(C语言)

目录 一&#xff1a;C语言的构成特点 二: 数据类型 三: 常量、变量、运算符及表达式 &#xff08;一&#xff09;标识符 &#xff08;二&#xff09;常量 &#xff08;三&#xff09;变量&#xff1a;其值可以改变的量 &#xff08;四&#xff09;各种类型数据混合运算 &…

简单好用的解压缩软件:keka 中文 for mac

Keka是一款功能全面、易于使用的文件压缩和解压缩软件&#xff0c;为Mac用户提供了便捷的文件管理工具。它支持多种压缩格式&#xff0c;具有快速解压和强大的压缩功能&#xff0c;让您能够轻松地处理各种文件压缩需求。 隐私非常重要 安全共享只需设置密码并创建高度加密的文…

深度强化学习 第 2 章 蒙特卡洛

2.1随机变量 强化学习中会经常用到两个概念&#xff1a; 随机变量、 观测值。 本书用大写字母表示随机变量&#xff0c;小写字母表示观测值&#xff0c;避免造成混淆。 下面我们定义概率质量函数&#xff08;probability mass function&#xff0c;缩写 PMF&#xff09;和概率…

LINUX定时解压缩方案

需求背景 对接客户中某个上游为外包系统&#xff0c;外包系统每日推送压缩文件至指定文件夹下&#xff0c;文件格式为YYYYMMDD_RegReport.zip。由于每日采集文件&#xff0c;无法对接压缩包内文件&#xff0c;需要将推送的压缩文件每日解压为文件夹 需求分析 与客户沟通后&a…