【数字图像处理笔记】Matlab实现离散傅立叶变换 (二)

请添加图片描述

  • 💌 所属专栏:【数字图像处理笔记】

  • 😀 作  者:我是夜阑的狗🐶

  • 🚀 个人简介:一个正在努力学技术的CV工程师,专注基础和实战分享 ,欢迎咨询!

  • 💖 欢迎大家:这里是CSDN,我总结知识的地方,喜欢的话请三连,有问题请私信 😘 😘 😘

您的点赞、关注、收藏、评论,是对我最大的激励和支持!!!🤩 🤩 🤩

请添加图片描述

文章目录

  • 前言
  • 一、原理
  • 二、实现过程
      • 1、离散傅立叶变换(直接调用Matlab内置函数):
      • 2、离散傅立叶变换(自己编写):
      • 3、离散傅里叶逆变换(自己编写):
  • 总结


前言

  大家好,又见面了,我是夜阑的狗🐶,本文是专栏【数字图像处理笔记】专栏的第2篇文章;
  这是今天学习到数字图像处理笔记 – Matlab实现离散傅立叶变换 💖💖💖,开启新的征程,记录最美好的时刻🎉,每天进步一点点。
  专栏地址:【数字图像处理笔记】 , 此专栏是我是夜阑的狗对数字图像处理学习过程的总结,希望能够加深自己的印象,以及帮助到其他的小伙伴😉😉。
  如果文章有什么需要改进的地方还请大佬不吝赐教👏👏。

一、原理

  要在数字图像处理中应用傅立叶变换, 还需要解决两个问题:

  • 问题一:在数学中进行傅立叶变换的f(x)为连续(模拟)信号, 而计算机处理的是数字信号(图像数据);
  • 问题二:数学上采用无穷大概念,而计算机只能进行有限次计算。

  通常, 将受这种限制的傅立叶变换称为离散傅立叶变换(Discrete Fourier Transform,DFT)。离散傅立叶变换的定义如下。

  • 离散傅立叶正变换:

F ( u ) = ∑ x = 0 N − 1 f ( x ) e − j 2 π u x N F(u) = \sum_{ \begin{subarray}{l} x=0 \end{subarray}}^{N-1}f(x)e^{-j{\frac {2 \pi ux} N}} F(u)=x=0N1f(x)ejN2πux
  其中 u = 0 , 1 , 2 , Λ , N − 1 u = 0,1,2,\Lambda, N-1 u=0,1,2,Λ,N1

  • 离散傅立叶逆变换:

f ( u ) = 1 N ∑ u = 0 N − 1 F ( x ) e − j 2 π u x N f(u) = {\frac 1 N}\sum_{ \begin{subarray}{l} u=0 \end{subarray}}^{N-1}F(x)e^{-j{\frac {2 \pi ux} N}} f(u)=N1u=0N1F(x)ejN2πux
  其中 x = 0 , 1 , 2 , Λ , N − 1 x = 0,1,2,\Lambda, N-1 x=0,1,2,Λ,N1

二、实现过程

1、离散傅立叶变换(直接调用Matlab内置函数):

  代码:

I=imread('cameraman.tif');
% I=rgb2gray(I);	%将图像转换为灰度图
I=im2double(I);     %将图像的数据格式转换为double型的 
F=fft2(I);               %傅立叶变换
%不进行象限转换
F1=abs(F);             %傅里叶变换的模
T1=log(F1+1);		 %数据范围压缩
%进行象限转换
F=fftshift(F);          %对傅里叶变换后的图像进行象限转换
F=abs(F);               %傅里叶变换的模
T=log(F+1);           %数据范围压缩
figure;                    %显示
subplot(2,2,1);imshow(I);
subplot(2,2,2);imshow(I);
subplot(2,2,3);imshow(T,[]); 
subplot(2,2,4);imshow(T1,[]);

  运行结果如下图所示:

