首页
Preview

如何使用Python创建像3Blue1Brown一样的流畅数学动画

除非另有说明,否则所有图片均由作者提供。

你知道创造 3Blue1Brown 的《线性代数精华》系列视频用了多少行代码吗?

这个系列有 16 个视频,频道上总共有 100 多个视频,这些数字足以说明数学界对 Grant Sanderson 的贡献有多大。

虽然这个频道似乎专注于数学,但它实际上是他为了练习编程技能而创建的图形库的副产品。他称之为 Manim,它成为了可视化和动画展示数学和计算机科学中一些最复杂主题的先锋工具。

目前,他关于神经网络、微积分、拓扑和纯数学的视频都被认为是 YouTube 上的珍品。

如果你能创造出与他的作品类似的东西,那不是很酷吗?通过这个 Manim 教程,你不仅可以创建自己的惊人动画,还可以学习 Grant Sanderson 在他的视频中使用的一些标志性转换的秘密。

什么是 Manim?

Manim 是数学动画引擎的缩写,由 Grant Sanderson 创建,用于制作高精度的数学动画视频。3B1B 频道和这个 Python 库的主要目标是通过视觉直觉来补充传统的基于教科书的数学学习。

目前,Manim 有两个版本:由 Grant 创建的原始库和由 Manim 社区维护的分支版本。在本文中,我们将使用社区版本,因为它的维护更好、经过测试,而且最重要的是文档编写得更详细。

有很多安装选项,我认为使用 Docker 镜像是与库交互的最简便方式。请参考此页面获取 Docker 化安装说明或此页面获取其他选项,以便你跟上本文的内容。

或者,你可以留下来享受内容,因为这里会有一些惊人的动画!

请注意,本文包含多个 GIF 和视频动画,这可能会减慢它们的显示速度。你可以从我的 GitHub 仓库下载文章的源代码。本文还涉及到一些 Python 面向对象编程的概念,这可能会让初学者感到困惑。如果你在任何时候遇到困难,请查看我的面向对象编程系列文章

Manim 的高级概述

Manim 是作为 FFmpeg 视频编码引擎 和 Python 之间的桥梁而创建的。由于无法将内置的 Python 数据结构传递给 FFmpeg,Manim 实现了几个数学对象表示和动画类。

这些类通常分为三类:SceneMobjectAnimation。为了更清楚地解释这些概念,让我们创建我们的第一个动画:

在你安装了 Manim 并将上面的代码保存在名为 scenes.py 的脚本中后,运行以下命令:

manim -pqh scenes.py MyFirstAnimation

然后你应该会得到这个输出:

恭喜!你刚刚制作了你的第一个动画!

这是 CLI 命令的详细说明——在 manim 后添加 -p 将使你能够在编译完成后立即播放视频。与 qh 结合使用,表示以高质量进行渲染。有四个分辨率:低(l)、中(m)、高(h)和 4k(k),渲染时间逐渐增加。

如果你想要动画的 GIF 版本,在 -pqh 后添加 -i。这里是完整列表的 manim CLI 命令。

拆解基本的 Manim API

让我们逐行分析上面的动画以理解它。

在第一行导入了所有的 manim 内容之后,我们定义了一个场景类和一个 construct 方法:

class MyFirstAnimation(Scene):
    def construct(self):
        ...

这是创建单个动画的通用公式——你定义一个自定义类,该类继承自 Scene类,并具有一个 construct 方法。Scene 类是 Manim 的高级构建块,它将所有相关的动画和对象连接到一个结构中。接下来,我们创建了两个属于Mobject类(数学对象)的对象(一个星形和一个圆形)。这个Mobject 类是许多内置mobjects(如几何形状、向量、坐标系等)的基本数据结构。基本上,所有不是场景和动画的东西都是Mobject

然后,我们有 Animation 类。在上面的例子中,我们使用了其中的三个 - FadeInTransformFadeOut。Manim中的所有内置Animation类都接受mobjects作为参数,并对它们应用各种效果。例如,Transform接受两个mobjects,并播放平滑动画,将第一个转换为另一个。

