opencv - Fourier Transform 傅里叶变换

目标

在本节中,我们将学习

  • 使用 OpenCV 查找图像的傅里叶变换
  • 利用 Numpy 中可用的 FFT 函数
  • 傅里叶变换的一些应用
  • 我们将看到以下函数:cv.dft()cv.idft()

理论

傅里叶变换用于分析各种滤波器的频率特性。对于图像,2D 离散傅里叶变换 (DFT) 用于查找频域。一种称为快速傅里叶变换 (FFT) 的快速算法用于计算 DFT。有关这些的详细信息可以在任何图像处理或信号处理教科书中找到。请参阅其他资源部分。

对于正弦信号 x ( t ) = A sin ⁡ ( 2 π f t ) x(t) = A \sin(2 \pi ft) x(t)=Asin(2πft) ,我们可以说 f 是信号的频率,如果取其频域,我们可以在 f 处看到一个尖峰。如果对信号进行采样以形成离散信号,我们会得到相同的频域,但在 [ − π , π ] [- \pi, \pi] [π,π] [ 0 , 2 π ] [0,2\pi] [0,2π](或 N 点 DFT 的 [ 0 , N ] [0,N] [0,N])范围内具有周期性。您可以将图像视为在两个方向上采样的信号。因此,在 X 和 Y 方向上进行傅里叶变换可以得到图像的频率表示。

更直观地,对于正弦信号,如果幅度在短时间内变化如此之快,您可以说它是一个高频信号。如果它变化缓慢,它就是一个低频信号。您可以将同样的想法扩展到图像。图像中幅度在哪里急剧变化?在边缘点或噪声处。所以我们可以说,边缘和噪声是图像中的高频内容。如果幅度没有太大变化,它就是低频分量。

现在我们将看到如何找到傅里叶变换。

Numpy 中的傅里叶变换

首先,我们将了解如何使用 Numpy 查找傅里叶变换。Numpy 有一个 FFT 包可以执行此操作。np.fft.fft2() 为我们提供了频率变换,它将是一个复杂数组。它的第一个参数是输入图像,它是灰度的。第二个参数是可选的,它决定输出数组的大小。如果它大于输入图像的大小,则在计算 FFT 之前用零填充输入图像。如果它小于输入图像,则输入图像将被裁剪。如果没有传递参数,则输出数组大小将与输入相同。

现在,一旦您得到结果,零频率分量(DC 分量)将位于左上角。如果您想将其置于中心,则需要在两个方向上将结果移动 N 2 \frac{N}{2} 2N。这只需通过函数 np.fft.fftshift() 即可完成。(它更容易分析)。一旦找到频率变换,就可以找到幅度谱。

import cv2 as cv
import numpy as np
from matplotlib import pyplot as pltimg = 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()

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

看,您可以看到中心有更多白色区域,表明低频内容更多。

所以您找到了频率变换现在您可以在频域中执行一些操作,例如高通滤波和重建图像,即找到逆 DFT。为此,您只需使用大小为 60x60 的矩形窗口进行掩蔽即可去除低频。然后使用 np.fft.ifftshift() 应用逆移位,以便 DC 分量再次出现在左上角。然后使用 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 颜色的图像,您会看到一些伪影(我用红色箭头标记了一个实例)。它显示了一些类似波纹的结构,这被称为振铃效应。这是由我们用于掩蔽的矩形窗口引起的。此掩码转换为 sinc 形状,从而导致此问题。因此,矩形窗口不用于过滤。更好的选择是高斯窗口。

OpenCV 中的傅里叶变换

OpenCV 为此提供了 cv.dft()cv.idft() 函数。它返回的结果与上一个相同,但有两个通道。第一个通道将具有结果的实部,第二个通道将具有结果的虚部。首先应将输入图像转换为 np.float32。我们将了解如何执行此操作。

import numpy as np
import cv2 as cv
from matplotlib import pyplot as pltimg = 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),即我们传递 LF 内容,在 HF 区域为 0。

rows, cols = img.shape
crow,ccol = rows/2 , cols/2
# 首先创建一个掩码,中心方块为 1,其余全部为零
mask = np.zeros((rows,cols,2),np.uint8)
mask[crow-30:crow+30, ccol-30:ccol+30] = 1
# 应用掩码并进行逆 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()

查看结果:

在这里插入图片描述

注意: 与往常一样,OpenCV 函数 cv.dft()cv.idft() 比 Numpy 函数更快。但 Numpy 函数更易于使用。有关性能问题的更多详细信息,请参阅以下部分。