在这里插入图片描述

  从图中可以看出,原图像经过快速傅立叶变换 fft 后可以得到频谱图;以及通过 ffshift 函数将零频点移到频谱的中间,可以更直观观察傅立叶变换,傅立叶变换能使从空间域与频率域两个不同角度来分析图像问题。还可以通过 ifftshift 函数从频率域反映射到空间域,傅里叶逆变换基本还原图像。
  在进行傅立叶变换的具体实现中,要注意对fft变换后的频域矩阵数值比较大,一般采用log(abs[F]+1) 来对缩放频域,保证映射都在正数范围内,abs 函数可以求出复数矩阵的模缩放处理后进行显示。
  频谱图表示信号变化的快慢剧烈程度,通过分析不同图像和频谱图的关系时发现,高频信号对应图像的边缘细节,低频信号对应图像的大致概貌和轮廓。因此,对于细节边缘清晰或者噪声较多的图像,经过傅立叶变换后,靠外边的高频信号更多;而对于平滑、具备大体轮廓的图像,经过傅立叶变换后,靠中间的低频信号更多。
  所以,频谱图中的四个角和X,Y轴的尽头都是高频。可以以发现频谱图中的较亮白线应该是对应相机三脚架的边缘以及衣服的边缘。

2、离散傅立叶变换(自己编写):

  代码:

clc; clear;

data = imread('cameraman.tif');  % 数据——最好比卷积核的尺寸大
data = im2double(data); 
% data = rgb2gray(data);     % rgb转为灰度图像
subplot(1,3,1);
imshow(data);
title('原始图像')

zidai = fft2(data);   % matlab自带函数,来用对比
T1= abs(zidai);    %傅里叶变换的模
T1= fftshift(T1);   %对傅里叶变换后的图像进行象限转换
T1 = log(T1+1);	  %数据范围压缩
subplot(1,3,2);
% imshow(real(zidai));  % 一般只要实部
imshow(T1,[]); 
title('fft2');

size_data = size(data);
M = size_data(1);  % 图(原始数据矩阵)的长
N = size_data(2);  % 图(原始数据矩阵)的宽

% 下面是傅里叶正变换必备的一些矩阵:
Wm = exp(-j*2*pi/M);
Wn = exp(-j*2*pi/N); % 不同G中用不同的W
Em = zeros(M);
En = zeros(N);     % E是辅助计算矩阵
Gm = zeros(M)+Wm;
Gn = zeros(N)+Wn;  % G是计算时要用的矩阵
F = zeros(M,N);    % F是转换到频域的结果

% 对Gm的计算: 循环长度为M
fprintf('二维离散傅里叶变换开始:\n');
for row = 0:M-1
    for col = 0:M-1
        Em(row+1,col+1) = row * col;
        Gm(row+1,col+1) = Gm(row+1,col+1)^Em(row+1,col+1);
    end
end
% 对Gn的计算: 循环长度为N
for row = 0:N-1
    for col = 0:N-1
        En(row+1,col+1) = row * col;
        Gn(row+1,col+1) = Gn(row+1,col+1)^En(row+1,col+1);
    end
end

% F = real(Gm*data*Gn);  % F = Gm*f*Gn是计算公式,一般只要实部
F = Gm*data*Gn;
subplot(1,3,3);
T=fftshift(F);   %对傅里叶变换后的图像进行象限转换
T=abs(T);        %傅里叶变换的模
T=log(T+0.7);  %数据范围压缩
% imshow(F);
imshow(T,[]);
title('myfft2');

error = sum(sum((real(F)-real(zidai)).^2));
if error < 10^(-10)
    fprintf('自带与手写结果一致!\n');
else
    fprintf('不一致!\n');
end

  运行结果如下图所示:

在这里插入图片描述

  从图中的对比结果可以看出,通过编程实现傅里叶变换与 Matlab 自带的傅里叶变换函数得到的频谱图基本一致,说明了该程序的正确性。

3、离散傅里叶逆变换(自己编写):

  代码:

