当前位置: 首页 > news >正文

MATLAB中circshift函数的原理分析——psf2otf函数的核心

之所以讲到MATLAB中circshift函数,也是源于Rafael Gonzalez的这个图,作为前几篇答廖老师问的blog的基础。
Rafael Gonzalez的这个图无论从哪幅图到哪幅图都不是直接的傅里叶变换或傅里叶逆变换,需要循环移位,即circshift函数。
在这里插入图片描述
这就需要从头说起。

离散时间傅里叶变换(DTFT)的一个性质是,如果一个序列共轭对称,即 x [ n ] = x ∗ [ − n ] x[n] = x^*[-n] x[n]=x[n],那么它的傅里叶变换是实数。因此,当fft函数的输出结果出乎意料地为复数时,人们有时会感到惊讶。

用实序列说明。当输入序列是实偶对称时,其傅里叶变换的输出序列也是实数且偶对称的。

例如:

n = -3:3;
x = exp(-abs(n)/2)x =0.2231    0.3679    0.6065    1.0000    0.6065    0.3679    0.2231

这个序列看起来是对称的,但当我们计算fft(x)时,其输出却是复数。


>> X = fft(x)X =153.3951 + 0.0000i  -1.0726 - 0.5166i   0.2154 + 0.2701i  -0.0593 - 0.2598i  -0.0593 + 0.2598i670.2154 - 0.2701i  -1.0726 + 0.5166i

原因是fft函数计算的是在区间 0 ≤ n < N 0 \leq n < N 0n<N内非零的序列 x [ n ] x[n] x[n]的离散傅里叶变换。实际上, x [ n ] x[n] x[n]并不是关于原点对称的,它是一个对称序列的移位版本,而这种移位导致了fft的输出为复数。

为了得到实数值的傅里叶变换,我们需要将序列循环移位,使中心元素移动到向量的左边。对于长度为奇数或偶数的序列,我们都可以使用以下方法来找到中心位置,并进行相应的循环移位:

xs = circshift(x, [0 -floor(length(x)/2)]);
xs =1.0000    0.6065    0.3679    0.2231    0.2231    0.3679    0.6065

现在,如果我们计算 fft(xs),将会得到预期的实数输出。

>> Xs = fft(xs)Xs =3.3951    1.1905    0.3454    0.2665    0.2665    0.3454    1.1905

结合之前讲的循环移位,用这幅图解释,循环移位后是最后的结果,但是对应于第三幅中中心在原点的情况,这才是偶函数。
在这里插入图片描述

如果打算进行零填充(zero-padding),应该先填充再应用循环移位(这里很关键,我曾经在这里错过,百思不得其解,思考了数年之久)。下面是一个示例,其中我们将原始序列扩展到长度为128,并对其进行处理:

x128 = x;
x128(128) = 0; % 零填充到长度128
x128s = circshift(x128, [0 -floor(length(x)/2)]); % 循环移位
X128 = fft(x128s);

检查是否为实数:

isreal(X128)ans =logical0

这里可能会出现一个小的误差,认为这个过程不能产生实数结果,但实际上是因为浮点舍入误差。查看虚部的大小可以发现它们非常小:

max(abs(imag(X128(:))))ans =2.1252e-16

可以使用real函数去除可以忽略不计的虚部。下面是绘制实值傅里叶变换的方法。我将使用频率轴标记技术来展示结果:

w = unwrap(fftshift(2*pi * (0:(128-1)) / 128) - 2*pi);
figure; plot(w/pi, fftshift(real(X128)), "LineWidth", 1);
xlabel('弧度 / \pi');
box off;
grid on;

在这里插入图片描述

http://www.lryc.cn/news/502885.html

相关文章:

  • js 惰性函数
  • 智能技术引领未来:自动图像标注的创新应用与发展
  • 深入探索数据库世界:SQLite、Redis、MySQL 与数据库设计范式
  • 内网是如何访问到互联网的(华为源NAT)
  • 华为无线AC、AP模式与上线解析(Huawei Wireless AC, AP Mode and Online Analysis)
  • 奖励模池化
  • 基于django协同过滤的音乐推荐系统的设计与实现
  • Tiptap,: 富文本编辑器入门与案例分析
  • 使用Linux的logrotate工具切割日志:Tomcat、NGINX(journal文件清理)
  • CSS系列(11)-- 滤镜与混合模式详解
  • linux - 存储管理
  • 在 Kibana 中为 Vega Sankey 可视化添加过滤功能
  • styled-components 库的用法介绍和实践总结
  • SSE(Server-Sent Events)主动推送消息
  • pandas.core.frame.DataFrame怎么进行对象内容的读写
  • 短作业优先调度算法
  • SpringBoot 应用并发处理请求数的深入解析
  • MetaGPT中的教程助手:TutorialAssistant
  • 介绍一款docker ui 管理工具
  • 0022 基于SpringBoot的婚纱摄影线上预约系统的设计与实现
  • uni-app在image上绘制点位并回显
  • Comparator.comparing 排序注意
  • PPO系列3 - PPO原理
  • .idea
  • 单片机:实现呼吸灯(附带源码)
  • PostgreSQL数据库序列信息查询
  • 【Linux】Nginx一个域名https一个地址配置多个项目【项目实战】
  • Linux驱动开发(12):中断子系统–按键中断实验
  • 代码随想录-算法训练营-番外(图论02:岛屿数量,岛屿的最大面积)
  • 20 go语言(golang) - gin框架安装及使用(一)