IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 人工智能 -> opencv-python学习笔记(十二)—— 图像处理之傅里叶变换 -> 正文阅读

[人工智能]opencv-python学习笔记(十二)—— 图像处理之傅里叶变换

系列文章目录

FFT

利用OpenCV对图像进行傅里叶变换、使用Numpy中可用的FFT函数、傅里叶变换的一些应用

相关函数: cv.dft(), cv.idft()

1. 理论

采用傅里叶变换分析各种滤波器的频率特性。对于图像,采用二维离散傅里叶变换(DFT)来求频域。DFT的计算采用了快速傅里叶变换(FFT)算法。关于这些的细节可以在任何图像处理或信号处理的教科书中找到。请参阅附加参考资料部分。

正弦信号 x ( t ) = A sin ? ( 2 π f t ) x(t)=A \sin (2 \pi f t) x(t)=Asin(2πft),我们可以说f是信号的频率,如果观察其频域,我们可以看到一个峰值在f。如果信号采样形成离散信号,我们得到相同的频域,但周期为(?π,π]或[0,2π)(在N-point DFT中为(0,N))。你可以把一幅图像看作是一个在两个方向上采样的信号。在X和Y方向上进行傅里叶变换得到图像的频率表示。

更直观地说,对于正弦信号,如果振幅在短时间内变化如此之快,你可以说它是一个高频信号。如果变化缓慢,则为低频信号。你可以把同样的想法延伸到图像上。振幅在图像中什么地方变化很大?在边缘点,或噪音。所以我们可以说,边缘和噪声是图像中的高频内容。如果振幅变化不大,则为低频分量。(一些链接被添加到附加资源_,它直观地解释了频率转换的例子)。

现在我们来看看如何求傅里叶变换。

2. 傅里叶变换(Numpy)

首先,我们将看到如何使用Numpy进行傅里叶变换。Numpy有一个FFT包来做这个。Np.fft.fft2()为我们提供了一个复杂数组的频率变换。它的第一个参数是输入图像,即灰度。第二个参数是可选的,它决定输出数组的大小。如果大于输入图像的大小,则在FFT计算前用零填充输入图像。如果小于输入图像,输入图像将被裁剪。如果没有传入参数,输出数组的大小将与输入数组相同。

