图像处理:使用Numpy和OpenCV实现傅里叶和逆傅里叶变换

news2025/5/16 13:08:12

文章目录

1、什么是傅里叶变换及其基础理论

 1.1 傅里叶变换

1.2 基础理论

2. Numpy 实现傅里叶和逆傅里叶变换

2.1 Numpy 实现傅里叶变换

2.2 实现逆傅里叶变换

2.3 高通滤波示例

3. OpenCV 实现傅里叶变换和逆傅里叶变换及低通滤波示例

3.1 OpenCV 实现傅里叶变换

3.2 实现逆傅里叶变换

3.3 低通滤波示例


1、什么是傅里叶变换及其基础理论

 1.1 傅里叶变换

图像处理一般分为直接对图像内的像素进行处理的空间域处理和频率域处理。

空间域处理主要划分为灰度变换和空间滤波两种形式。

  • 灰度变换是对图像内的单个像素进行处理,比如调节对比度和处理阈值等。
  • 空间滤波涉及图像质量的改变,例如图像平滑处理。空间域处理的计算简单方便,运算速度更快。

频率域处理是先将图像变换到频率域,然后在频率域对图像进行处理,最后再通过反变换将图像从频率域变换到空间域。

1.2 基础理论

时间差,在傅里叶变换里就是相位。相位表述的是与时间差相关的信息。

在图像处理过程中,傅里叶变换就是将图像分解为正弦分量和余弦分量两部分,即将图像从空间域转换到频域。

数字图像经过傅里叶变换后,得到的频域值是复数。因此,显示傅里叶变换的结果需要使用实数图像(real image)加虚数图像(complex image),或者幅度图像(magnitude image)加相位图像(phase image)的形式。因为幅度图像包含了原图像中我们所需要的大部分信息,所以在图像处理过程中,通常仅使用幅度图像。

如果希望先在频域内对图像进行处理,再通过逆傅里叶变换得到修改后的空域图像,就必须同时保留幅度图像和相位图像。对图像进行傅里叶变换后,会得到图像中的低频和高频信息。低频信息对应图像内变化缓慢的灰度分量。高频信息对应图像内变化越来越快的灰度分量,是由灰度的尖锐过渡造成的。

傅里叶变换的目的,就是为了将图像从空域转换到频域,并在频域内实现对图像内特定对象的处理,然后再对经过处理的频域图像进行逆傅里叶变换得到空域图像。

2. Numpy 实现傅里叶和逆傅里叶变换

2.1 Numpy 实现傅里叶变换

Numpy 模块中的 fft2( ) 函数可以实现图像的傅里叶变换。

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(频谱值))

用 Numpy 实现傅里叶变换,观察得到的频谱图像。

import cv2 
import numpy as np 
import matplotlib.pyplot as plt

img = cv2.imread('./img/hand1.png',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('original') 
plt.axis('off') 
plt.subplot(122) 
plt.imshow(magnitude_spectrum, cmap = 'gray') 
plt.title('result') 
plt.axis('off') 
plt.show()

2.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] 灰度空间内,使用的公式为:

iimg = np.abs(逆傅里叶变换结果)

在 Numpy 内实现傅里叶变换、逆傅里叶变换,观察逆傅里叶变换的结果图像。

import cv2 
import numpy as np 
import matplotlib.pyplot as plt

img = cv2.imread('./img/hand1.png',0) 
f = np.fft.fft2(img) 
fshift = np.fft.fftshift(f)

ishift = np.fft.ifftshift(fshift) 
iimg = np.fft.ifft2(ishift) 

iimg = np.abs(iimg)  

plt.subplot(121), plt.imshow(img, cmap = 'gray') 
plt.title('original'), plt.axis('off') 
plt.subplot(122), plt.imshow(iimg, cmap = 'gray') 
plt.title('iimg'), plt.axis('off') 
plt.show()

2.3 高通滤波示例

一副图像内,同时存在着高频信号和低频信号。