% 鉴于正向fft2手写与自带结果一致;
% ifft2的输入就直接用自带的fft2的结果。
clc; clear;

data = imread('cameraman.tif');  % 数据——最好比卷积核的尺寸大
data = im2double(data); 
% data = rgb2gray(data);     % rgb转为灰度图像
subplot(1,3,1);
imshow(data);
title('原始图像')

F = fft2(data);
T1= abs(F);
T1= fftshift(T1);
T1 = log(T1+1);	
subplot(1,3,2);
imshow(T1,[]);
% imshow(real(F));  % 一般画图只要实部, 作为输入时实虚都要!!
title('fft2');

% s = ifft2(F);
% subplot(1,3,3);
% imshow(s);
% return;

size_data = size(F);
M = size_data(1);  % 图(原始数据矩阵)的长
N = size_data(2);  % 图(原始数据矩阵)的宽

% 下面是傅里叶逆变换必备的一些矩阵:
Wm = exp(-j*2*pi/M);
Wn = exp(-j*2*pi/N);  % 不同G中用不同的W
Em = zeros(M);
En = zeros(N);        % E是辅助计算矩阵
Gm = zeros(M)+Wm;
Gn = zeros(N)+Wn;  % G是计算时要用的矩阵
f = zeros(M,N);    % F是转换到频域的结果

% 对Gm的计算: 循环长度为M
fprintf('二维离散反傅里叶变换开始:\n');
for row = 0:M-1
    for col = 0:M-1
        Em(row+1,col+1) = -row * col;
        Gm(row+1,col+1) = Gm(row+1,col+1)^Em(row+1,col+1);
    end
end
Gm = Gm/M;
% 对Gn的计算: 循环长度为N
for row = 0:N-1
    for col = 0:N-1
        En(row+1,col+1) = -row * col;
        Gn(row+1,col+1) = Gn(row+1,col+1)^En(row+1,col+1);
    end
end
Gn = Gn/N;   % 注意:这个/N和上面的/M都是算完G之后才除以的!因为上面计算的时候是幂项变化!

f = real(Gm*F*Gn);  % f = Gm*F*Gn是计算公式,一般只要实部
subplot(1,3,3);
imshow(f);
title('逆变换myidft2');

error = sum(sum((real(f)-real(data)).^2));
if error < 10^(-10)
    fprintf('反变换后与原图一致!\n');
else
    fprintf('不一致!\n');
end

  运行结果如下图所示:

在这里插入图片描述

  从图中的傅里叶逆变换处理结果可以看出,通过编程实现的傅里叶逆变换得到图像与原图基本一致,说明了该程序的正确性。
  通过本次操作基本掌握傅立叶变换的基本原理和实现算法。在实际过程中遇到以下几个问题及解决方法:

  • (1)要傅里叶变换频谱图进行分析,频谱没有中心化。解决方法:调用 fftshift() 函数对频谱图进行中心化。

总结

  感谢观看,如果觉得有帮助,请给文章点个赞吧,让更多的人看到。🌹 🌹 🌹

在这里插入图片描述

  也欢迎你,关注我。👍 👍 👍

  原创不易,还希望各位大佬支持一下,你们的点赞、收藏和留言对我真的很重要!!!💕 💕 💕 最后,本文仍有许多不足之处,欢迎各位认真读完文章的小伙伴们随时私信交流、批评指正!下期再见。🎉

更多专栏订阅:

  • 😀 【LeetCode题解(持续更新中)】
  • 🌼 【鸿蒙系统】
  • 👑 【Python脚本笔记】
  • 🚝 【Java Web项目构建过程】
  • 💛 【微信小程序开发教程】
  • 【JavaScript随手笔记】
  • 🤩 【大数据学习笔记(华为云)】
  • 🦄 【程序错误解决方法(建议收藏)】
  • 🚀 【软件安装教程】



订阅更多,你们将会看到更多的优质内容!!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

自然资源调查监测评价系统:守护绿色地球的先锋