现在一旦你得到结果,零频率成分(直流成分)将在左上角。如果你想让它居中,你需要在两个方向上移动N/2。这只是由函数**np.fft.fftshift()**完成。(这样分析起来更直观)。一旦你找到了频率变换,你就能找到幅度谱。

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
img = cv.imread('messi5.jpg',0)
f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)
magnitude_spectrum = 20*np.log(np.abs(fshift))
plt.subplot(121),plt.imshow(img, cmap = 'gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(magnitude_spectrum, cmap = 'gray')
plt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([])
plt.show()

在这里插入图片描述
看,你可以在中心看到更多的白色区域,其表示低频成分。

所以你实现了频率变换,现在你可以在频域做一些操作,比如高通滤波和重建图像,或者相反。为此,你只需通过一个大小为60x60的矩形窗口来屏蔽低频。然后使用np.fft.ifftshift()进行逆变换,使直流成分再次出现在左上角。然后使用np.ifft2()函数找到逆FFT。结果还是一个复数。可以取它的绝对值。

rows, cols = img.shape
crow,ccol = rows//2 , cols//2
fshift[crow-30:crow+31, ccol-30:ccol+31] = 0
f_ishift = np.fft.ifftshift(fshift)
img_back = np.fft.ifft2(f_ishift)
img_back = np.real(img_back)
plt.subplot(131),plt.imshow(img, cmap = 'gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(132),plt.imshow(img_back, cmap = 'gray')
plt.title('Image after HPF'), plt.xticks([]), plt.yticks([])
plt.subplot(133),plt.imshow(img_back)
plt.title('Result in JET'), plt.xticks([]), plt.yticks([])
plt.show()

在这里插入图片描述
结果说明高通滤波器是一种边缘提取操作。这一点我们在前面的图像梯度章节里面提到过。这也说明了图像中大部分成分都是低频部分。不管怎样,我们已经看到了如何在Numpy中找到DFT, IDFT等。现在让我们看看如何在OpenCV中做。

如果仔细观察结果,特别是最后一张JET颜色的图像,你可以看到一些成分(我用红色箭头标记的一个实例)。它显示出一些波纹状的结构,这被称为振铃效应。这是由于我们用矩形窗口做mask造成的。这个mask被转换成sin形状,这导致了这个问题。所以矩形窗口不用于过滤。更好的选择是Gaussian窗口。

3. 傅里叶变换(Opencv)

OpenCV为此提供了 cv.dft()cv.idft() 函数。它返回与前面相同的结果,但是有两个通道。第一个通道是结果的实部,第二个通道是结果的虚部。输入图像应先转换为np.float32。我们将看到如何去做。

import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread('messi5.jpg',0)
dft = cv.dft(np.float32(img),flags = cv.DFT_COMPLEX_OUTPUT)
dft_shift = np.fft.fftshift(dft)
magnitude_spectrum = 20*np.log(cv.magnitude(dft_shift[:,:,0],dft_shift[:,:,1]))
plt.subplot(121),plt.imshow(img, cmap = 'gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(magnitude_spectrum, cmap = 'gray')
plt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([])
plt.show()

注意:你也可以使用 cv.cartToPolar(),它在同时返回幅度和相位

现在我们要做逆DFT。在之前的会话中,我们创建了一个HPF(高通滤波器),这一次我们将看到如何删除图像中的高频内容,即我们应用LPF(低通滤波器)。它实际上模糊了图像。为此,我们首先创建一个掩膜,其在低频部分为1,高频部分为0。

rows, cols = img.shape
crow,ccol = rows/2 , cols/2
# create a mask first, center square is 1, remaining all zeros
mask = np.zeros((rows,cols,2),np.uint8)
mask[crow-30:crow+30, ccol-30:ccol+30] = 1
# apply mask and inverse DFT
fshift = dft_shift*mask
f_ishift = np.fft.ifftshift(fshift)
img_back = cv.idft(f_ishift)
img_back = cv.magnitude(img_back[:,:,0],img_back[:,:,1])# 计算幅度
plt.subplot(121),plt.imshow(img, cmap = 'gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(img_back, cmap = 'gray')
plt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([])
plt.show()

对于cv.magnitude,其作用是计算二维矢量的大小。即对于矢量 ( x , y ) (x,y) (x,y),计算其大小(模):
dst ( I ) = x ( I ) 2 + y ( I ) 2 \texttt{dst} (I) = \sqrt{\texttt{x}(I)^2 + \texttt{y}(I)^2} dst(I)=x(I)2+y(I)2 ?
结果:
在这里插入图片描述

4. DFT的性能优化

对于某些数组大小,DFT计算的性能更好。当数组大小是2的幂时,它是最快的。对于大小为2、3和5的乘积的数组,处理效率也相当高。因此,如果你担心代码的性能,可以在找到DFT之前将数组的大小修改为任何最佳大小(通过填充零)。对于OpenCV,你必须手动填充零。但是对于Numpy,你指定FFT计算的新大小,它会自动为你补零。

那么如何找到最优大小呢?OpenCV为此提供了一个函数cv.getOptimalDFTSize()。cvt .dft()和np.fft.fft2()都适用。让我们使用IPython magic命令timeit来检查它们的性能。

In [16]: img = cv.imread('messi5.jpg',0)
In [17]: rows,cols = img.shape
In [18]: print("{} {}".format(rows,cols))
342 548
In [19]: nrows = cv.getOptimalDFTSize(rows)
In [20]: ncols = cv.getOptimalDFTSize(cols)
In [21]: print("{} {}".format(nrows,ncols))
360 576

看,大小(342,548)被修改为(360,576)。现在让我们用零填充它(对于OpenCV),并找出它们的DFT计算性能。你可以通过创建一个新的大一点的全零数组并将数据复制到它来实现,或者使用cv.copyMakeBorder()。

nimg = np.zeros((nrows,ncols))
nimg[:rows,:cols] = img

或者

right = ncols - cols
bottom = nrows - rows
bordertype = cv.BORDER_CONSTANT #just to avoid line breakup in PDF file
nimg = cv.copyMakeBorder(img,0,bottom,0,right,bordertype, value = 0)

现在我们进行Numpy函数的DFT性能比较:

In [22]: %timeit fft1 = np.fft.fft2(img)
10 loops, best of 3: 40.9 ms per loop
In [23]: %timeit fft2 = np.fft.fft2(img,[nrows,ncols])
100 loops, best of 3: 10.4 ms per loop

可以看出快了4倍。现在我们将对OpenCV函数进行同样的尝试。

In [24]: %timeit dft1= cv.dft(np.float32(img),flags=cv.DFT_COMPLEX_OUTPUT)
100 loops, best of 3: 13.5 ms per loop
In [27]: %timeit dft2= cv.dft(np.float32(nimg),flags=cv.DFT_COMPLEX_OUTPUT)
100 loops, best of 3: 3.11 ms per loop

可以看出快了4倍。你还可以看到OpenCV函数比Numpy函数快3倍左右。这也可以用来测试逆FFT,留给你们做练习。

5. 为什么 Laplacian是高通滤波器?

类似的问题也在一个论坛上被问及。问题是,为什么Laplacian是高通滤波器?为什么sobel是高通滤波器?等。第一个问题的答案与傅里叶变换有关。对更大尺寸的傅里叶变换进行拉普拉斯变换。分析:

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
# simple averaging filter without scaling parameter
mean_filter = np.ones((3,3))
# creating a gaussian filter
x = cv.getGaussianKernel(5,10)
gaussian = x*x.T
# different edge detecting filters
# scharr in x-direction
scharr = np.array([[-3, 0, 3],
                   [-10,0,10],
                   [-3, 0, 3]])
# sobel in x direction
sobel_x= np.array([[-1, 0, 1],
                   [-2, 0, 2],
                   [-1, 0, 1]])
# sobel in y direction
sobel_y= np.array([[-1,-2,-1],
                   [0, 0, 0],
                   [1, 2, 1]])
# laplacian
laplacian=np.array([[0, 1, 0],
                    [1,-4, 1],
                    [0, 1, 0]])
filters = [mean_filter, gaussian, laplacian, sobel_x, sobel_y, scharr]
filter_name = ['mean_filter', 'gaussian','laplacian', 'sobel_x', \
                'sobel_y', 'scharr_x']
fft_filters = [np.fft.fft2(x) for x in filters]
fft_shift = [np.fft.fftshift(y) for y in fft_filters]
mag_spectrum = [np.log(np.abs(z)+1) for z in fft_shift]
for i in range(6):
    plt.subplot(2,3,i+1),plt.imshow(mag_spectrum[i],cmap = 'gray')
    plt.title(filter_name[i]), plt.xticks([]), plt.yticks([])
plt.show()

在这里插入图片描述

从图像中,你可以看到每个内核块的频率区域,以及它经过的区域。从这些信息中,我们可以知道为什么每个内核都是HPF或LPF

扩展资料

  1. An Intuitive Explanation of Fourier Theory by Steven Lehar
  2. Fourier Transform at HIPR
  3. What does frequency domain denote in case of images?

参考:https://docs.opencv.org/4.5.2/dd/dc4/tutorial_py_table_of_contents_transforms.html

  人工智能 最新文章
2022吴恩达机器学习课程——第二课(神经网
第十五章 规则学习
FixMatch: Simplifying Semi-Supervised Le
数据挖掘Java——Kmeans算法的实现
大脑皮层的分割方法
【翻译】GPT-3是如何工作的
论文笔记:TEACHTEXT: CrossModal Generaliz
python从零学(六)
详解Python 3.x 导入(import)
【答读者问27】backtrader不支持最新版本的
上一篇文章      下一篇文章      查看所有文章
加:2021-07-11 16:38:36  更:2021-07-11 16:40:35 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/22 11:18:00-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码