低频信号对应图像内变换缓慢的灰度分量。例如,在一副大草原的图像中,低频信号对应着颜色趋于一致的广袤草原。高频信号对应图像内变化越来越快的灰度分量,是由灰度的尖锐过渡造成的。如果在上面的大草原图像中还有一头狮子,那么高频信号就对应着狮子的边缘等信息。

滤波器能够允许一定频率的分量通过或者拒绝其通过,按照其作用方式可以划分为低通滤波器高通滤波器

允许低频信号通过的滤波器称为低通滤波器。低通滤波器使高频信号衰减而对低频信号放行,会使图像变模糊。允许高频信号通过的滤波器成为高通滤波器。高通滤波器使低频信号衰减而让高频信号通过,将增强图像中尖锐的细节,但是会导致图像的对比度降低。

傅里叶变换可以将图像的高频信号和低频信号分离。通过对图像的频域处理,可以实现图像增强、图像去噪、边缘检测、特征提取、压缩和加密等操作。

在Numpy内对图像进行傅里叶变换,得到其频域图像。然后,在频域内将低频分量的值处理为0,实现高通滤波。最后,对图像进行逆傅里叶变换,得到恢复的原始图像。

import cv2 
import numpy as np 
import matplotlib.pyplot as plt 

img = cv2.imread('./img/hand1.png',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] = 0 
ishift = np.fft.ifftshift(fshift) 

iimg = np.fft.ifft2(ishift) 
iimg = np.abs(iimg) 

plt.subplot(121), plt.imshow(img, cmap = 'gray') 
plt.title('original'), plt.axis('off') 
plt.subplot(122), plt.imshow(iimg, cmap = 'gray') 
plt.title('iimg'), plt.axis('off') 
plt.show()

3. OpenCV 实现傅里叶变换和逆傅里叶变换及低通滤波示例

3.1 OpenCV 实现傅里叶变换

OpenCV 提供了函数 cv2.dft() cv2.idft() 来实现傅里叶变换和逆傅里叶变换。

函数 cv2.dft()的语法格式为:

返回结果=cv2.dft(原始图像,转换标识)

在使用函数图像时,需要注意参数的使用规范:

对于参数“原始图像”,要首先使用 np.float32()函数将原始图像转换为 np.float32 格式。“转换标识”的值通常为 “ cv2.DFT_COMPLEX_OUTPUT”,用来输出一个复数陈列。

函数 cv2.dft( ) 返回的结果与使用 Numpy 进行傅里叶变换得到的结果是一致的,但是它返回的值是双通道的,第1个通道是结果的实数部分,第2个通道是结果的虚数部分。

经过函数 cv2.dft( ) 的变换后,得到了原始图像的频谱信息。此时,零频率分量并不在中心位置,为了处理方便需要将其移至中心位置,可以用函数 numpy.fft.fftshift( ) 实现。

例如,如下语句将频谱图像 dft 中的零频率分量移到频谱中心,得到了零频率分量位于中心的频谱图像 dftshift。

dftShift = np.fft.fftshift(dft)

经过上述处理后,频谱图像还只是一个由实部和虚部构成的值。要将其显示出来,还要做进一步的处理才行。

函数 cv2.magnitude( ) 可以计算频谱信息的幅度。该函数的语法格式为:

返回值=cv2.magnitude(参数1,参数2)

参数1:浮点型 x 坐标值,也就是实部。

参数2:浮点型 y 坐标值,也就是虚部,它必须和参数 1 具有相同的size。

函数 cv2.magnitude( ) 的返回值是参数1 和参数 2 的平方和的平方根,公式为:

得到频谱信息的幅度后,通常还要对幅度值做进一步的转换,以便将频谱信息以图像的形式展示出来。简单来说,就是需要将幅度值映射到灰度图像的灰度空间 [0,255] 内,使其以灰度图像的i形式显示出来。

这里使用的公式为:

