opencv - Fourier Transform 傅里叶变换

news2024/9/30 17:07:34

目标

在本节中,我们将学习

  • 使用 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 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()

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

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

所以您找到了频率变换现在您可以在频域中执行一些操作,例如高通滤波和重建图像,即找到逆 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 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),即我们传递 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 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

# or

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 倍。

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

论坛中提出了类似的问题。问题是,为什么拉普拉斯算子是高通滤波器?为什么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.coloradmin.cn/o/2180192.html

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

相关文章

优选驾考系统小程序的设计

管理员账户功能包括:系统首页,个人中心,驾校管理,驾考文章管理,驾照类型管理,报名入口管理,学员报名管理,练车预约管理,考试场地管理 微信端账号功能包括:系…

【羊毛资源】华为云开发者云主机免费申请使用指南

本文内容均来自个人笔记并重新梳理,如有错误欢迎指正! 如果对您有帮助,烦请点赞、关注、转发、订阅专栏! 专栏订阅入口 | 精选文章 | Kubernetes | Docker | Linux | 羊毛资源 | 工具推荐 | 往期精彩文章 【Docker】(全…

【GAN 图像生成】

理论知识学习: PART 1: 生成对抗网络GAN 深度学习模型,用于生成数据 对抗式训练,生成器v判别器 DCGAN>WGAN>StyleGAN技术不断进化 GAN在艺术创作。数据增强领域应用越来越广泛 应用: GAN在图像合成&#x…

生信初学者教程(十二):数据汇总

文章目录 介绍加载R包导入数据汇总表格输出结果总结介绍 在本教程中,汇总了三个肝细胞癌(HCC)的转录组数据集,分别是LIRI-JP,LIHC-US/TCGA-LIHC和GSE14520,以及一个HCC的单细胞数据集GSE149614的临床表型信息。这些数据集为科研人员提供了丰富的基因表达数据和相关的临床…

SqlAlchemy使用教程(七) 异步访问数据库

SqlAlchemy使用教程(一) 原理与环境搭建SqlAlchemy使用教程(二) 入门示例及编程步骤SqlAlchemy使用教程(三) CoreAPI访问与操作数据库详解SqlAlchemy使用教程(四) MetaData 与 SQL Express Language 的使用SqlAlchemy使用教程(五) ORM API 编程入门SqlAlchemy使用教程(六) – O…

Find My储物盒|苹果Find My技术与储物盒结合,智能防丢,全球定位

储物盒是用来存储,收藏东西的器具。储物盒可以帮助用户合理利用有限的空间,通过分类归置物品,避免浪费和混乱。储物盒能够有效地保护存放的物品,防止它们受到灰尘、污渍、损坏和潮湿的影响。储物盒还可以增加空间利用率、方便搬家…

Windows环境下使用Docker配置MySQL数据库

用Docker配置数据库,无论是做开发,还是做生产部署,都非常的方便 它不需要单独安装数据库,也不用担心出现各种环境的配置问题。 本文将分享用Docker配置数据库的步骤,这里用MySQL举例。 其他的数据库如MSSQL&#xf…

全球IP归属地查询-IP地址查询-IP城市查询-IP地址归属地-IP地址解析-IP位置查询-IP地址查询API接口

IP地址城市版查询接口 API是指能够根据IP地址查询其所在城市等地理位置信息的API接口。这类接口在网络安全、数据分析、广告投放等多个领域有广泛应用。以下是一些可用的IP地址城市版查询接口API及其简要介绍 1. 快证 IP归属地查询API 特点:支持IPv4 提供高精版、…

Scalefit:有效避免工作场所运动损伤的解决方案

在当今快节奏的工作环境中,运动损伤已成为一个不容忽视的问题。长时间的久坐、重复性动作以及缺乏适当的运动,都可能导致肌肉骨骼损伤、关节疼痛等问题。作为一款专注于运动健康管理的平台,Scalefit Industrial Athlete通过科学的方法和个性化…

天坑!Spark+Hive+Paimon+Dolphinscheduler

背景: 数据中台项目使用Spark+Hive+Paimon做湖仓底层,调度任务使用的是基于Dolphinscheduler进行二开。在做离线脚本任务开发时,在Paimon库下执行非查询类SQL报错。 INSERT报错 DELETE报错 现状: 原始逻辑为数据中台中选择的Paimon数据源,实际上在Dolphinscheduler中是…

生成靶标图像代码——C语言代码实现

1. 生成左右相机拍摄的3个彩色靶标的图像 两个相机在x轴方向上平移 // 生成左右相机拍摄3个靶标时的图像 生成彩色靶标 #include <stdio.h> #include <stdlib.h> #include <math.h>// 图像尺寸 #define WIDTH 1920 #define HEIGHT 1080// BMP头信息 #pra…

掌握自动化测试必要的几种技能?

1.自动化测试员技能——编程语言 当我开始担任手动测试人员时&#xff0c;我不喜欢编码。但是&#xff0c;当我逐渐进入自动化领域时&#xff0c;对我来说很清楚&#xff0c;如果没有对编程语言的一些基本了解&#xff0c;就无法编写逻辑自动化测试脚本。 对编程有一点了解&a…

短视频矩阵源码oem/矩阵系统搭建/源码开发注意事项知识分享

短视频矩阵系统的源码框架主要涵盖Spring、Struts与Hibernate三种。Spring是一款全栈式Java应用开发框架&#xff0c;集成了IOC容器、AOP以及事务管理等关键功能。Struts则基于MVC架构设计&#xff0c;用于Web应用程序的开发&#xff0c;有效分离数据模型、用户界面及控制器逻辑…

全面指南:探索并实施解决Windows系统中“mfc140u.dll丢失”的解决方法

当你的电脑出现mfc140u.dll丢失的问题是什么情况呢&#xff1f;mfc140u.dll文件依赖了什么&#xff1f;mfc140u.dll丢失会导致电脑出现什么情况&#xff1f;今天这篇文章就和大家聊聊mfc140u.dll丢失的解决办法。希望能够有效的帮助你解决这问题。 哪些程序依赖mfc140u.dll文件…

深圳市软件行业协会领导到访开源网安,共筑大湾区数字经济安全未来

近日&#xff0c;深圳市软件行业协会会长邓爱国、秘书长郑飞等一行人到访开源网安进行参观交流。双方以网信行业技能培训、软件安全开发能力评价和智能网联汽车安全测试等方面为探讨方向&#xff0c;对未来的合作进行了深入交流。 在参观过后&#xff0c;深圳市软件行业协会相关…

查找满足条件的行序号

有 2022 年 1 月的日销售额统计表如下所示&#xff1a; 找出日销售额大于 1000 的日子&#xff1a; spl("E(?1).pselecta(Sales>1000)",A1:B32)pselecta()返回所有满足条件的记录序号&#xff0c;pselect() 则只返回第一个满足条件的行序号 免费课程、免费软件下…

Elasticsearch要点简记

Elasticsearch要点简记 1、ES概述2、基础概念&#xff08;1&#xff09;索引、文档、字段&#xff08;2&#xff09;映射&#xff08;3&#xff09;DSL 3、架构原理4、索引字段的数据类型5、ES的三种分页方式&#xff08;1&#xff09;深度分页&#xff08;fromsize&#xff09…

码随想录算法训练营第60天|卡码网:94. 城市间货物运输 I、95. 城市间货物运输 II、96. 城市间货物运输 III

1.卡码网&#xff1a;94. 城市间货物运输 I 题目链接&#xff1a;https://kamacoder.com/problempage.php?pid1152 文章链接&#xff1a;https://www.programmercarl.com/kamacoder/0094.城市间货物运输I-SPFA.html 思路&#xff1a; 只对 上一次松弛的时候更新过的节点作为出…

智能餐饮:Spring Boot 点餐系统

第四章 系统设计 4.1 系统体系结构 网上点餐系统的结构图4-1所示&#xff1a; 图4-1 系统结构 模块包括主界面&#xff0c;首页、个人中心、用户管理、美食店管理、美食分类管理、美食信息管理、美食订单管理、美食评价管理、系统管理等进行相应的操作。 登录系统结构图&…

2025年3月PMP考试《PMBOK®指南》第六版不再作为参考资料

大家都知道《PMBOK指南》第六版是PMP认证考试的必备教材&#xff0c;由项目管理协会&#xff08;PMI&#xff09;指定。本书详细介绍了项目管理的5个过程组&#xff0c;并对项目管理的10个知识领域进行了阐述。 就在2024.9.30昨天的时候中国国际人才交流基金会公布了&#xff…