图像处理之离散傅里叶变换(DFT)

上学期修了数字图像处理这门课程,想着正好趁这个机会写(shui)几篇文章,告诉自己没有白学。傅里叶变换,是图像处理中的一个重要内容,频率域处理的操作都要建立在傅里叶变换的基础上,所以作为这个专栏的开篇,不如就简单介绍和实现一下离散傅里叶变换(DFT)。


一、傅里叶级数和变换

法国数学家傅里叶提出,任何周期函数都可表示为不同频率的正弦函数和/或余弦函数之和,其中每个正弦函数和/或余弦函数都要乘以不同的系数,这个和就称为傅里叶级数。按照这个思想,周期为T的连续变量t的周期函数f(t),可表示为乘以适当系数的正弦函数和余弦函数之和,即

f(t)=\sum_{n=-\infty }^{\infty }c_{n}e^{j\tfrac{2\pi n}{T}t},系数为

c_{n}=\frac{1}{T}\int_{-T/2}^{T/2}f(t)e^{-j\tfrac{2\pi n}{T}t}dt, n=0,\pm 1,\pm 2,...

另外根据欧拉公式有e^{j\theta }=cos\theta+jsin\theta,所以上述式子便可展开为正弦函数和余弦函数之和(其中涉及到复数的知识请读者自行了解,这里不作过多说明)。

而一些(曲线下方面积有限的)非周期函数也能用正弦函数和/或余弦函数乘以加权函数的积分来表示。这种情况下的公式就是傅里叶变换,其在许多理论和应用科学中起到非常大的作用。连续单变量函数的傅里叶变换和反变换表示为

