做网站需要跟客户了解什么,深圳做企业网站的,电子商务就是网络营销,南京网页效果图设计接单第14章#xff1a;傅里叶变换一、理论基础#xff1a;二、Numpy实现傅里叶变换#xff1a;1. 实现傅里叶变换#xff1a;2. 逆傅里叶变换#xff1a;3. 高通滤波示例#xff1a;三、OpenCV实现傅里叶变换#xff1a;1. 实现傅里叶变换#xff1a;2. 实现逆傅里叶变换傅里叶变换一、理论基础二、Numpy实现傅里叶变换1. 实现傅里叶变换2. 逆傅里叶变换3. 高通滤波示例三、OpenCV实现傅里叶变换1. 实现傅里叶变换2. 实现逆傅里叶变换3. 低通滤波示例图像处理一般分为空间域处理和频率域处理。
空间域
空间域处理是直接对图像内的像素点进行处理。空间域处理主要划分为灰度变换和空间滤波两种形式。灰度变换是对图像内的单个像素进行处理比如调节对比度和处理域值等。空间滤波涉及图像的质量改变比如图像平滑处理。空间域处理的计算简单方便运算速度更快。
频率域
频率域处理是先将图像变换的频率域然后在频率域对图像进行处理最后在通过反变换将图像从频率域变换到空间域。傅里叶变换是应用最广泛的一种频域变换它能够将图像从空间域变换到频率域而你傅里叶变换能够将频率域信息变换到空间域内。傅里叶变换在图像处理领域有着非常重要的作用。
下面从理论基础、基本实现、具体应用等角度对傅里叶变回进行简单的介绍。
一、理论基础
傅里叶变换非常抽象很多人在工程中用了很多年的傅里叶变换也没有彻底了解傅里叶变回到底是怎么回事。为了更好的说明傅里叶变换我们先看生活中的一个例子。
下表所示是某饮料的配方该配方是一个以时间形式表示的表格表格很长这里仅仅截取了其中一部分。该表中记录冲时刻“0000”开始到某个特定时间“00:11”内的操作。 分析表格发现该配方
每隔1分钟放一块冰糖。每隔2分钟放3粒红豆。每隔3分钟放2粒绿豆。每隔4分钟放4块西红柿。每隔5分钟放1杯纯净水。
上述文字是从操作频率的角度对配方进行说明。
在数据处理过程中经常使用图表的形式表述信息。如果从时域的角度该配方表可以表示为如下图形式。 如果从频率(周期)的角度表示这个配方表可以表示为如下图形式图中横坐标是周期(频率的倒数)纵坐标是配料的份数。 对于函数同样可以将其从时域变换到频域。下图是一个频率为5(1秒5个周期)、振幅为1的正弦曲线。 如果从频率的角度考虑则可以将其绘制为如下图所示的频域图。图中横坐标是频率纵坐标是振幅。 上述两图是等价的他们是一个函数的两种不同表示方式。可以通过频域表示得到对应的时域表示也可以通过时域表示得到对应的频域表示。
法国数学家傅里叶指出任何周期函数都可以表示为不同频率的正弦函数和的形式。在今天看来这个理论是理所当然的但是这个理论难以理解在但是遭受了很大的质疑。
下面我们来看傅里叶变换的具体过程。例如周期函数的曲线如下图左上角所示。该周期函数可以表示为
y 3 * np.sin(0.8 * x) 7 * np.sin(0.5 * x) 2 * np.sin(0.2 * x)
因此该函数可以看成是由下列三个函数的和构成的
y1 3 * np.sin(0.8 * x)y2 7 * np.sin(0.5 * x)y3 2 * np.sin(0.2 * x)
上述三个函数对应的函数曲线分别如下图右上角、左下角、右下角的图所示。 如果从频域的角度考虑上述三个正弦函数可以分别表示为下图中的三根柱子图中横坐标是频率纵坐标是振幅。 通过以上分析可知图中左上角的曲线可以表示为上图所示的频域图。
从左上角的时域函数图形构造出上图所示频域图像的过程就是傅里叶变换。
左上角的时域函数图形与上图的频域图形表示的是完全相同的信息。傅里叶变换就是从频域的角度完整地表述时域信息。
除了上述的频率和振幅外还要考虑时间的问题。例如饮料配方为了控制风味需要严格控制加入配料的时间。上表中“00:00”时刻的操作在更精细的控制下实际上如下表所示。 如果加入配料的时间发生了变换饮料的风味就会发生变化。所以在实际处理过程中还要考虑时间差。这个时间差在傅里叶变换中就是相位。相位表述的时域时间差相关的信息。
例如函数
y 3 * np.sin(0.8 * x) 7 * np.sin(0.5 * 2 2) 2 * np.sin(0.2 * x 2)
可以看成下列三个函数的和的形式
y1 3 * np.sin(0.8 * x)y2 7 * np.sin(0.5 * x 2)y3 2 * np.sin(0.2 * x 3)
上述的四个函数分别对应的函数曲线为下图中的左上角、右上角、左下角、右下角。 在本例中如果把横坐标看成开始时间则构成函数y的三个正弦函数并不都是从0时刻开始的他们之间存在时间差。如果直接使用没有时间差的函数则无法构成上图左上角所示的函数而是会构成前面我们所说到的那个周期函数y 3 * np.sin(0.8 * x) 7 * np.sin(0.5 * x) 2 * np.sin(0.2 * x)。所以相差是傅里叶变换中一个非常重要的条件。
上面分别用饮料配方和函数的例子介绍了时域与频域转换的可行性以帮助我们来理解傅里叶变换。
在图形处理过程中傅里叶变换就是将图像分解成正弦分量和余弦分量两部分即将图像从空间域转换到频率域。 数字图像经过傅里叶变换后得到的频域是复数。因此显示傅里叶变换的结果需要使用实数图像(real image)加虚数图像(complex image)或者幅度图像(magnitude image)加相位图像(phase image)的形式。
因为幅度图像中包含了原图我们所需要的大部分信息所以图像处理过程中通常仅使用幅度图像。当然如果希望在频域内对图像进行处理在通过逆傅里叶变换得到修改后的空域图像。就必须同时保留幅度图像和相位图像。
对图像进行傅里叶变换后我们会得到图像中低频和高频的信息。低频信息对应图像中变化缓慢的灰度分量。高频信息对应图像内变换越来越快的灰度分量是由灰度的尖锐过渡造成的。例如在一幅大草原的图像中低频信息就对应着广袤的颜色趋于一致的草原等细节信息而高频信息则对应着狮子的轮廓等各种边缘及噪声信息。
傅里叶变换的目的就是为了将图像从空域转换到频域并在频域内实现对图像的特定处理然后再对经过处理的频域图像进行逆傅里叶变换得到空域图像。 傅里叶变换在图像处理领域发挥着非常关键的作用可以实现图像增强、图像去噪、边缘检测、特征提取、图像压缩和加密等。
二、Numpy实现傅里叶变换
Numpy模块提供了傅里叶变换功能Numpy模块中的fft2()函数可以实现图像的傅里叶变换。本节介绍如何用Numpy模块实现图像的傅里叶变换以及在频域内过滤图像的低频信息保留高频信息实现高通滤波。
1. 实现傅里叶变换
Numpy模块提供了实现傅里叶变换的函数numpy.fft.fft2()它的语法格式是
返回值numpy.fft.fft2(原始图像)
这里需要注意的是参数“原始图像”的类型是灰度图像函数的返回值是一个复数数组(complex ndarray)。
经过该函数的处理就能得到图像的频谱信息。此时图像频谱中的零频率分量位于频谱图像(频域图像)的左上角为了便于观察通常会使用numpy.fft.fftshift()函数将零频率成分移动到频域图像的中心位置如图所示。 函数numpy.fft.fftshift()的语法格式是
返回值numpy.fft.fftshift(原始频谱)
使用该函数处理后图像频谱中的零频率分量会被移到频域图像的中心位置对于观察傅里叶变换后频谱中的零频率部分非常有效。
对图像进行傅里叶变换后得到的是一个复数数组。为了显示为图像需要将它们的值调整到[0,255]的灰度空间内使用的公式为
像素新值20*np.log(np.abs(频谱值))
示例1实现傅里叶变换
import cv2
import numpy as np
import matplotlib.pyplot as pltimg cv2.imread(../lena.bmp, 0)f np.fft.fft2(img)
fshift np.fft.fftshift(f)
magnitude_spectrum 20 * np.log(np.abs(fshift))plt.subplot(1, 2, 1)
plt.imshow(img, cmapgray)
plt.title(original)
plt.axis(off)plt.subplot(1, 2, 2)
plt.imshow(magnitude_spectrum, cmapgray)
plt.title(result)
plt.axis(off)
plt.show()2. 逆傅里叶变换
需要注意的是如果在傅里叶变换过程中使用了numpy.fft.fftshift()函数移动零频率分量那么在逆傅里叶变换过程中需要先使用numpy.fft.ifftshift()函数将零频率分量移到原来的位置再进行逆傅里叶变换。 函数numpy.fft.ifftshift()是numpy.fft.fftshift()的逆函数其语法格式为
调整后的频谱numpy.fft.ifftshift(原始频谱)
numpy.fft.ifft2()函数是numpy.fft.fft2()的逆函数。用来实现逆傅里叶变换返回空域的复数数组。该函数的语法格式为
返回值numpy.fft.ifft2(频域数据)
函数numpy.fft.ifft2()的返回值仍旧是一个复数数组(complex ndarray)。
逆傅里叶变换得到的空域信息是一个复数数组需要将该信息调整至[0,255]灰度空间内使用的公式为
iimgnp.abs(逆傅里叶变换结果)
示例1实现逆傅里叶变换
import cv2
import numpy as np
import matplotlib.pyplot as pltimg cv2.imread(../boat.512.tiff, 0)
f np.fft.fft2(img)
fshift np.fft.fftshift(f)
magnitude_spectrum 20 * np.log(np.abs(fshift))ishift np.fft.ifftshift(fshift)
iimg np.fft.ifft2(ishift)
iimg np.abs(iimg)plt.subplot(131)
plt.imshow(img, cmapgray)
plt.title(img)
plt.axis(off)plt.subplot(132)
plt.imshow(magnitude_spectrum, cmapgray)
plt.title(fft2)
plt.axis(off)plt.subplot(133)
plt.imshow(iimg, cmapgray)
plt.title(iimg)
plt.axis(off)
plt.show()3. 高通滤波示例
在一幅图像内同时存在着高频信号和低频信号。
低频信号对应图像内变化缓慢的灰度分量。例如在一幅大草原的图像中低频信号对应着颜色趋于一致的广袤草原。高频信号对应图像内变化越来越快的灰度分量是由灰度的尖锐过渡造成的。如果在上面的大草原图像中还有一头狮子那么高频信号就对应着狮子的边缘等信息。
滤波器能够允许一定频率的分量通过或者拒绝其通过按照其作用方式可以划分为低通滤波器和高通滤波器。
允许低频信号通过的滤波器称为低通滤波器。低通滤波器使高频信号衰减而对低频信号放行会使图像变模糊。允许高频信号通过的滤波器称为高通滤波器。高通滤波器使低频信号衰减而让高频信号通过将增强图像中尖锐的细节但是会导致图像的对比度降低。
傅里叶变换可以将图像的高频信号和低频信号分离。 例如傅里叶变换可以将低频信号放置到傅里叶变换图像的中心位置如前图所示低频信号位于右图的中心位置。可以对傅里叶变换得到的高频信号和低频信号分别进行处理例如高通滤波或者低通滤波。在对图像的高频或低频信号进行处理后再进行逆傅里叶变换返回空域就完成了对图像的频域处理。通过对图像的频域处理可以实现图像增强、图像去噪、边缘检测、特征提取、压缩和加密等操作。
例如在下图所示左图original是原始图像中间的图像result是对左图original进行傅里叶变化后得到的结果右图则是对result进行高通滤波后的结果。将傅里叶变换结果图像result中的低频分量值都替换为0(处理为黑色)就屏蔽了低频信号只保留高频信号实现高通滤波。 要将上图中右图中间的像素值都置零需要先计算其中心位置的坐标然后选取以该坐标为中心上下左右各30个像素大小的区域将这个区域内的像素值置零。该滤波器的实现方法为 rows,colsimg.shape crow,ccolint(rows/2),int(cols/2) fshift[crow-30:crow30,ccol-30:ccol30]0
import cv2
import numpy as np
import matplotlib.pyplot as pltimg cv2.imread(../boat.512.tiff, 0)f np.fft.fft2(img)
fshift np.fft.fftshift(f)rows, cols img.shape
crow, ccol int(rows / 2), int(cols / 2)
fshift[crow - 30: crow 30, ccol - 30: ccol 30] 0ishift np.fft.ifftshift(fshift)
iimg np.fft.ifft2(ishift)
iimg np.abs(iimg)plt.subplot(121)
plt.imshow(img, cmapgray)
plt.title(original)
plt.axis(off)plt.subplot(122)
plt.imshow(iimg, cmapgray)
plt.title(iimg)
plt.axis(off)plt.show()三、OpenCV实现傅里叶变换
OpenCV提供了函数cv2.dft()和cv2.idft()来实现傅里叶变换和逆傅里叶变换。
1. 实现傅里叶变换
OpenCV中使用函数cv2.dft()进行傅里叶变换语法格式为
返回结果cv2.dft(原始图像转换标识)
在使用该函数时需要注意参数的使用规范
对于参数“原始图像”要首先使用np.float32()函数将图像转换成np.float32格式。“转换标识”的值通常为“cv2.DFT_COMPLEX_OUTPUT”用来输出一个复数阵列。
函数cv2.dft()返回的结果与使用Numpy进行傅里叶变换得到的结果是一致的但是它返回的值是双通道的第1个通道是结果的实数部分第2个通道是结果的虚数部分。
经过函数 cv2.dft()的变换后我们得到了原始图像的频谱信息。此时零频率分量并不在中心位置为了处理方便需要将其移至中心位置可以用函数numpy.fft.fftshift()实现。例如如下语句将频谱图像 dft 中的零频率分量移到频谱中心得到了零频率分量位于中心的频谱图像dftshift。
dftShiftnp.fft.fftshift(dft)
经过上述处理后频谱图像还只是一个由实部和虚部构成的值。要将其显示出来还要做进一步的处理才行。
函数cv2.magnitude()可以计算频谱信息的幅度。该函数的语法格式为
返回值cv2.magnitude(参数1参数2) 参数1浮点型x坐标值也就是实部。参数2浮点型y坐标值也就是虚部它必须和参数1具有相同的大小(size值的大小不是value值的大小)。
函数cv2.magnitude()的返回值是参数1和参数2的平方和的平方根公式为 I表示原始图像dst表示目标图像。
得到频谱信息的幅度后通常还要对幅度值做进一步的转换以便将频谱信息以图像的形式展示出来。简单来说就是需要将幅度值映射到灰度图像的灰度空间[0,255]内使其以灰度图像的形式显示出来。
这里使用的公式为
result20*np.log(cv2.magnitude(实部虚部))
示例1
import cv2
import numpy as npimg cv2.imread(../lena.bmp, 0)
dft cv2.dft(np.float32(img), flagscv2.DFT_COMPLEX_OUTPUT)
dft_shift np.fft.fftshift(dft)result 20 * np.log(cv2.magnitude(dft_shift[:, :, 0], dft_shift[:, :, 1]))print(dft)
print(dft_shift)
print(result)示例2用OpenCV函数对图像进行傅里叶变换并展示其频谱信息。
import cv2
import numpy as np
import matplotlib.pyplot as pltimg cv2.imread(../lena.bmp, 0)
dft cv2.dft(np.float32(img), flagscv2.DFT_COMPLEX_OUTPUT)
dft_shift np.fft.fftshift(dft)
result 20 * np.log(cv2.magnitude(dft_shift[:, :, 0], dft_shift[:, :, 1]))
plt.subplot(121)
plt.imshow(img, cmapgray)
plt.title(original)
plt.axis(off)plt.subplot(122)
plt.imshow(result, cmapgray)
plt.title(result)
plt.axis(off)plt.show()2. 实现逆傅里叶变换
在OpenCV中使用函数cv2.idft()实现逆傅里叶变换该函数是傅里叶变换函数cv2.dft()的逆函数。其语法格式为
返回结果cv2.idft(原始数据)
对图像进行傅里叶变换后通常会将零频率分量移至频谱图像的中心位置。如果使用函数numpy.fft.fftshift()移动了零频率分量那么在进行逆傅里叶变换前要使用函数numpy.fft.ifftshift()将零频率分量恢复到原来位置。
注意在进行逆傅里叶变换后得到的值仍旧是复数需要使用函数cv2.magnitude()计算其幅度。
示例
import cv2
import numpy as np
import matplotlib.pyplot as pltimg cv2.imread(../boat.512.tiff, 0)
dft cv2.dft(np.float32(img), flagscv2.DFT_COMPLEX_OUTPUT)
dft_shift np.fft.fftshift(dft)rst 20 * np.log(cv2.magnitude(dft_shift[:, :, 0], dft_shift[:, :, 1]))ishift np.fft.ifftshift(dft_shift)
iimg cv2.idft(ishift)
iimg cv2.magnitude(iimg[:, :, 0], iimg[:, :, 1])plt.subplot(131)
plt.imshow(img, cmapgray)
plt.title(original)
plt.axis(off)plt.subplot(132)
plt.imshow(rst, cmapgray)
plt.title(rst)
plt.axis(off)plt.subplot(133)
plt.imshow(iimg, cmapgray)
plt.title(iimg)
plt.axis(off)plt.show()3. 低通滤波示例
前面讲过在一幅图像内低频信号对应图像内变化缓慢的灰度分量。例如在一幅大草原的图像中低频信号对应着颜色趋于一致的广袤草原。低通滤波器让高频信号衰减而让低频信号通过图像进行低通滤波后会变模糊。
例如在下图中左图original是原始图像中间的图像result是对original进行傅里叶变换后得到的结果右图是低通滤波后的图像。将傅里叶变换结果图像result中的高频信号值都替换为0处理为黑色就屏蔽了高频信号只保留低频信号从而实现了低通滤波。
在实现低通滤波时可以专门构造一个如下图左图所示的掩码图像用它与原图的傅里叶变换频谱图像进行与运算就能将频谱图像中的高频信号过滤掉。 import cv2
import numpy as np
import matplotlib.pyplot as pltimg cv2.imread(../boat.512.tiff, 0)
dft cv2.dft(np.float32(img), flagscv2.DFT_COMPLEX_OUTPUT)
dft_shift 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 - 30: crow 30, ccol - 30: ccol 30] 1f_shift dft_shift * mask
print(f_shift)# mask np.zeros((rows, cols), np.uint8)
# mask[crow - 30: crow 30, ccol - 30: ccol 30] 1
# f_shift cv2.bitwise_and(dft_shift, dft_shift, maskmask)
# print(f_shift)ishift np.fft.ifftshift(f_shift)
iimg cv2.idft(ishift)
iimg cv2.magnitude(iimg[:, :, 0], iimg[:, :, 1])plt.subplot(121)
plt.imshow(img, cmapgray)
plt.title(original)
plt.axis(off)plt.subplot(122)
plt.imshow(iimg, cmapgray)
plt.title(iimg)
plt.axis(off)plt.show()