最近在做Fourier Transform的内容,记录一下今天下午的成果。

本文代码全部自行编写,需要math and music项目完整工程可以在gayhub上获取。(现在还没弄完,就先不发了。)

概要

第一部分:

    图像代码部分原理很直接,即极坐标参数方程的转化。

第二部分:

  关于图像质点中心的问题,数学上需要使用复数与微积分的知识求出。

    3b1b的原代码也是将质点的x-coordinate of center of mass图像直接用公式绘制。

    但是本文使用的是暴力的方法,直接用Mobject的get_center通过帧updater描点的方法绘制离散的点集。如果需要,可以拟合为曲线。

  

原视频:https://www.youtube.com/watch?v=spUNpyF58BY&t=188s

bilibili:

https://www.bilibili.com/video/BV1pW411J7s8?share_source=copy_web

数学公式在geogebra中构建如下:

即将cos(mx)+1转化为参数方程[(1+cos(mt))·cos(nt),(1+cos(mt))·sin(nt)]

关于sin和cos的选择:

正弦和余弦差别在于初始相位。这里出于教学考虑用余弦而不是正弦,主要是因为复指数函数的实部是余弦。如果用正弦的话,会发现质心的纵坐标而不是横坐标在频率重合的时候达到峰值(而且是负的)。

manim代码:

创建的Mobject有:axes axes_label polarPlane D_delta D_rou D_move

  以及三个图像:axes_graph polar_graph para_graph

然后使用add_update()添加DecimalNumber作为变化数值到动画更新函数即可。

第一部分代码:

class FourierTrans_First(Scene):
def construct(self):
axes = Axes(
x_range=[-0, 2*PI, PI/4],
y_range=[-0.1, 2.5, 1],
x_length=14,
y_length=2
).to_edge(UP)
axes_label = axes.get_axis_labels('Time','Intensity')
polarPlane = PolarPlane(
radius_max=2.0,
azimuth_units="TAU radians",
size=4,
azimuth_label_font_size=24,
radius_config={"font_size": 24},
).add_coordinates().to_edge(DOWN+LEFT)
#显示坐标与坐标标签
self.add(axes,axes_label,polarPlane) #一些全局参数-修改这三个参数就好
delta = 0#偏移量
rou = 20#theta的系数
move = 10#极坐标变换的变化程度系数
dn_kwargs = {'num_decimal_places':3,}
D_delta = DecimalNumber(delta,**dn_kwargs)
D_rou = DecimalNumber(rou,**dn_kwargs)
D_move = DecimalNumber(move,**dn_kwargs).shift(DOWN) #解析式-公式修改这里就好
r = lambda t: np.sin(D_rou.get_value()*t)+1
par = lambda t: np.array([
(r(t))*np.cos(D_move.get_value()*t),
(r(t))*np.sin(D_move.get_value()*t),
0])
#更新函数
def Func_axes():
return axes.plot(r,color=PINK) def Func_polar():
return polarPlane.plot_polar_graph(r, [0, 2 * PI], color=ORANGE) def Func_para():
para = ParametricFunction(
par,
t_range = np.array([0, 3.14*2]),
fill_opacity=0)\
.set_color(color=[RED,YELLOW,BLUE,RED])\
.shift(DOWN*2+RIGHT*2)
self.add(Dot(para.get_center()))
return para axes_graph = Func_axes()
polar_graph = Func_polar()
para_graph = Func_para() axes_graph.add_updater(lambda mob: mob.become(Func_axes()))
polar_graph.add_updater(lambda mob: mob.become(Func_polar()))
para_graph.add_updater(lambda mob:mob.become(Func_para())) self.add(D_rou,D_move)
self.play(Write(axes_graph),Write(polar_graph),Write(para_graph))
#self.play(ChangeDecimalToValue(D_rou,20),run_time=5,rate_func=linear)
self.play(ChangeDecimalToValue(D_move,20),run_time=5,rate_func=linear)
self.wait(1)

第二部分(含一)代码:

from manim import *

