visual Studio MFC 平台实现图片的傅里叶变换

图片的傅里叶变换

本文主要讲解傅里叶变换的基本数学概念与物理概念,并本文使用visual Studio MFC 平台实现对傅里叶变换在图片上进行了应用。

一、傅里叶变换的原理

在这里推荐一篇讲得非常形象的文章通俗讲解:图像傅里叶变换

1.1 傅里叶变换原理的说明

傅里叶变换是一种数学变换,它将一个函数(可以是时域中的信号空域中的图像)转换为频域中的表示,从而揭示了信号或图像中存在的不同频率成分。在图像处理中,我们通常使用二维傅里叶变换来处理二维图像。

对于一幅图像而言,傅里叶变换将图像从空域(像素点的位置)转换到频域(不同频率的成分)频域中的信息描述了图像中不同空间频率的变化。这对于分析图像中的纹理、边缘以及其他特征非常有用。

傅里叶变换的结果可以分解为振幅谱和相位谱。振幅谱表示了图像中不同频率成分的强度,而相位谱表示了这些频率成分的相位信息

在图像处理中,傅里叶变换常常用于频域滤波、图像增强、压缩等应用。傅里叶变换的逆变换可以将频域表示转换回空域,因此我们可以在频域中进行操作后再通过逆变换得到处理后的图像。

从纯粹的数学意义上看,傅里叶变换是将一个图像函数转换为一系列周期函数来处理的;
物理效果看,傅里叶变换是将图像从空间域转换到频率域,其逆变换是将图像从频率域转换到空间域。即傅里叶变换的物理意义是将图像的灰度分布函数变换为图像的频率分布函数,傅里叶逆变换是将图像的频率分布函数变换为灰度分布函数。

实际上对图像进行二维傅里叶变换得到频谱图就是图像梯度的分布图,傅里叶频谱图上看到的明暗不一的亮点实际上图像上某一点 与邻域点差异的强弱,即梯度的大小,即该点的频率大小
如果频谱图中暗的点数更多,则实际图像是比较柔和的;反之,如果频谱图中亮的点数多,则实际图像是比较尖锐的,边界分明且边界两边像素差异较大

以下是对一些关键概念的简要总结:

  1. 数学意义: 傅里叶变换是一种将一个信号(包括图像)从时间域(或空间域)转换为频率域的方法。它将一个信号分解为一组正弦和余弦函数(频率分量),以揭示信号中的不同频率成分。

  2. 物理效果: 傅里叶变换的物理效果是将图像从空间域(表示像素在图像中的位置)转换为频率域(表示图像中不同频率的成分)。逆傅里叶变换则将频率域的信息重新转换为空间域,从而实现对原始图像的还原。

  3. 频谱图: 傅里叶变换的结果通常以频谱图的形式呈现,其中显示了图像在频率域中的分布。频谱图中的亮度表示不同频率成分的强度,而频谱图上的点对应于不同的频率。

  4. 梯度分布: 在频谱图中,明暗不一的亮点对应于图像中不同频率的变化。较暗的区域表示较低频率的成分,而较亮的区域表示较高频率的成分。这与图像的梯度(差异)有关,因为梯度较大的区域通常对应于频谱图中较亮的部分。

总体而言,傅里叶变换为我们提供了一种在频率域中理解图像特征的工具,有助于分析图像的纹理、边缘和其他结构。这对于许多图像处理任务,如滤波、增强和压缩,都是非常有用的。

1.2 数学表达

1.2.1 傅里叶变换的数学表示

对于一个连续函数 f ( t ) f(t) f(t)其傅里叶变换 F ( w ) F(w) F(w) 定义为:

F ( w ) = ∫ − ∞ ∞ f ( t ) ⋅ e − i w t d t F(w) = \int_{-\infty}^{\infty} f(t) \cdot e^{-iwt} \,dt F(w)=f(t)eiwtdt

其中, F ( w ) F(w) F(w)表示频率为 w w w的成分的复幅度, e − i w t e^{-iwt} eiwt 是复指数函数, t t t 是时间。

1.2.2 傅里叶逆变换的数学表示

傅里叶变换的逆过程是傅里叶逆变换,它将频率域表示还原为时间或空间域表示。对于一个频谱 F ( w ) F(w) F(w),其逆变换 f ( t ) f(t) f(t) 定义为:

f ( t ) = 1 2 π ∫ − ∞ ∞ F ( w ) ⋅ e i w t d w f(t) = \frac{1}{2\pi} \int_{-\infty}^{\infty} F(w) \cdot e^{iwt} \,dw f(t)=2π1F(w)eiwtdw

1.2.3 离散傅里叶变换(DFT)的数学表示