每次创建动画时,都必须将其包装在play函数中,以便它们在屏幕上呈现。

最后,我们有像REDBLUEYELLOWPITAU等常量。这些是Manim的 constants 模块的一部分,将常用值编码为变量,并在片段的第一行中导入:

控制Mobjects及其位置

默认情况下,添加到屏幕上的所有mobjects都显示在ORIGIN中:

>>> ORIGINarray([0., 0., 0.])

Manim使用numpy数组表示xyz坐标的屏幕。只要你在2D空间中进行动画,z就会保持为0。要在xy方向上将对象移动一个单位,可以使用常量LEFTRIGHTUPDOWN

例如,我们将在屏幕的不同位置绘制四个mobjects,并在原点放置一个点以供参考:

由于LEFTRIGHT等变量是Numpy数组,因此它们允许数值运算,从而像上面那样进行缩放。还有其他内置的位置变量,如UL(UP + LEFT)、DR(DOWN + RIGHT)等:

在上面的片段中,我们使用了mobjects的shift方法,通过传递它们的新坐标位置来移动它们。由于shift只是一个函数,因此实际的移位不会被动画化。要显示未进行动画处理的mobjects,我们使用add方法。

如果我们想要动画化这种移动运动会怎样呢?好吧,你可以在animate函数之后链接shift,像这样:

事实上,使用animate方法,你可以对几乎任何类型的mobject进行动画处理。例如,mobjects具有几个以set_*开头的方法,这些方法更改它们的属性。这是一个例子:

动画化函数

让我们更加认真地学习如何绘制函数并动画化它们的创建。从现在开始,我将使用JupyterLab及其%%manim单元格魔术来呈现manim输出。语法与CLI界面相同。

要绘制类似于Matplotlib中的2D轴,请使用所需的参数调用 Axes 类。

接下来,我们使用 get_graph 方法,传递我们要绘制的函数。这个内置方法只接受单变量函数,返回xy之间的一对一映射。在上面的例子中,我们绘制了sin(1/x)的图形。

可选地,你可以使用get_graph_label在特定位置放置函数的标签:

最后,我们使用 VGroup 类创建了一组mobjects。它允许对多个mobjects进行同时动画和变换。

还要记得绘制你创建的每个mobject。可以使用动画函数,如Create/Write,也可以使用self.add

更多酷例子

你没想到我会不展示3B1B的一些标志性动画吧?

我从他的《线性代数的本质》系列中了解了3B1B,看到空间的线性变换完全让我惊叹。疯狂的部分是,使用Manim对其进行动画处理非常容易:

同样,看到在3D中绘制函数的图形是令人眼前一亮的,因为我们都习惯在XY平面上绘制函数。当你查看以下函数时,你将意识到数学可以是多么美丽:嘿,那么这些非线性变换怎么样?

还有更好的吗?当然可以!

虽然已经很酷了,但是你今天所学只是manim能做的一小部分。上面的动画只是Grant Sanderson在他的简单开场场景中使用的内容。

当你想要超越内置的mobjects和动画类时,这个库就有一个陡峭的学习曲线。实现自定义类可能会非常冗长,对于较长的视频通常需要成千上万行的代码。

然而,如果你真的热爱数学并想用新颖和创造性的方式向他人解释它,这不应该阻止你。

结语

我很抱歉把这篇文章变成了太多的“如何”文章。那只是我根深蒂固的过度解释的倾向。

然而,我觉得恰当的解释是必要的,因为互联网上充满了过时的教程和视频。除此之外,当你在一个项目中意外地使用不同版本的manim时,会出现混淆。

如果你想成为一个铁杆manim动画师,我强烈建议你仔细阅读社区版本的文档的每一页。我还建议你查看像这个这样使用Manim的频道,并阅读他们的源代码。

译自:https://towardsdatascience.com/how-to-create-slick-math-animations-like-3blue1brown-in-python-457f74701f68

版权声明:本文内容由TeHub注册用户自发贡献,版权归原作者所有,TeHub社区不拥有其著作权,亦不承担相应法律责任。 如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

点赞(0)
收藏(0)
alivne
复杂的问题简单化

评论(0)

添加评论