class FourierTrans_First(Scene):
def construct(self):
#########全局参数-修改这5个参数就好#########
delta = 0#偏移量
rou = 0#theta的系数
move = 1#极坐标变换的变化程度系数
target = 1#追踪质心y坐标
track_end = 18#扭扭的结尾
############################################
dn_kwargs = {'num_decimal_places':3,}
D_delta = DecimalNumber(delta,**dn_kwargs)
D_rou = DecimalNumber(rou,**dn_kwargs).shift(LEFT)
D_move = DecimalNumber(move,**dn_kwargs).next_to(D_rou,DOWN)
D_target = DecimalNumber(target,**dn_kwargs).next_to(D_move,DOWN) #######解析式-修改这里 《公式r》 就好#######
r = lambda t: np.sin(D_rou.get_value()*t)+1
############################################
par = lambda t: np.array([
(r(t))*np.cos(D_move.get_value()*t),
(r(t))*np.sin(D_move.get_value()*t),
0]) #coordinate system & labels
axes = Axes(
x_range=[-0, 2*PI, PI/4],
y_range=[-0.1, 2.5, 1],
x_length=14,
y_length=2
).to_edge(UP)
axes_label = axes.get_axis_labels('Time','Intensity') #polar plane
polarPlane = PolarPlane(
radius_max=2.0,
azimuth_units="TAU radians",
size=4,
azimuth_label_font_size=24,
radius_config={"font_size": 24},
).add_coordinates().to_edge(DOWN+LEFT) #point track plane
pointAxes = Axes(
x_range=[0, track_end+track_end*0.3,1],
y_range=[-0.5, 1],
x_length=6,
y_length=4
).to_edge(UP).to_edge(DOWN+RIGHT) #更新函数
def Func_axes():
return axes.plot(r,color=PINK) def Func_polar():
return polarPlane.plot_polar_graph(r, [0, 2 * PI], color=ORANGE) def Func_para():
para = ParametricFunction(
par,
t_range = np.array([0, 3.14*2]),
fill_opacity=0)\
.set_color(color=[RED,YELLOW,BLUE,RED])
return para def Func_para_with_messPoint():
para = ParametricFunction(
par,
t_range = np.array([0, 3.14*2]),
fill_opacity=0)\
.set_color(color=[RED,YELLOW,BLUE,RED]) messPoint = Dot(pointAxes.coords_to_point(D_move.get_value(),para.get_y()),color=GREEN_B,radius=0.02)
self.add(messPoint)
return para axes_graph = Func_axes()
polar_graph = Func_polar()
para_graph = Func_para() #define messPoint
messPoint = Dot(para_graph.get_center()) #定义updater_func表达式
axU = lambda mob: mob.become(Func_axes())
poU = lambda mob: mob.become(Func_polar())
paU = lambda mob:mob.become(Func_para().shift(DOWN+RIGHT*3))
paU_with_messPoint = lambda mob:mob.become(Func_para_with_messPoint().move_to(para_graph)) #添加updater
axes_graph.add_updater(axU)
polar_graph.add_updater(poU)
para_graph.add_updater(paU) ################################################
####################开始动画####################
################################################ #显示坐标与坐标标签
group_axes = VGroup(axes,axes_label,axes_graph)
group_polar = VGroup(polarPlane,polar_graph)
self.add(D_rou,D_move)
self.play(Write(group_axes),Write(group_polar),Write(para_graph))
self.play(ChangeDecimalToValue(D_rou,track_end),run_time=14,rate_func=linear) #左下角的图像消失,右下角的图像挪来左边
polar_graph.remove_updater(poU)
self.play(FadeOut(polar_graph)) para_graph.remove_updater(paU)
self.play(para_graph.animate.move_to(group_polar)) self.play(GrowFromCenter(pointAxes)) #开始扭扭~并且加点追踪
para_graph.add_updater(paU_with_messPoint)
D_move.set_value(0)
self.play(ChangeDecimalToValue(D_move,track_end),run_time=30,rate_func=linear)
self.wait(1)