随着人类对自然资源的日益依赖&#xff0c;如何合理、可持续地利用这些资源成为了全球关注的焦点。自然资源调查监测评价系统&#xff0c;作为守护绿色地球的重要工具&#xff0c;正发挥着越来越重要的作用。本文将带您了解这一系统的内涵、功能及其在现代社会中的意义。一、自…

Linux内核驱动开发-字符设备驱动框架

1前置条件 &#xff08;1&#xff09;【linux】内核编译结束 &#xff08;2&#xff09;【linux】目录配置跳转文件&#xff1a;补充&#xff1a;配置的跳转文件只能在【linux】目录下使用&#xff0c;子目录无法使用2驱动框架 2.1编写驱动程序 #include <linux/init.h&g…

Lagent AgentLego 智能体应用搭建——笔记

Lagent & AgentLego 智能体应用搭建——笔记 一、智能体简介1.1、为什么要有智能体1.1.1、幻觉问题1.1.2、时效性1.1.3、可靠性 1.2、智能体的含义1.3、智能体的组成1.3.1、大脑1.3.2、感知1.3.3、动作 1.4、智能体范式1.4.1、AutoGPT1.4.2、Rewoo1.4.3、ReAct 二、Lagent …

账号安全及应用

一、账号安全控制 1.1系统账号清理 将用户设置为无法登陆 锁定账户 删除账户 设定账户密码&#xff0c;本质锁定 锁定配置文件-chattr&#xff1a; -a 让文件或目录仅供附加用途。只能追加 -i 不得任意更动文件或目录。 1.2密码安全控制 chage 1.3历史命令 history&am…

Unity 踩坑记录 Rigidbody 刚体重力失效

playerSetting > physics > Gravity > 设置 Y 的值为负数

SpringBoot 根据不同环境切换不同文件路径

最简单的办法就是使用多个 application.yml 配置文件 。一个叫 application-test.yml 测试用&#xff1b;另一个是正式使用的 application-prod.yml 。win环境下大部分是开发测试时候使用的&#xff0c;服务正式上线需要部署在Linux服务器上又换成了Linux。但开发初期或者项目…

Docker容器概念介绍与基本管理

前言 在软件开发和部署环境中&#xff0c;使用 Docker 等容器技术可以帮助团队实现快速、一致、可靠的应用程序部署&#xff0c;提高开发效率和应用程序的可移植性。 目录 一、虚拟化产品介绍 1. 云服务模型 1.1 IaaS 1.2 PaaS 1.3 SaaS 1.4 DaaS 2. 产品介绍 2.1 虚…

5款好用的监控员工电脑软件推荐 (如何监控员工上班工作情况)

在现代的商业环境中&#xff0c;管理和监控员工的工作内容是至关重要的。 为了确保员工的工作效率和质量&#xff0c;公司需要使用一些工具来监控他们的工作进程。 以下是五款实用的监控员工工作内容的软件。 域智盾软件 域智盾是一款专为企业打造的智能管理系统。 它借助人…

FPGA设计篇——波形绘制软件

FPGA设计篇——波形绘制软件 写在前面一、Visio二、TimeGen三、WaveDrom写在最后 写在前面 在FPGA设计过程中&#xff0c;经常需要编写设计文档&#xff0c;其中&#xff0c;不可缺少的就是仿真波形的绘制&#xff0c;可以直接截取Vivado或者Modelsim平台实际仿真波形&#xff…

JVM学习笔记(四)类加载与字节码技术

目录 一、类文件结构 二、字节码指令 2.3 图解方法执行流程 1&#xff09;原始 java 代码 2&#xff09;编译后的字节码文件 3&#xff09;常量池载入运行时常量池 4&#xff09;方法字节码载入方法区 5&#xff09;main 线程开始运行&#xff0c;分配栈帧内存 6&…

分布式-知识体系

