AnyMath 文档
Notebook

MATLABEngee在谱分析与时频分析任务中的比较

在频谱分析与时频分析领域比较 MATLABEngee 时,我们将针对两个任务——傅里叶正变换与逆变换以及时频分析——探讨它们的功能和方法。

设一个随机输入信号。

In [ ]:
Pkg.add(["DSP"])
   Resolving package versions...
   Installed MPItrampoline_jll ── v5.5.2+0
   Installed IntervalArithmetic ─ v0.22.23
   Installed Documenter ───────── v1.8.1
  No Changes to `~/.project/Project.toml`
  No Changes to `~/.project/Manifest.toml`
In [ ]:
x_in = randn(300)
plot(x_in)
Out[0]:

傅里叶谱变换(FFT 和 IFFT)

Engee 中使用了 FFTW 包中的函数:

  1. fft:正向快速傅里叶变换。
  2. ifft:逆快速傅里叶变换。
In [ ]:
using FFTW

# 傅里叶正变换
X = fft(x_in)

# 傅里叶逆变换
x_e = ifft(X)
Out[0]:
300-element Vector{ComplexF64}:
   0.17371489951964067 - 1.0954200509634878e-16im
    2.2377132029330844 + 2.2408317281964536e-16im
   -1.4829786507042373 + 2.2273568055204485e-16im
   -0.2348809459284378 - 4.320879722422531e-17im
  -0.31906921401547966 - 3.6273233115378e-17im
  -0.34465018150965426 + 1.56247404219809e-17im
   -1.2607176668657911 + 3.8205740429821057e-17im
   -1.3833370605598396 - 1.0954483820890101e-16im
    0.1073530872080035 + 4.054066051089606e-18im
   -1.1869125065267447 + 1.204268348309886e-16im
  -0.08869450663083418 - 9.907440153835353e-17im
    0.5356860088040623 - 9.578303805633852e-17im
 -0.027712149720118998 - 7.601346822348835e-17im
                       ⋮
    -1.099956486756265 - 2.4424426718144734e-16im
    1.9684779743047827 - 2.3821720609620034e-16im
   -0.9838794916231319 - 6.468831717252368e-17im
   -0.5483474914245768 + 9.609569947930888e-17im
   -0.4423484330625661 - 1.2054068815356207e-16im
   0.12882694892579774 - 7.323649583095336e-17im
    0.3790454548946689 + 1.2509628585190657e-16im
   -0.8125388544875829 + 1.946643454251107e-16im
    -0.603401253638474 + 1.6844285716281442e-17im
    0.9546133370515606 + 1.1027054714660098e-17im
   -1.0973310353263745 + 1.3942493435956269e-16im
    -1.198221964035762 - 1.6134900674300149e-16im

MATLAB 中,提供了用于快速傅里叶变换的内置函数:

  1. fft:正向快速傅里叶变换。
  2. ifft:逆快速傅里叶变换。
In [ ]:
using MATLAB

# 傅里叶正变换
mat"""X = fft($(x_in));"""

# 傅里叶反变换
x_m=mat"""ifft(X);"""
Out[0]:
300-element Vector{Float64}:
  0.17371489951964084
  2.2377132029330844
 -1.4829786507042373
 -0.2348809459284376
 -0.3190692140154795
 -0.3446501815096541
 -1.260717666865791
 -1.3833370605598394
  0.1073530872080034
 -1.186912506526744
 -0.08869450663083417
  0.5356860088040618
 -0.027712149720119327
  ⋮
 -1.0999564867562652
  1.9684779743047829
 -0.9838794916231323
 -0.5483474914245771
 -0.44234843306256627
  0.12882694892579727
  0.37904545489466895
 -0.812538854487583
 -0.6034012536384741
  0.9546133370515602
 -1.0973310353263745
 -1.1982219640357619

让我们比较结果并计算误差。

In [ ]:
plot(x_in)
plot!(real(x_e))
plot!(x_m)
Out[0]:
In [ ]:
error_e = abs.(x_in-real(x_e))
error_m = abs.(x_in-x_m)
println("Engee的平均误差:$(sum(error_e)/length(error_e))")
println("MATLAB 平均误差:$(sum(error_m)/length(error_m))")
Engee的平均误差:1.9054347220418914e-16
MATLAB的平均误差:2.179376470956562e-16

在两种环境中,正向傅里叶变换的结果均为复数,而逆变换则返回原始信号,仅存在与数值舍入相关的微小误差。
由此可见,代码的语法和逻辑完全一致。

频域-时域傅里叶变换

在Engee中,此类变换没有标准函数,需要手动实现。

In [ ]:
using DSP
# 用于生成啁啾信号的函数
function chirp(t::AbstractVector{T}, f0::T, t1::T, k::T) where T<:Real
    return cos.(2π * (f0 .* t .+ 0.5 * k .* t.^2))
end

# 哈明窗口
function hamming(N::Int)
    n = 0:N-1
    return 0.54 .- 0.46 .* cos.(2π * n / (N - 1))
end

x = chirp(0:0.001:1, 0.0, 1.0, 100.0)  # 啁啾声
l=500 # 窗口大小
window=vcat(hamming(l),zeros(length(x)-l))

P = DSP.periodogram(x; fs=1000, window=window, nfft=length(x))

# 光谱可视化
plot(freq(P), 20*log10.(power(P)), xlabel="Frequency (Hz)", ylabel="Power Spectrum (dB)", title="Power Spectrum", linewidth=2)
Out[0]:

MATLAB 提供了 pspectrum 函数,可用于对信号进行时频分析。
pspectrum 会自动选择合适的分析方法。
支持多种可视化形式(频谱图、功率密度图)。

In [ ]:
using Images
mat"""cd("$(@__DIR__)")"""
mat"""
% 频域-时域分析
x = chirp(0:0.001:1, 0, 1, 100);
pspectrum(x, 1000); % 时频谱
saveas(gcf, 'frequency_time_spectrum.jpg'); % 将当前图形保存为 JPG
"""
load( "$(@__DIR__)/frequency_time_spectrum.jpg" )
Out[0]:
No description has been provided for this image

从图表中可以看出,信号行为的主要趋势在 Engee 中得到了反映。若要绘制更详细的图表,需要额外实现更精细的周期图函数窗口计算。

此外,让我们比较一下在 MATLAB 和 Engee 中生成的输入数据的正确性。

In [ ]:
plot(mat"chirp(0:0.001:1, 0, 1, 100)"[:])
plot!(chirp(0:0.001:1, 0.0, 1.0, 100.0))
title!("Sum_error: $(sum(mat"chirp(0:0.001:1, 0, 1, 100)"[:]-chirp(0:0.001:1, 0.0, 1.0, 100.0)))")
Out[0]:

如我们所见,输入信号完全一致。

结论

MATLAB 提供了用于执行这些操作的内置函数。 在 Engee 中,可以利用第三方库(如 DSP 或 FFTW)来处理更复杂的信号运算。此外,需要注意的是,Engee 在变换的实现方式上提供了更大的灵活性。 为了简化在 Engee 中实现这些操作以完成您的任务,请使用本演示中描述的现成方法。

在比较这两种环境的能力时,还有一点需要注意:MATLAB 针对矩阵和信号处理进行了优化。 然而,如果代码在编写时充分考虑了 Engee 环境的特性,Engee 的计算速度通常会更快,这在大型系统中执行和测试算法时能带来显著的速度提升。