目录

傅里叶级数 画初音 附底层代码

傅里叶级数

公式原型

https://raw.githubusercontent.com/kengerlwl/kengerlwl.github.io/refs/heads/master/image/6059b08d8855b8450233e45c78893109/63a9ec3cebdb311f588775df13f64c3b.png https://raw.githubusercontent.com/kengerlwl/kengerlwl.github.io/refs/heads/master/image/6059b08d8855b8450233e45c78893109/59d753bfa952b7c154c42d249cc10138.png https://raw.githubusercontent.com/kengerlwl/kengerlwl.github.io/refs/heads/master/image/6059b08d8855b8450233e45c78893109/259554a68e39cac718a4d814bcc1b394.png https://raw.githubusercontent.com/kengerlwl/kengerlwl.github.io/refs/heads/master/image/6059b08d8855b8450233e45c78893109/849151af38e824a2580a95c09697715f.png

代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import numpy as np
import matplotlib.pyplot as plt
import math

# x, y 的参数方程,用来计算在某个时间进度下,x和y的坐标
def fx(t):
    x = 2 * np.cos(t) - np.cos(2*t)
    return x
def fy(t):
    y = 2* np.sin(t) - np.sin(2*t)
    return y


def ft(t):
    x = fx(t)
    y = fy(t)
    return x + 1j * y


t= np.linspace(0, 2 * math.pi, 100)

x = fx(t)

y = fy(t)

# 查看原始数据
plt.title('the origin data')
plt.plot(x, y, c = 'blue')
# plt.show()


# 微分计算的步长
dx = 0.001

# 计算定积分, dx是微分程度 left right是上下界
def calF(f, dx, left, right):
    Sum = 0


    # 选值进行计算的点
    xNum = np.linspace(left, right, int((right-left) /dx)  )

    for i in xNum:
        now = f(i) * dx
        Sum += now
    return Sum


tmpf = lambda x: x**2

ans = calF(tmpf, dx, 0, 1)
print(ans)


T = 2 * math.pi
wo = 2 * math.pi / T

# 这里用得是欧拉公式化简后的 e 的指数形式
c = []


# 这里的范围就相当于是圈数
for i in range(-30, 30):
    print(i)
    tmpf = lambda x: ft(x)* np.exp(-1j * i * wo * x)  # 隐函数表达式

    nowc = calF(tmpf, dx, 0, T) / T  # 定积分计算, 因为具有着正交的性质
    c.append([i, nowc])


print(c)


# 计算傅里叶级数的函数
def FinallFunc(t):
    Sum = 0
    for n, nowc in c:
        tmp = nowc * np.exp(1j * n * wo * t)
        Sum += tmp

    return Sum



# 进行测试, 看是否计算出来了傅里叶级数
tx = []
ty = []
for i in t:
    num = FinallFunc(i)
    tx0 = num.real
    ty0 = num.imag

    tx.append(tx0)
    ty.append(ty0)
plt.title('the Fourier data')
plt.scatter(tx, ty, c= 'black')
plt.show()

结果,拟合效果很好 https://raw.githubusercontent.com/kengerlwl/kengerlwl.github.io/refs/heads/master/image/6059b08d8855b8450233e45c78893109/05327a3d729c8fbb1621ee55aad860cf.png

数据变成离散的点,将这些点变成一个近似函数

那么需要对数据先分段拟合成一个个小段的函数,可以直接用直线。

这里参考某位大佬的做法大佬,使用贝塞尔曲线进行拟合,不过要注意函数。

我这里就不用贝塞尔了,直接用直线替代。

每一段,分必计算c(-n) 到 cn。然后相加起来,注意每一断时间。

写好加载数据变成函数的代码后。

然后与前面的拟合代码结合。

结果: 当接近500个圈的时候就效果很不错了。

https://raw.githubusercontent.com/kengerlwl/kengerlwl.github.io/refs/heads/master/image/6059b08d8855b8450233e45c78893109/a5ddb6607611c10d245089501543a8b9.png 底层工程在github