在数字信号处理中,通常使用离散傅里叶变换。对于一个离散序列 x [ n ] x[n] x[n],其离散傅里叶变换 X [ k ] X[k] X[k] 定义为:

X [ k ] = ∑ n = 0 N − 1 x [ n ] ⋅ e − i 2 π N k n X[k] = \sum_{n=0}^{N-1} x[n] \cdot e^{-i\frac{2\pi}{N}kn} X[k]=n=0N1x[n]eiN2πkn

其中, N N N 是序列的长度, X [ k ] X[k] X[k] 表示频率为 k N \frac{k}{N} Nk 的成分的复幅度。

1.3 傅里叶变换的应用

  1. 频域分析: 傅里叶变换允许我们在频域中分析信号,找到不同频率的成分。

  2. 滤波: 在频域中进行滤波操作,去除或增强特定频率的成分。

  3. 信号压缩: 将信号在频域中表示通常可以更紧凑地表示信号。

  4. 图像处理: 在图像处理中,傅里叶变换常用于分析和处理图像的频率成分。

总的来说,傅里叶变换是一种非常强大的数学工具,广泛应用于信号处理、通信、图像处理等领域。

二、 傅里叶变换与快速傅里叶变换的区别

傅里叶变换(Fourier Transform)和快速傅里叶变换(Fast Fourier Transform, FFT)是两种相关但不同的数学算法,用于在信号处理、图像处理等领域分析信号的频域特征。

  1. 傅里叶变换:

    • 定义: 傅里叶变换是一种将信号从时域(时间域)转换到频域(频率域)的数学变换。对于连续信号,傅里叶变换的定义是积分形式;对于离散信号,傅里叶变换的定义是离散形式。
    • 计算复杂度: 对于 N 个数据点的信号,傅里叶变换的计算复杂度是 O(N^2),其中 N 是数据点的数量。
  2. 快速傅里叶变换(FFT):

    • 定义: FFT 是一种优化算法,用于高效地计算傅里叶变换。FFT 算法可以在 O(N log N) 的时间内完成信号的傅里叶变换,相较于传统的傅里叶变换算法,FFT 算法速度更快
    • 计算复杂度: FFT 的计算复杂度相对较低,使得在计算机上更容易处理大规模的数据。

总结区别:

  • FFT 是一种特定的傅里叶变换算法,它是为了提高傅里叶变换的计算速度而设计的。
  • 傅里叶变换是一般性的概念,可以用于描述信号在频域中的表示;FFT 是实现傅里叶变换的具体算法。
  • FFT 的主要优势在于其计算速度,尤其是对于大规模数据的情况,它比传统傅里叶变换更为高效。

在实际应用中,由于 FFT 算法的高效性,它通常是首选的频域分析工具。很多信号处理库和软件包中都包含了 FFT 的实现,使得工程师和科学家能够更方便地进行频域分析。

三、 绘制傅里叶变换的频谱

因为要使用opencv的库所以visual Studio没有配置opencv的,需要先配置一下,可以参考博客Visual Studio 配置opencv环境

#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/core.hpp>using namespace cv;
// 中心化频谱函数
void fftShift(Mat& mag)
{int cx = mag.cols / 2;int cy = mag.rows / 2;Mat q1(mag, cv::Rect(0, 0, cx, cy));Mat q2(mag, cv::Rect(cx, 0, cx, cy));Mat q3(mag, cv::Rect(0, cy, cx, cy));Mat q4(mag, cv::Rect(cx, cy, cx, cy));Mat tmp;q1.copyTo(tmp);q4.copyTo(q1);tmp.copyTo(q4);q2.copyTo(tmp);q3.copyTo(q2);tmp.copyTo(q3);
}
//FFT傅里叶变换
void CMFCApplication1View::OnFft()
{// TODO: 在此添加命令处理程序代码if (gray_data != nullptr) {// 将灰度数据转换为OpenCV的Mat对象,图像尺寸为bmpHeight x bmpWidth,数据类型为8位无符号整数Mat image(bmpHeight, bmpWidth, CV_8U, gray_data);// 执行傅里叶变换Mat padded; // 扩展输入图像到最佳尺寸int m = getOptimalDFTSize(image.rows);int n = getOptimalDFTSize(image.cols);copyMakeBorder(image, padded, 0, m - image.rows, 0, n - image.cols, BORDER_CONSTANT, Scalar::all(0));//在图像周围填充零// 为频域图像分配内存Mat planes[] = { Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F) };//存储频域表示的复杂图像Mat complexImage;merge(planes, 2, complexImage);// 执行傅里叶变换,从空间域转换到频域。dft(complexImage, complexImage);// 分离实部和虚部,存储在planes数组中split(complexImage, planes);// 计算幅度谱,将结果存储在planes数组的第一个平面magnitude(planes[0], planes[1], planes[0]);// 变换到对数尺度     //对幅度谱进行对数变换以增强可视化效果planes[0] += Scalar::all(1);log(planes[0], planes[0]);// 归一化到 [0, 1]normalize(planes[0], planes[0], 0, 1, NORM_MINMAX);// 显示未中心化的频谱图imshow("Spectrum (Uncentered)", planes[0]);// 中心化频谱fftShift(planes[0]);// 显示中心化后的频谱图imshow("Spectrum (Centered)", planes[0]);waitKey(0);//等待按键操作,然后关闭图像窗口}else {// 处理图像未加载的情况AfxMessageBox(_T("未加载灰度图片"));}
}