result = 20*np.log(cv2.magnitude(实部,虚部))
import numpy as np 
import cv2 

img = cv2.imread('./img/hand1.png',0) 
dft = cv2.dft(np.float32(img), flags = cv2.DFT_COMPLEX_OUTPUT) 
print(dft) 

dftShift = np.fft.fftshift(dft) 
print(dftShift) 

result = 20*np.log(cv2.magnitude(dftShift[:, :,0], dftShift[:, :,1])) #两个参数,需要拆分通道
print(result)

用 OpenCV 函数对图像进行傅里叶变换,并展示频谱信息。

import numpy as np 
import cv2 
import matplotlib.pyplot as plt

img = cv2.imread('./img/hand1.png',0) 
dft = cv2.dft(np.float32(img), flags = cv2.DFT_COMPLEX_OUTPUT) 
dftShift = np.fft.fftshift(dft) 
result = 20*np.log(cv2.magnitude(dftShift[:, :,0], dftShift[:, :,1])) 
plt.subplot(121), plt.imshow(img, cmap = 'gray') 
plt.title('original'), plt.axis('off') 
plt.subplot(122), plt.imshow(result, cmap = 'gray') 
plt.title('result'), plt.axis('off') 
plt.show() 

3.2 实现逆傅里叶变换

在 OpenCV 中,使用函数 cv2.idft( ) 实现逆傅里叶变换,该函数是傅里叶变换函数 cv2.dft( ) 的逆函数。其语法格式为:

返回结果=cv2.idft(原始数据)

对图像进行傅里叶变换后,通常会将零频率分量移至频谱图像的中心位置。如果使用函数numpy.fft.fftshift() 移动了零频率分量,那么在进行逆傅里叶变换前,要使用函数 numpy.fft.ifftshift()将零频率分量恢复到原来位置。

注意:在进行逆傅里叶变换后,得到的值仍旧是复数,需要使用函数cv2.magnitude()计算其幅度。

用OpenCV函数对图像进行傅里叶变换、逆傅里叶变换,并展示原始图像及经过逆傅里叶变换后得到的图像。

import numpy as np 
import cv2 
import matplotlib.pyplot as plt

img = cv2.imread('./img/hand1.png',0) 
dft = cv2.dft(np.float32(img), flags = cv2.DFT_COMPLEX_OUTPUT) 
dftShift = np.fft.fftshift(dft)

ishift = np.fft.ifftshift(dftShift) 
iImg = cv2.idft(ishift) 
iImg= cv2.magnitude(iImg[:, :,0], iImg[:, :,1]) # 计算幅度
plt.subplot(121), plt.imshow(img, cmap = 'gray') 
plt.title('original'), plt.axis('off') 
plt.subplot(122), plt.imshow(iImg, cmap = 'gray') 
plt.title('inverse'), plt.axis('off') 
plt.show()

3.3 低通滤波示例

在一副图像内,低频信号对应图像内变化缓慢的灰度分量。图像进行低通滤波后会变模糊。

实现的中间步骤:

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,:] = 1

然后,将其与频谱图像进行运算,实现低通滤波。这里采用的运算形式是:

fShift = dftShift*mask

使用函数 cv2.dft()对图像进行傅里叶变换,得到其频谱图像。然后,在频域内将其高频分量的值处理为0,实现低通滤波。最后,对图像进行逆傅里叶变换,得到恢复的原始图像。

import numpy as np 
import cv2 
import matplotlib.pyplot as plt 
img = cv2.imread('./img/hand1.png',0) 
dft = cv2.dft(np.float32(img), flags = cv2.DFT_COMPLEX_OUTPUT) 
dftShift = 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,:] = 1 
fShift = dftShift*mask ishift = np.fft.ifftshift(fShift) 
iImg = cv2.idft(ishift) 
iImg= cv2.magnitude(iImg[:, :,0], iImg[:, :,1])