分布式系统 本质就是一堆机器的协同&#xff0c;要做的就是用各种手段来让机器的运行达到预期 分布式业务场景 分布式四纵四横说 基于 MSA&#xff08;微服务架构&#xff09;的分布式知识体系 相关概念 – 【摘自网络原文】 节点与网络 节点 传统的节点也就是一台单体的物…

搞嵌入式到底属于程序员吗?

搞嵌入式到底属不属于程序员呢&#xff1f;毫无疑问&#xff0c;当然算啊&#xff01;而且我十分赞同另一位朋友所说的&#xff1a;嵌入式程序员是难得的全栈型程序员。尽管嵌入式领域方向众多且繁杂&#xff0c;但他们同样也是会写代码的程序员。 嵌入式行业主要分为硬件和软…

《从零开始的Java世界》11网络编程

《从零开始的Java世界》系列主要讲解Javase部分&#xff0c;从最简单的程序设计到面向对象编程&#xff0c;再到异常处理、常用API的使用&#xff0c;最后到注解、反射&#xff0c;涵盖Java基础所需的所有知识点。学习者应该从学会如何使用&#xff0c;到知道其实现原理全方位式…

打开IIS网站网页错误提示Argument ‘Key must not be null‘ cannot be null.解决方案 Oracle数据库监听

打开网页异常如下&#xff1a; /“应用程序中的服务器错误。 Argument Key must not be null cannot be null.参数名:Key must not be null 客户端 连接oracle 提示&#xff1a;ORA-12541:TNS:无监听程序 按组合键WindowsR&#xff0c;打开运行 输入命令&#xff1a;lsnrctl s…

周报不止是汇报进度,如何用周报轻松提升团队协作效率?

周报是工作中常见的沟通工具&#xff0c;对于项目经理来说尤其重要。写周报不仅仅是为了完成一项任务&#xff0c;它更是项目管理中不可或缺的环节&#xff0c;它不仅有助于项目经理跟踪项目进度&#xff0c;还加强了团队成员间的沟通与协作。以下是几个关键的原因&#xff1a;…

Geoserver的RESTful接口使用

概述 GeoServer提供了一个RESTful接口&#xff0c;客户端可以通过该接口获取有关实例的信息并进行配置更改。REST接口使用简单的HTTP调用&#xff0c;通过客户端就可以配置GeoServer&#xff0c;而无需使用Web管理接口。 Geoserver中的关系 工作区、数据源、图层、图层组以及…

用 LMDeploy 高效部署 Llama-3-8B,1.8倍vLLM推理效率

节前&#xff0c;我们星球组织了一场算法岗技术&面试讨论会&#xff0c;邀请了一些互联网大厂朋友、参加社招和校招面试的同学&#xff0c;针对算法岗技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何准备、面试常考点分享等热门话题进行了深入的讨论。 汇总…

微信小程序Vue+nodejs+uniapp课堂教学辅助在线学习系统

uni-app框架&#xff1a;使用Vue.js开发跨平台应用的前端框架&#xff0c;编写一套代码&#xff0c;可编译到Android、小程序等平台。 后台主要实现功能&#xff1a;一、用户的管理(用户的信息管理) 二、 课程的管理&#xff08;课程发布&#xff0c;课后成绩的查看&#xff0c…

【C语言__联合和枚举__复习篇10】

目录 前言 一、联合体 1.1 联合体的概念 1.2 联合体与结构体关于声明和内存布局的比较 1.3 联合体的大小如何计算 1.4 使用联合体的2个示例 二、枚举体 2.2 枚举体的概念 2.2 枚举体的优点 前言 本篇主要讨论以下问题&#xff1a; 1. 联合体是什么&#xff0c;它有什么特点 …

每天一题crypto(1)---RSA(小明文攻击)

零.做题&#xff1a; 看到N很大&#xff0c;如果满足 就表示模过程中&#xff0c;没有丢失信息&#xff0c;所以 直接解即可&#xff0c;不要管pq等等 一.题目&#xff1a; N很大 from Crypto.Util.number import * from gmpy2 import *flag bNSSCTF{******}p getPrime(5…