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

news2024/12/23 0:27:27

图片的傅里叶变换

本文主要讲解傅里叶变换的基本数学概念与物理概念,并本文使用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.coloradmin.cn/o/1308529.html

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

相关文章

kernel(三):kernel移植

本文主要探讨210官方kernel移植。 配置文件选择 选择配置文件smdkv210_android_defconfig(arch/arm/configs) 修改主Makefile 配置cpu架构和交叉编译工具链 vim MakefileARCH ? armCROSS_COMPILE ? /root/arm-2009q3/bin/arm-none-linux-gnueabi- 初步编译烧…

HarmonyOS应用程序框架

应用程序入口—UIAbility的使用 UIAbility概述 UIAbility是一种包含用户界面的应用组件&#xff0c;主要用于和用户进行交互。UIAbility也是系统调度的单元&#xff0c;为应用提供窗口在其中绘制界面。 每一个UIAbility实例&#xff0c;都对应于一个最近任务列表中的任务。 …

【论文阅读】MAKE-A-VIDEO: TEXT-TO-VIDEO GENERATION WITHOUT TEXT-VIDEO DATA

Make-a-video:没有文本-视频数据的文本-视频生成。 paper&#xff1a; code&#xff1a; ABSTRACT 优点: (1)加速了T2V模型的训练(不需要从头开始学习视觉和多模态表示)&#xff0c; (2)不需要配对的文本-视频数据&#xff0c; (3)生成的视频继承了当今图像生成模型的庞大…

HBase 高可用集群详细图文安装部署

目录 一、HBase 安装部署 1.1 Zookeeper 正常部署 1.2 Hadoop 正常部署 1.3 HBase 安装 1.4 HBase 的配置文件 1.4.1 hbase-env.sh 1.4.2 hbase-site.xml 1.4.3 regionservers 1.4.4 创建目录 1.5 HBase 远程发送到其他节点 1.6 HBase 服务的启动 1.6.1 单点…

用友时空 KSOA 多处SQL注入漏洞复现

0x01 产品简介 用友时空 KSOA 是建立在 SOA 理念指导下研发的新一代产品,是根据流通企业前沿的 IT 需求推出的统一的IT基础架构,它可以让流通企业各个时期建立的 IT 系统之间彼此轻松对话。 0x02 漏洞概述 用友时空 KSOA 系统 PayBill、QueryService、linkadd.jsp等接口处…

数字化赋能实体经济,凌雄科技发挥DaaS模式提质增效价值

11月中旬&#xff0c;市场监管总局发布了2023年前三季度经营主体数据。其中&#xff0c;前三季度全国新设民营企业总计706.5万户&#xff0c;截至9月底&#xff0c;全国登记在册的民营企业数量超过5200万户&#xff0c;在企业总量中占比高达92.3%。如何帮助民营企业实现高质量发…

中海达亮相能源北斗与时空智能创新技术应用大会

12月7日-8日&#xff0c;2023年能源北斗与时空智能创新技术应用大会暨鹭岛论坛在厦门举办。本次活动以“能源北斗时空智能”为主题&#xff0c;由中关村智能电力产业技术联盟、中国能源研究会、中国卫星导航定位协会、中国电力科学研究院有限公司、国网信息通信产业集团有限公司…

探索 Vim:一个强大的文本编辑器

引言&#xff1a; Vim&#xff08;Vi IMproved&#xff09;是一款备受推崇的文本编辑器&#xff0c;拥有强大的功能和高度可定制性&#xff0c;提供丰富的编辑和编程体验。本文将探讨 Vim 的基本概念、使用技巧以及为用户带来的独特优势。 简介和发展 1. Vim 的简介和历史 V…

0基础学习VR全景平台篇第127篇:什么是VR全景/720全景漫游?