DFT 的性能优化

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

那么我们如何找到这个最佳大小?OpenCV 为此提供了一个函数 cv.getOptimalDFTSize()。它适用于 cv.dft()np.fft.fft2()。让我们使用 IPython 魔法命令 %timeit 检查它们的性能。

In [16]: img = cv.imread('messi5.jpg',0)
In [17]: rows,cols = img.shape
In [18]: print("{} {}".format(rows,cols))
342 548In [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# orright = 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 倍。

为什么拉普拉斯算子是高通滤波器?

论坛中提出了类似的问题。问题是,为什么拉普拉斯算子是高通滤波器?为什么Sobel是 HPF?等等。对此给出的第一个答案是从傅里叶变换的角度。只需对拉普拉斯算子的傅里叶变换进行更高尺寸的 FFT 即可。分析它:

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
# 没有缩放参数的简单平均滤波器
mean_filter = np.ones((3,3))
# 创建高斯滤波器
x = cv.getGaussianKernel(5,10)
gaussian = x*x.T
# 不同的边缘检测滤波器
# x 方向上的 scharr
scharr = np.array([[-3, 0, 3],[-10,0,10],[-3, 0, 3]])# x 方向上的 sobel
sobel_x= np.array([[-1, 0, 1],[-2, 0, 2],[-1, 0, 1]])# y 方向上的 sobel
sobel_y= np.array([[-1,-2,-1],[0, 0, 0],[1, 2, 1]])# 拉普拉斯算子
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

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

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

相关文章

Android Studio 新版本 Logcat 的使用详解

点击进入官方Logcat介绍 一个好的Android程序员要会使用AndroidStudio自带的Logcat查看日志,会Log定位也是查找程序bug的第一关键。同时Logcat是一个查看和处理日志消息的工具,它可以更快的帮助开发者调试应用程序。 步入正题,看图说话。 点…

sql-server【bcp工具】

目录 1.查看bcp是否可用 2.bcp 命令的基本语法 3.数据导出 4.数据导入 bcp(Bulk Copy Program)是 SQL Server 提供的一个命令行工具,用于在 SQL Server 实例与用户指定格式的数据文件之间批量复制表或视图数据。bcp 工具非常适合进行大量…

基于Spark的汽车行业大数据分析及可视化系统

作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏:…

【leetcode】121.买卖股票的最佳时机

思路&#xff1a; 找到后面与前面的差值最大即可。 代码&#xff1a; int maxProfit(int* prices, int pricesSize) {int i 0, j 0;//i是后一个最大的&#xff0c;j是前面最小的int max 0, temp 0;//表示最大值for (i 1; i < pricesSize; i){if (prices[j] < pr…

产品经理的学习

初学 接需求 画原型 写文档 日常产出 流程图 举例购物的流程 结构图 一个应用的全部功能&#xff0c;用思维导图的方式去罗列出来 竞品分析文档 竞品分类 竞品选择 竞品采集 竞品文档书写 也可以做一个产品的产品结构图 需求文档 干系人 需求方 记录人 产品经理 其他项目干系人…

【办公类-48-03】20240930每月电子屏台账汇总成docx-3(三园区合并EXCLE,批量生成3份word)

背景需求&#xff1a; 前期电子屏汇总是“总园”用“”问卷星”、“一分园”用“腾讯文档”&#xff0c;二分园“用“手写word”” 【办公类-48-02】20240407每月电子屏台账汇总成docx-2&#xff08;腾讯文档xlsx导入docx&#xff0c;每页20条&#xff09;【办公类-48-02】20…

腾讯云新开端口

检查防火墙设置 890 2024-09-30 20:47:18 netstat -tuln | grep 1213891 2024-09-30 20:47:49 ping 110.40.130.231892 2024-09-30 20:48:38 sudo firewall-cmd --zonepublic --add-port1213/tcp --permanent893 2024-09-30 20:48:51 sudo firewall-cmd --reload894 2024-…

汽车线束之故障诊断方案-TDR测试

当前&#xff0c;在汽车布局中的线束的性能要求越来越高。无法通过简单的通断测试就能满足性能传输要求。早起对智能化要求不高&#xff0c;比如没有激动雷达、高清摄像、中央CPU等。 近几年的智能驾驶对网络传输要求越来越高&#xff0c;不但是高速率&#xff0c;还需要高稳定…

常见的RTSP播放器有哪些?

VLC播放器 特点&#xff1a;VLC 是一款功能强大、跨平台的多媒体播放器&#xff0c;支持多种音频和视频格式以及流媒体协议&#xff0c;包括 RTSP。它具有广泛的解码器支持&#xff0c;能播放大多数常见的视频和音频格式。其开源特性使得它拥有活跃的开发者社区&#xff0c;不断…

HCIP--以太网交换安全(一)

目录 端口隔离 MAC地址表安全 以太网交换安全概述&#xff1a;以太网交换安全是一系列技术和策略的集合&#xff0c;旨在保护以太网交换机免受各种网络攻击和威胁。 端口隔离 一、端口隔离概述&#xff1a; 作用&#xff1a;可以实现同一个VLAN内端口的隔离 优势&#xff1a…

modelsim仿真 wave视图里 数据位宽和进制怎么显示

在modelsim 某些版本安装后&#xff0c;如ModelSim SE-64 2020.4版本&#xff0c;重置布局等情况下&#xff0c; 解决方案其实很简单&#xff1a; 点击中间的按钮 在Wave Windows Preferences 勾选Display-Show Radix Base -> Waveforms

Lj视频下载器 1.1.37 简洁高效的视频下载工具

Lj视频下载器是一个功能强大的视频下载器&#xff0c;支持直接添加视频地址或 m3u8 资源地址&#xff0c;可以从网页中自动提取视频进行下载。支持多种视频格式&#xff0c;包括 m3u8&#xff0c;并能自动检测并移除广告片段。 大小&#xff1a;19M 百度网盘&#xff1a;https…

音悦 1.5.1 完全免费,无广告,纯净听歌体验

音悦是一款完全免费的听歌应用&#xff0c;汇聚全网多平台曲库&#xff0c;拥有排行榜、MV、个性电台、我的歌单、收藏喜欢等功能。无需会员&#xff0c;没有广告&#xff0c;免费听歌下歌&#xff0c;是一款非常纯净小巧但功能齐全的听歌神器。 大小&#xff1a;27.6M 百度网…

YOLOv11尝鲜测试五分钟极简配置

ultralytics团队在最近又推出了YOLOv11&#xff0c;不知道在有生之年能不能看到YOLOv100呢哈哈。 根据官方文档&#xff0c;在 Python>3.8并且PyTorch>1.8的环境下即可安装YOLOv11&#xff0c;因此之前YOLOv8的环境是可以直接用的。 安装YOLOv11&#xff1a; pip instal…

yum使用阿里云的镜像源报错 Failed connect to mirrors.aliyuncs.com:80; Connection refused“

报错&#xff1a;Failed connect to mirrors.aliyuncs.com:80; Connection refused"&#xff0c;如果单独只是这个报错的话&#xff0c;那么原因是由于非阿里云ECS用户无法解析主机“mirrors.cloud.aliyuncs.com”。如果不单单只是这个报错另外还有其它报错请参考我其它文…

Redis 五大基本数据类型及其应用场景进阶(缓存预热、雪崩 、穿透 、击穿)

Redis 数据类型及其应用场景 Redis 是什么? Redis是一个使用C语言编写的高性能的基于内存的非关系型数据库&#xff0c;基于Key/Value结构存储数据&#xff0c;通常用来 缓解高并发场景下对某一资源的频繁请求 &#xff0c;减轻数据库的压力。它支持多种数据类型,如字符串、…

YOLOv11改进策略【损失函数篇】| Shape-IoU:考虑边界框形状和尺度的更精确度量

一、本文介绍 本文记录的是改进YOLOv11的损失函数&#xff0c;将其替换成Shape-IoU。现有边界框回归方法通常考虑真实GT&#xff08;Ground Truth&#xff09;框与预测框之间的几何关系&#xff0c;通过边界框的相对位置和形状计算损失&#xff0c;但忽略了边界框本身的形状和…

IDEA几大常用AI插件

文章目录 前言列表GPT中文版TalkXBito AIIDEA自带的AI 前言 最近AI、GPT特别火&#xff0c;IDEA里面又有一堆插件支持GPT&#xff0c;所以做个专题比较一下各个GPT插件 列表 先看idea的plugins里支持哪些&#xff0c;搜索“GPT”之后得到的&#xff0c;我用下来感觉第一第二和…

[网络]抓包工具介绍 tcpdump

一、tcpdump tcpdump是一款基于命令行的网络抓包工具&#xff0c;可以捕获并分析传输到和从网络接口流入和流出的数据包。 1.1 安装 tcpdump 通常已经预装在大多数 Linux 发行版中。如果没有安装&#xff0c;可以使用包管理器 进行安装。例如 Ubuntu&#xff0c;可以使用以下…