\left\{\begin{matrix} F(\mu )=\int_{-\infty }^{\infty }f(t)e^{-j2\pi \mu t}dt\\ \\ f(t) =\int_{-\infty }^{\infty }F(\mu)e^{j2\pi \mu t}d\mu \end{matrix}\right.

上述两个式子共同构成傅里叶变换对,可以表示为f(t)\Leftrightarrow F(\mu)

同样,令f(t,z)是两个连续变量tz的连续函数,则其二维连续傅里叶变换对为

\left\{\begin{matrix} F(\mu,\nu )=\int_{-\infty}^{\infty}\int_{-\infty}^{\infty}f(t,z)e^{-j2\pi (\mu t+\nu z)}dtdz \\ \\f(t,z)=\int_{-\infty}^{\infty}\int_{-\infty}^{\infty}F(\mu,\nu)e^{j2\pi (\mu t+\nu z)}d\mu d\nu \end{matrix}\right.

二、离散傅里叶变换(DFT)

有了上一节中所讲的数学基础,我们这里直接给出离散傅里叶的变换对

\left\{\begin{matrix} F(u)=\sum_{x=0}^{M-1}f(x)e^{-j2\pi ux/M}, u=0,1,2,...,M-1\\ \\ f(x)=\frac{1}{M} \sum_{x=0}^{M-1}F(u)e^{j2\pi ux/M},x=0,1,2,...,M-1 \end{matrix}\right.

将式子与连续形式的傅里叶变换进行对比,应该是容易理解的。有时,我们也会发现有的公式把1/M放在了第一个式子中,这并不会影响两个公式形成一个傅里叶变换对。此外在实现的时候,为了方便我们通常将DFT公式写成下面这种形式

\left\{\begin{matrix} F(u)=\sum_{x=0}^{M-1}f(x)W_{M}^{ux}, u=0,1,2,...,M-1\\ \\f(x)=\frac{1}{M} \sum_{x=0}^{M-1}F(u)W_{M}^{-ux},x=0,1,2,..,M-1 \end{matrix}\right.

W_{M}=e^{-j2\pi /M}

若用矩阵计算的形式表达上面这个过程,就是

\begin{bmatrix} F(0)\\ F(1)\\ F(2)\\ ...\\ F(M-1) \end{bmatrix}=\begin{bmatrix} W_{M}^{0} &W_{M}^{0} &W_{M}^{0} &... &W_{M}^{0} \\ W_{M}^{0}&W_{M}^{1} &W_{M}^{2} &... &W_{M}^{M-1} \\ W_{M}^{0}& W_{M}^{2} &W_{M}^{4} &... &W_{M}^{2(M-1)} \\ ...& ... &... & ... &... \\ W_{M}^{0}&W_{M}^{M-1} & W_{M}^{2(M-1)} & ...& W_{M}^{(M-1)^{2}} \end{bmatrix}\begin{bmatrix} f(0)\\ f(1)\\ f(2)\\ ...\\ f(M-1) \end{bmatrix}

综上,给出一维DFT的实现过程如下。

#一维离散傅里叶变换
def dft(f):
    #得到长度
    M = f.shape[0]
    
    #计算变换矩阵
    x, y = np.mgrid[0:M, 0:M]
    w = x * y
    base = np.exp(-1j*2*np.pi/M)
    W = base**w
    
    #矩阵相乘计算结果
    F = np.dot(W, f)
    return F

三、二维DFT及其可分离性

类似于一维DFT,我们也可得到如下的二维离散傅里叶变换对

\left\{\begin{matrix} F(u,v)=\sum_{x=0}^{M-1}\sum_{y=0}^{N-1}f(x,y)e^{-j2\pi (ux/M+vy/N)},u=0,1,2,...,M-1,v=0,1,2,...,N-1\\ \\ f(x,y)=\frac{1}{MN}\sum_{u=0}^{M-1}\sum_{v=0}^{N-1}F(u,v)e^{j2\pi (ux/M+vy/N)} ,x=0,1,2,...,M-1,y=0,1,2,...,N-1\end{matrix}\right.

接下来我们对正变换进行化简,可得

F(u,v)=\sum_{x=0}^{M-1}e^{-j2\pi ux/M}\sum_{x=0}^{N-1}f(x,y)e^{-j2\pi vy/N}=\sum_{x=0}^{M-1}F(x,v)e^{-j2\pi ux/M}

F(x,v)=\sum_{y=0}^{N-1}f(x,y)e^{-j2\pi xy/N}

上述过程可以看到,f(x,y)的二维DFT可通过计算f(x,y)的每一行的一维变换,然后沿计算结果的每一列计算一维变换来得到。也就是说二维DFT通过多次一维DFT计算即可得到,参考下面实现过程。

#二维离散傅里叶变换
def dft_2d(f):
    #得到输入的行数和列数
    M, N = f.shape[0], f.shape[1]
    
    #初始化两个复数类型数组,用于保存结果
    F, F_x = np.zeros(shape=(M,N), dtype=np.complex128), np.zeros(shape=(M,N), dtype=np.complex128)
    
    #逐行逐列进行两次一维傅里叶变换
    for i in range(M):F_x[i,:] = dft(f[i,:])
    for i in range(N):F[:,i] = dft(F_x[:,i])
    
    return F

四、使用DFT算法计算IDFT

我们将二维离散傅里叶反变换过程两边取复共轭,并将得到的结果乘以MN

MNf^{*}(x,y)=\sum_{u=0}^{M-1}\sum_{v=0}^{N-1}F^{*}(u,v)e^{-j2\pi (ux/M+vy/N)}

然后,我们可以发现上式的右侧是F^{*}(u,v)的DFT。这告诉我们,若把F^{*}(u,v)代入计算二维傅里叶正变换的算法中,则结果将是MNf^{*}(x,y)。所以将这个结果取复共轭并乘以1/MN就可以得到f(x,y),就是我们想要的反变换,实现过程如下。

#二维离散傅里叶反变换
def idft_2d(F):
    #得到行数和列数
    M, N = F.shape[0], F.shape[1]
    
    #先对F的共轭进行正向离散傅里叶变换,除以常数后再取共轭
    f = np.conjugate(dft_2d(np.conjugate(F)))/M/N
    
    return f

五、傅里叶变换中心化

可以证明,一维正离散变换和反离散变换都是无限周期的,周期为M,即

\left\{\begin{matrix} F(u)=F(u+kM)\\ \\ f(x) = f(x+kM) \end{matrix}\right.

如一维情况那样,二维傅里叶变换及其反变换在u方向和v方向是无限周期的,即

\left\{\begin{matrix} F(u,v)=F(u+k_{1}M,v)=F(u,v+k_{2}N)=F(u+k_{1}M,v+k_{2}N)\\ \\ f(x,y)=f(x+k_{1}M,y)=f(x,y+k_{2}N)=f(x+k_{1}M,y+k_{2}N) \end{matrix}\right.

周期性在实现基于DFT的算法中很重要。区间0M-1上的变换数据由在点M/2处相遇的两个半周期组成,但该周期的较低部分出现在较高的频率处。针对显示和滤波的目的,在该区间内有一个数据连续并且正确排序的完整变换周期更为方便。也就说我们需要先将F(u,v)变换到F(u-M/2,v-N/2),方便我们进一步操作,下图显示了一维和二维情况下的这个过程。

图1 冈萨雷斯原书中关于一维和二维傅里叶变换中心化的说明

下面用代码实现了中心化和逆中心化的过程。

#中心化
def fshift(F):
    #两个轴平移半个周期
    M, N = F.shape[0], F.shape[1]
    F = np.roll(F, int(N/2), axis=0)
    F = np.roll(F, int(M/2), axis=1)
    
    return F

#去中心化
def ifshift(F):
    #两个轴平移半个周期
    M, N = F.shape[0], F.shape[1]
    F = np.roll(F, -int(N/2), axis=0)
    F = np.roll(F, -int(M/2), axis=1)
    
    return F

六、效果展示

首先,我们使用DFT得到图片的频率域,然后展示其频谱图。方法是先得到变换后结果的模长,然后使用log函数将其映射到图片可表示的范围。

#图像频谱
def fimage(img):
    return np.log(np.abs(img))
图2 (a)原图;(b)使用自己完成的DFT函数变换得到频谱图;
(c)使用自己完成的DFT函数和中心化函数变换得到的频谱图;
(d)使用numpy包中FFT函数和中心化函数变换得到的频谱图。

 接下来是将自己完成的函数和numpy包中函数混用的情况,从结果上看基本没有差别,可以认为实现效果还不错。

图3 (a)原图;
(b)使用自己实现的函数进行正变换后使用numpy包中的函数进行反变换;
(c)使用numpy包中的函数进行正变换后使用自己实现的函数进行反变换。

 七、多说两句

这篇文章参考《冈萨雷斯 数字图像处理(第四版)》,只是对书中核心内容进行了总结并加以实现,未涉及到的细节可见原著。

  • 14
    点赞
  • 75
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: 离散傅里叶变换DFT)是指将一个离散的信号序列转换为其频域表示的过程。它把一个有限长的离散序列映射到一个有限长的频域序列。 离散傅里叶变换是傅里叶变换在离散输入上的推广。它将一个长度为N的离散序列转换为一个长度为N的频域序列。在时域上,输入序列可以表示为离散时间的采样点集合。在频域上,它表示了输入信号的不同频率成分的幅度和相位。 离散傅里叶变换的计算过程包括两个步骤:首先,通过线性组合计算正弦和余弦函数的离散采样来表示信号;然后,再次对这些离散采样应用傅里叶变换公式以得到频域表示。 离散傅里叶变换广泛应用于信号处理和图像处理等领域。它可以用于频域滤波、快速傅里叶变换(FFT)、频谱分析等。通过DFT,我们能够将一个时域上的信号转换为其频域表示,从而能够更好地理解和处理信号的频率特性。 尽管离散傅里叶变换可以通过直接计算实现,但其计算复杂度较高,特别是对于较长的输入序列。快速傅里叶变换(FFT)是一种高效的算法,能够在O(NlogN)时间复杂度内计算离散傅里叶变换,其被广泛应用于实际应用中。 总之,离散傅里叶变换是将离散序列转换为其频域表示的过程,通过DFT我们可以了解信号的频率特性,并在信号处理中得到广泛应用。 ### 回答2: 离散傅里叶变换DFT)是将离散时间域信号转换成频域信号的一种数学变换方法。在信号处理和图像处理领域中广泛应用。 DFT的基本原理是将一个离散时间域信号分解为一系列复数的正弦和余弦函数分量,表示信号在不同频率上的振幅和相位信息。通过DFT,我们可以得到信号的频率特性,如频谱图、频率分量以及它们在时间上的实现方式。 DFT的计算是通过对输入信号的N个离散采样点进行离散傅里叶变换公式的运算得到的。公式可以描述为: X[k] = Σ(n=0 to N-1) x[n] * W^(-kn) 其中,X[k]表示输出频域信号的第k个频率分量,x[n]表示输入的时间域信号的第n个采样点,N表示信号的采样点数,W为复数旋转因子,定义为W = e^(-j2π/N)。 DFT计算的复杂度是O(N^2),这意味着当信号的采样点数增加时,计算所需的时间也会呈平方倍数增长。为了提高计算效率,可以使用快速傅里叶变换(FFT)算法,将计算复杂度降低到O(NlogN)的级别。 通过DFT,我们可以从时域的输入信号中得到其频域的频谱信息,进而可以进行频域滤波、频谱分析、频率特征提取等一系列信号处理操作。此外,DFT还广泛应用于音频处理、图像处理、通信系统等领域中。 ### 回答3: 离散傅里叶变换(Discrete Fourier Transform,DFT)是一种将离散序列(通常是时域上的信号)转换为频域上的表示的数学工具。它是傅里叶变换在离散信号上的推广。 DFT将一个长度为N的离散序列X={x_0, x_1, x_2, ..., x_{N−1}}转换为其频域表示X'={X_0, X_1, X_2, ..., X_{N−1}}。其中,X_k是X的第k个频谱系数,k=0,1,2,...,N−1。DFT的数学公式是: X_k = ∑_{n=0}^{N−1} x_n * exp(−2πikn/N),k=0,1,2,...,N−1。 DFT将一个信号分解为一系列正弦和余弦波的和,这些波的频率从0到N-1,每个波的振幅由X_k决定。相反地,逆DFTIDFT)可以从频域表示恢复出原始的时域序列。 DFT的应用十分广泛。对于信号处理,DFT可以用于频域滤波、谱分析和频谱合成等。在通信系统中,DFT被广泛应用于正交频分复用(OFDM)技术,其中信号在频域上被划分为多个子载波进行传输,利用DFT实现时域与频域之间的转换。此外,DFT还被应用于图像处理、声音合成、压缩和音频编码等领域。 尽管DFT是一种强大的工具,它的计算复杂度较高,特别是对于大规模的输入序列。为了解决这个问题,人们发展出了快速傅里叶变换(Fast Fourier Transform,FFT)算法,它通过利用DFT的对称性和周期性,将计算复杂度从O(N^2)降低到O(NlogN)。FFT广泛应用于实际工程中,提高了计算效率。 总结来说,DFT是将离散序列转换为频域表示的数学工具,广泛应用于信号处理、通信系统、图像处理等领域。它的计算复杂度较高,但通过FFT等算法可以得到高效的计算方法,为实际应用提供了便利。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值