说明:dft(complexImage, complexImage); 这一行执行的傅里叶变换,调用了OpenCV中的dft函数,对输入的complexImage执行傅里叶变换。在这个上下文中,dft是一个通用的傅里叶变换函数,而非专门的FFT实现。由于OpenCV中的dft函数使用了优化算法,它实际上在内部采用了FFT来提高计算效率,但在代码层面上,我们通常将其称为傅里叶变换。

左:灰度图 中:进行中心化后的频谱图 右:未中心化的频谱图
在这里插入图片描述

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

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

相关文章

idea__SpringBoot微服务11——整合Druid数据源(新依赖)(新注解)

整合JDBC 一、导入依赖二、配置Druid————————创作不易&#xff0c;如觉不错&#xff0c;随手点赞&#xff0c;关注&#xff0c;收藏(*&#xffe3;︶&#xffe3;)&#xff0c;谢谢~~ 接着 第10的 新注解&#xff1a; ConfigurationProperties ConfigurationPropert…

【人工智能】实验四:遗传算法求函数最大值实验与基础知识

实验四&#xff1a;遗传算法求函数最大值实验 实验目的 熟悉和掌握遗传算法的原理、流程和编码策略&#xff0c;并利用遗传算法求解函数优化问题&#xff0c;理解求解流程并测试主要参数对结果的影响。 实验内容 采用遗传算法求解函数最大值。 实验要求 1. 用遗传算法求解…

3. cgal 示例 GIS (Geographic Information System)

GIS (Geographic Information System) 地理信息系统 原文地址: https://doc.cgal.org/latest/Manual/tuto_gis.html GIS 应用中使用的许多传感器&#xff08;例如激光雷达&#xff09;都会生成密集的点云。此类应用程序通常利用更先进的数据结构&#xff1a;例如&#xff0c;不…

053:vue工具--- 英文字母大小写在线转换

第047个 查看专栏目录: VUE ------ element UI 专栏目标 在vue和element UI联合技术栈的操控下&#xff0c;本专栏提供行之有效的源代码示例和信息点介绍&#xff0c;做到灵活运用。 &#xff08;1&#xff09;提供vue2的一些基本操作&#xff1a;安装、引用&#xff0c;模板使…

QEMU源码全解析 —— virtio(13)

接前一篇文章&#xff1a; 通过前文书&#xff08;从QEMU源码全解析 —— virtio&#xff08;9&#xff09;开始&#xff09;对整个流程以及各个相关函数的解析&#xff0c;可以看到从virtio PCI代理设备的具现化到virtio设备的具现化过程。但前述分析还遗漏了一部分&#xff0…

LeetCode(69)对称二叉树【二叉树】【简单】

目录 1.题目2.答案3.提交结果截图 链接&#xff1a; 对称二叉树 1.题目 给你一个二叉树的根节点 root &#xff0c; 检查它是否轴对称。 示例 1&#xff1a; 输入&#xff1a;root [1,2,2,3,4,4,3] 输出&#xff1a;true示例 2&#xff1a; 输入&#xff1a;root [1,2,2,nu…

朱卫明:从韶关走向世界的创作型歌手

朱卫明&#xff0c;艺名Aming&#xff0c;是一位来自广东韶关的杰出唱作音乐人。他以其独特的创作才华和深情的嗓音&#xff0c;赢得了众多歌迷的喜爱。作为一名创作型歌手&#xff0c;朱卫明用音乐传递情感&#xff0c;用歌声打动人心。 一、早年经历与音乐启蒙 朱卫明出生于…

Python开发工具PyCharm v2023.3全新发布——全面推出AI Assistant工具

JetBrains PyCharm是一种Python IDE&#xff0c;其带有一整套可以帮助用户在使用Python语言开发时提高其效率的工具。此外&#xff0c;该IDE提供了一些高级功能&#xff0c;以用于Django框架下的专业Web开发。 PyCharm v2023.3正式版下载 在 PyCharm 2023.3 中&#xff0c;每…

Linux Shell——输入输出重定向