【manim】3b1b的"Almost" Fourier Transform复刻的更多相关文章

  1. 傅里叶变换 - Fourier Transform

    傅里叶级数 傅里叶在他的专著<热的解析理论>中提出,任何一个周期函数都可以表示为若干个正弦函数的和,即: \[f(t)=a_0+\sum_{n=1}^{\infty}(a_ncos(n\o ...

  2. 使用 scipy.fft 进行Fourier Transform:Python 信号处理

    摘要:Fourier transform 是一个强大的概念,用于各种领域,从纯数学到音频工程甚至金融. 本文分享自华为云社区<使用 scipy.fft 进行Fourier Transform:P ...

  3. 从傅里叶级数(Fourier series)到离散傅里叶变换(Discrete Fourier transform)

    从傅里叶级数(Fourier series)到离散傅里叶变换(Discrete Fourier transform) 一. 傅里叶级数(FS) 首先从最直观的开始,我们有一个信号\(x(t)\)(满足 ...

  4. YY表行推荐十块顶级复刻表,一比一开模复刻,外观堪比正品

    随着国内制表工艺的逐渐提升,顶级复刻表的行列里成员越来越多,今天复刻表工厂就总结一下最值得入手的十款顶级复刻表来和大家分享. TOP 10:爱彼 AP15400购买指数★★★ AP15400采用顶级复 ...

  5. 复刻smartbits的国产网络测试工具minismb简介

           复刻smartbits的国产网络性能测试工具minismb,是一款专门用于测试智能路由器,网络交换机的性能和稳定性的软硬件相结合的工具.可以通过此工具测试任何ip网络设备的端口吞吐率,带 ...

  6. 复刻smartbits的国产网络性能测试工具minismb-如何配置Ping报文

    复刻smartbits的国产网络性能测试工具minismb,是一款专门用于测试智能路由器,网络交换机的性能和稳定性的软硬件相结合的工具.可以通过此以太网测试工具测试任何ip网络设备的端口吞吐率,带宽, ...

  7. 复刻smartbits的国产网络测试工具minismb-使用burst模式

    复刻smartbits的国产网络性能测试工具minismb,是一款专门用于测试智能路由器,网络交换机的性能和稳定性的软硬件相结合的工具.可以通过此工具测试任何ip网络设备的端口吞吐率,带宽,并发连接数 ...

  8. 复刻smartbits的国产网络测试工具minismb-如何添加数据流

    复刻smartbits的国产网络性能测试工具minismb,是一款专门用于测试智能路由器,网络交换机的性能和稳定性的软硬件相结合的工具.可以通过此工具测试任何ip网络设备的端口吞吐率,带宽,并发连接数 ...

  9. 复刻smartbits的国产网络测试工具minismb-如何测试路由器

    复刻smartbits的国产网络性能测试工具minismb,是一款专门用于测试智能路由器,网络交换机的性能和稳定性的软硬件相结合的工具.可以通过此工具测试任何ip网络设备的端口吞吐率,带宽,并发连接数 ...

随机推荐

  1. JAVA用for循环打印*三角形

    public class Sanjiaoxing { //本节为for循环的嵌套结构练习 public static void main(String[] args) { // TODO Auto-g ...

  2. vue 使用npm install安装依赖失败 【问题分析与解决】

    1 进入项目根目录,先通过 npm install 命令安装项目所需依赖,再通过 vue ui 命令打开 Vue Cli 提供的图形化界面,选择项目所在文件夹将项目导入. 出现问题 npm insta ...

  3. Linux文本三剑客-sed

    sed工作原理: sed: Stream Editor.流编辑器 --- 属于行编辑工具 sed和vim一样都是文本编辑工具. 行编辑工具:一行一行处理文件内容 全屏编辑工具:一次性将文件内容加载到内 ...

  4. IP寻址与规划

    一.IP寻址和子网划分 IP地址的主机部分可被分为三种地址:网络地址.主机地址和定向广播地址. 网络地址是网络号中的第一个地址.它用来将网络内的其他所有网段唯一标识为一个网段或广播域.定向广播地址是网 ...

  5. NC20861 兔子的逆序对

    NC20861 兔子的逆序对 题目 题目描述 兔子最近喜欢上了逆序对.一个逆序对 \((i,j)\) 需要满足 \(i < j\) 且 \(a_i > a_j\) .兔子觉得只是求一个序列 ...

  6. C语言输出九九乘法表

    C语言学了有一阵子了,趁着假期没事练练手,没想到挺简单 基本思路是这样的 先写一个主函数,然后定义两个变量i1和i2;使用for语句循环嵌套,外层循环负责写循环9次,内循环里面写从1开始递增去和外层循 ...

  7. halcon 基础总结(一)裁切图片并旋转图像

    ​ 第一步当然是读取图像了:read_image (Image, 'C:/Users/HJ/Desktop/test_image/b.jpg') ​ 第二步:二值化.二值化.因为我这里的物体是黑色的, ...

  8. Python 数据科学手册:读书笔记概论

    为防止遗忘,在空闲时间将读书的笔记开始按照章节进行概括总结(2022.1.1): 第二章:NumPy 入门 第三章:Pandas 数据处理 第四章:Matplotlib 数据可视化 第五章:机器学习 ...

  9. pip安装报错Could not install packages due to an EnvironmentError: Missing dependencies for SOCK

    unset all_proxy && unset ALL_PROXY

  10. 升级了Springboot版本后项目启动不了了

    问题背景 项目上使用的springboot版本是2.1.1.RELEASE,现在因为要接入elasticsearch7.x版本,参考官方文档要求,需要将springboot版本升级到2.5.14. 本 ...