plt.subplot(121), plt.imshow(img, cmap = 'gray') 
plt.title('original'), plt.axis('off') 
plt.subplot(122), plt.imshow(iImg, cmap = 'gray') 
plt.title('inverse'), plt.axis('off') 
plt.show() 

经过低通滤波后,图像的边缘信息被削弱了。

参考资料:新机器视觉

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

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

相关文章

RNN模型与NLP应用——(7/9)机器翻译与Seq2Seq模型

声明: 本文基于哔站博主【Shusenwang】的视频课程【RNN模型及NLP应用】,结合自身的理解所作,旨在帮助大家了解学习NLP自然语言处理基础知识。配合着视频课程学习效果更佳。 材料来源:【Shusenwang】的视频课程【RNN模型及NLP应用…

使用YoloV5和Mediapipe实现——上课玩手机检测(附完整源码)

目录 效果展示 应用场景举例 1. 课堂或考试监控(看到这个学生党还会爱我吗) 2. 驾驶安全监控(防止开车玩手机) 3. 企业办公管理(防止工作时间玩手机) 4. 监狱、戒毒所、特殊场所安保 5. 家长监管&am…

XT-912在热交换站的应用

热网监控需求 随着国民经济的不断进步和人民生活水平日益提高,社会对环境的要求越来越高。近年来国家大力提倡城镇集中供热,改变原来各单位、各片区自己供热、单独建立锅炉房给城市带来的污染,由城市外围的一个或者多个热源厂提供热源&#…

语文常识推翻百年“R完备、封闭”论