输入输出重定向 1. 重定向输入2. 重定向输出 总结 最近学习了shell语法&#xff0c;总结一下关于输入输出重定向的知识。 一般情况下&#xff0c;linux每次执行命令其实都会打开三个文件&#xff0c;分别是&#xff1a; 标准输入stdin 文件描述符为0 标准输出stdout 文件描述符…

Text2SQL学习整理(一) 综述

数据库由一张或多张表格构成&#xff0c;表格之间的关系通过共同的列&#xff08;外键&#xff09;关联&#xff0c;人们使用数据库来方便的记录和存储信息。SQL是广泛应用的关系型数据库查询语言&#xff0c;但是对于普通用户而言&#xff0c;编写SQL语句有一定的难度。 Text…

Xpath注入

这里学习一下xpath注入 xpath其实是前端匹配树的内容 爬虫用的挺多的 XPATH注入学习 - 先知社区 查询简单xpath注入 index.php <?php if(file_exists(t3stt3st.xml)) { $xml simplexml_load_file(t3stt3st.xml); $user$_GET[user]; $query"user/username[name&q…

方案分享:如何做好云中的DDoS防御?

所有企业都会有遭受DDoS攻击的风险。由于目前DDoS即服务&#xff08;DaaS&#xff09;的售价低廉&#xff0c;因此对于恶意攻击者来说&#xff0c;发起攻击比以往任何时候都更加容易&#xff0c;技术门槛也更低。分析公司IDC一项关于DDoS防御的调查显示&#xff0c;超过50%的IT…

数据结构-06-散列/哈希表

1-什么是散列表 散列表用的是数组支持按照下标随机访问数据的特性&#xff0c;所以散列表其实就是数组的一种扩展&#xff0c;由数组演化而来。可以说&#xff0c;如果没有数组&#xff0c;就没有散列表。散列表中的元素在数组的位置(index)是通过散列函数得到的。 2-散…

【MyBatis-Plus】MyBatis进阶使用

目录 一、MyBatis-Plus简介 1.1 介绍 1.2 优点 1.3 结构 二、MyBatis-Plus基本使用 2.1 配置 2.2 代码生成 2.3 CRUD接口测试 三、MyBatis-Plus策略详解 3.1 主键生成策略 3.2 雪花ID生成器 3.3 字段自动填充策略 3.4 逻辑删除 四、MyBatis-Plus插件使用 4.1 乐…

从零开始:VuePress2 + GitHub Pages 搭建你的第一个免费博客网站

可能你也想拥有一个属于自己的博客网站&#xff0c;但是自己搭个博客网站不知道从何下手&#xff0c;而且还需要租个云服务器&#xff0c;虽然一个月只需几十块钱&#xff0c;但是我们的博客网站是要长期维护的&#xff0c;日积月累也要不少钱呢。 现在我就教你用 VuePress2 …

JVM-1-运行时数据区

程序计数器&#xff08;Program Counter Register&#xff09; 是一块较小的内存空间&#xff0c;它可以看作是当前线程所执行的字节码的行号指示器。在Java虚拟机的概念模型里[1]&#xff0c;字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令&…

【ICCV 2022】Masked Autoencoders Are Scalable Vision Learners

何凯明一作文章&#xff1a;https://arxiv.org/abs/2111.06377 本文的出发点&#xff1a;是BERT的掩码自编码机制&#xff1a;移除一部分数据并对移除的内容进行学习。mask自编码源于CV但盛于NLP&#xff0c;恺明对此提出了疑问&#xff1a;是什么导致了掩码自编码在视觉与语言…

Apache OfBiz 反序列化命令执行漏洞(CVE-2023-49070)

项目介绍 Apache OFBiz是一个非常著名的电子商务平台&#xff0c;是一个非常著名的开源项目&#xff0c;提供了创建基于最新J2EE/XML规范和技术标准&#xff0c;构建大中型企业级、跨平台、跨数据库、跨应用服务器的多层、分布式电子商务类WEB应用系统的框架。OFBiz最主要的特…

自定义注解

自定义注解 自定义注解 以实战案例为驱动,快速掌握此怎么自己自定义注解,也好出去自己吹牛逼~哈哈哈 假设我们打车,需要检验验证码,我们需要一个注解字来进行核验,我们怎么操作呢? 大纲总览 ​​ 1.定义注解 可以自己创一个包单门存放自己的注解: 如​constraints​ 包 然后…

Linux高级系统编程-MySQL数据库基本使用语法

DDL:数据定义语言 作用 : 用于完成对数据库对象&#xff08;数据库、数据表、视图、索引等&#xff09;的创建、删除、修改 数据库操作 查询数据库 - > 显示当前 mysql 中的数据库列表 > show databases; - > 显示指定名称的数据的创建的 SQL 指令 > show c…