“全景”作为一种表现宽阔视野的手法&#xff0c;在很久之前就得到了普遍的认同。北宋年间&#xff0c;由张择端绘制的《清明上河图》就是一幅著名的全景画。摄影术出现后&#xff0c;全景摄影也随之而生。 到今天&#xff0c;全景拍摄不再被专业摄影师所独享&#xff0c;广大…

uniapp 之 图片 视频 文件上传

<view class"" style"padding: 24rpx 0"><text>相关资料 <text class"fs-26 color-666">&#xff08;图片、视频、文档不超过9个&#xff09;</text> </text><view class"flex align-center" style&…

CNN 卷积神经网络之 DenseNet 网络的分类统一项目(包含自定义数据集的获取)

1. DenseNet 网络介绍 本章实现的项目是DenseNet 网络对花数据集的五分类&#xff0c;下载链接&#xff1a; 基于迁移学习的 DenseNet 图像分类项目 DenseNet 网络是在 ResNet 网络上的改进&#xff0c;大概的网络结构如下&#xff1a; 1.1 卷积的简单介绍 图像识别任务主要…

通过 RIOT 将 AWS ElastiCache 迁移到阿里云 Tair

本文通过示例介绍了 RIOT 如何轻松地将数据从 AWS ElastiCache 迁移到云原生内存数据库&#xff08;如 Tair 和云数据库 Redis 版&#xff09;。 1. 准备资源迁移 1.1. 源代码 AWS ElastiCache cache.r6g.xlarge。它有三个数据分片&#xff0c;与 Redis 6.2 兼容。 AWS EC2 t2.…

共建开源新里程:北京航空航天大学OpenHarmony技术俱乐部正式揭牌成立

12月11日,由OpenAtom OpenHarmony(以下简称“OpenHarmony”)项目群技术指导委员会(以下简称“TSC”)和北京航空航天大学共同举办的“OpenHarmony软件工程研讨会暨北京航空航天大学OpenHarmony技术俱乐部成立仪式”在京圆满落幕。 现场大合影 活动当天,多位重量级嘉宾出席了此次…

2023.12.14 hive sql的聚合增强函数 grouping set

目录 1.建库建表 2.需求 3.使用union all来完成需求 4.聚合函数增强 grouping set 5.聚合增强函数cube ,rollup 6.rollup翻滚 7.聚合函数增强 -- grouping判断 1.建库建表 -- 建库 create database if not exists test; use test; -- 建表 create table test.t_cookie(month …

理解 Proxy 和 Object.defineProperty:提升你的 JavaScript 技能(下)

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

华为配置基本QinQ示例

组网需求 如图1所示&#xff0c;网络中有两个企业&#xff0c;企业1有两个分支&#xff0c;企业2有两个分支。这两个企业的各办公地的企业网都分别和运营商网络中的SwitchA和SwitchB相连&#xff0c;且公网中存在其它厂商设备&#xff0c;其外层VLAN Tag的TPID值为0x9100。 现…

ffmpeg编解码——数据包(packet)概念(如何正确处理数据包中的显示时间戳pts与解码时间戳dts关系?)

文章目录 FFmpeg编解码——数据包&#xff08;Packet&#xff09;概念1. 数据包&#xff08;Packet&#xff09;简介2. 数据包&#xff08;Packet&#xff09;在FFmpeg中的应用2.1 从媒体文件读取数据包2.2 向媒体文件写入数据包 3. 数据包&#xff08;Packet&#xff09;相关问…

智能优化算法应用:基于鸽群算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于鸽群算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于鸽群算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.鸽群算法4.实验参数设定5.算法结果6.参考文献7.MA…

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

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

C语言 联合体验证 主机字节序 +枚举

联合体应用&#xff1a;验证当前主机的大小端&#xff08;字节序&#xff09; //验证当前主机的大小端 #include <stdio.h>union MyData {unsigned int data;struct{unsigned char byte0;unsigned char byte1;unsigned char byte2;unsigned char byte3;}byte; };int main…