​语文常识推翻百年“R完备、封闭”论 黄小宁 李四光:迷信权威等于扼杀智慧。语文常识表明从西方传进来的数学存在重大错误:将无穷多各异数轴误为同一轴。 复平面z各点z的对应点zk的全体是zk平面。z面平移变换为zk(k是非1正实常数&#xf…

基于Docker容器部署DeepSeek-R1-Distill-Qwen-7B

首先打开魔搭社区,然后搜索DeepSeek-R1-Distill-Qwen-7B,进入详情页 官方推荐使用vllm来启动,但是手动搭建vllm环境容易出各种问题,我们这里直接找一个vllm的Docker镜像 一、拉取镜像 docker pull vllm/vllm-openai 如果拉取不…

UART双向通信实现(序列机)

前言 UART(通用异步收发传输器)是一种串行通信协议,用于在电子设备之间进行数据传输。RS232是UART协议的一种常见实现标准,广泛应用于计算机和外围设备之间的通信。它定义了串行数据的传输格式和电气特性,以确…

CentOS 7 全流程部署Magic-PDF数据清洗工具(附GPU加速方案)

CentOS 7 全流程部署Magic-PDF数据清洗工具(附GPU加速方案) 一、环境准备与方案选型 1.1 硬件要求 配置项最低要求推荐配置CPU4核8核内存8GB16GB存储50GBSSD/NVMeGPU可选NVIDIA T4 1.2 系统环境检查 # 查看系统版本 cat /etc/redhat-release# 检查G…

LabVIEW多线程

在 LabVIEW 中,多线程编程是提升程序执行效率的关键手段,尤其是在需要并行处理数据采集、控制执行和用户界面交互的场景下。LabVIEW 本身是基于数据流(Dataflow)的编程语言,天然支持多线程,但要高效利用多线…

ctfshow _萌新 萌新_密码篇

萌新_密码1 先对密文进行 Hex 解码,得到了 S1lkZjBhM2ViZDVjNGRjMTYwLUV7ZmI2M2VlMDI5OGI4ZjRkOH0 再进行 base64 解码,得到了 KYdf0a3ebd5c4dc160-E{fb63ee0298b8f4d8} 再进行栅栏解码,得到了 flag KEY{dffb06a33eeeb0d259c84bd8cf146d08…

蓝桥杯2024省赛PythonB组——日期问题

题目链接: https://www.lanqiao.cn/problems/103/learning/?page1&first_category_id1&name%E6%97%A5%E6%9C%9F%E9%97%AE%E9%A2%98 题目内容: 解题思路 import os import sys# 请在此输入您的代码 from datetime import datetime date_str input().str…

带头结点 的单链表插入方法(头插法与尾插法)

带头结点的单链表插入方法(头插法与尾插法) 在单链表的操作中,插入是最常见的操作之一,本文介绍 带头结点的单链表 如何实现 后插法 和 前插法(包括 插入法 和 后插数据交换法),并提供完整的 C …

Opencv之dilib库:表情识别

一、简介 在计算机视觉领域,表情识别是一个既有趣又具有挑战性的任务。它在人机交互、情感分析、安防监控等众多领域都有着广泛的应用前景。本文将详细介绍如何使用 Python 中的 OpenCV 库和 Dlib 库来实现一个简单的实时表情识别系统。 二、实现原理 表情识别系统…

基于web的生产过程执行管理系统(源码+lw+部署文档+讲解),源码可白嫖!

摘要 随着世界经济信息化、全球化的到来和电子商务的飞速发展,推动了很多行业的改革。若想达到安全,快捷的目的,就需要拥有信息化的组织和管理模式,建立一套合理、畅通、高效的线上管理系统。当前的生产过程执行管理存在管理效率…

C++:继承+菱形虚拟继承的一箭双雕

目录 一、继承概念与定义 1.1、什么是继承? 1.2、继承定义 二、继承关系与访问限定符 2.1、继承方式 三、基类与派生类对象的赋值转换 3.1、向上转型 3.2、对象切片 四、继承中的作用域 4.1、隐藏 五、派生类中的成员函数 5.1、构造与析构 六、继承与友…

网络:华为数通HCIA学习:静态路由基础

文章目录 前言静态路由基础静态路由应用场景 静态路由配置静态路由在串行网络的配置静态路由在以太网中的配置 负载分担配置验证 路由备份(浮动静态路由)配置验证 缺省路由配置验证 总结 华为HCIA 基础实验-静态路由 & eNSP静态路由 基础…

CFResNet鸟类识别:原网络基础上改进算法

​本文为为🔗365天深度学习训练营内部文章 原作者:K同学啊​ 先放一张ResNet50模型的鸟类识别结果图 一 ResNetSE-NetBN import matplotlib.pyplot as plt import tensorflow as tf import warnings as w w.filterwarnings(ignore) # 支持中文 plt.rcP…

Ubuntu 20.04 出现问号图标且无法联网 修复

在 Ubuntu 中遇到网络连接问题(如出现问号图标且无法联网),可以通过以下命令尝试重启网络服务: 1. 推荐先修改DNS 编辑 -> 虚拟机网络编辑器-> VMnet8 ->NAT 设置 -> DNS 设置 -> 设置DNS 服务器 DNS填什么 取决…

基于Contiue来阅读open-r1中的GRPO训练代码

原创 快乐王子HP 快乐王子AI说 2025年04月03日 23:54 广东 前面安装了vscode[1]同时也安装了Coninue的相关插件[2],现在想用它们来阅读一下open-r1项目的代码[3]。 首先,从启动训练开始(以GRPO为例子) 第一步,使用TRL的vLLM后端…

51c嵌入式~单片机~合集7~※

我自己的原文哦~ https://blog.51cto.com/whaosoft/13692314 一、芯片工作的心脏--晶振 在振荡器中采用一个特殊的元件——石英晶体,它可以产生频率高度稳定的交流信号,这种采用石英晶体的振荡器称为晶体振荡器,简称晶振。 制作方法 …

英菲克(INPHIC)A9无线蓝牙鼠标 链接电脑的方式

英菲克(INPHIC)A9鼠标链接至电脑时,要长按住“模式切换MODE”按钮5秒左右的时间,此时模式指示灯变成蓝色,并且闪烁。 这时使用电脑的蓝牙设置中,“添加设备”,会出现BT4.0 Mouse提示&#xff0…