見出し画像

理系のためのManim入門 *随時更新*

[最終更新日 2024年3月22日]


そもそも Manim って何?

ChatGPT 大先生に聞いてみましょう。

Manim(Mathematical Animation Engine)は、数学や物理を視覚的に表現するためのPythonのアニメーションエンジンです。Manimは、3Blue1Brownとして知られるYouTuberであるGrant Sandersonによって開発され、彼の数学の教育動画で幅広く使用されています。

つまり Python でコードを書いたら、数式やグラフをアニメーションとして動画化してくれるのが Manim です。次のような動画が作れます。

3Blue1Brown先生、偉大すぎる。世界一の数学系Youtuber(当社調べ)なのも納得。

私もいくつかmanimを利用してYoutube動画を作りました


事前知識

Manim を利用するうえで必要なのは、

  1. やる気

  2. Python の知識

  3. TeX 記法の知識

  4. コンピュータ視覚関連の知識

があれば重宝します。

Manim のインストール

Manimは誰でも無料で利用できます。今回は ManimCE を使います。

(正確には, Manimには2つのバージョンがあり ManimCE と ManimGL です。配布されているのは ManimCE の方で開発が進んでいる段階ですので仕様変更が多いです。ManimGLのほうは 3b1B氏が利用していると思われるバージョンです。レンダリングを待たずにリアルタイムにアニメーションを作成できるものらしいです。)

必要なソフト

  • LaTeX (数式のレンダリングするやつ)

  • Python (プログラム書くやつ)

  • FFmpeg (動画エンコードするやつ)

  • Manim (本体)

  • VScode + Manim Sideview (編集が便利になるやつ)


LaTeX, Python, FFmpeg はそれぞれインストールしておきましょう。

Metachick-2021様の記事が参考になります。


Python のバージョンについて

普通にPythonをインストールしましょう。わからない場合は他の方の記事を参照してください。

Python の最新バージョンは Python 3.12 です。普通にManim を動かすうえではPython 3.12で大丈夫です。

しかし、後述のプラグインのインストールのために、Python 3.10にダウングレードした経緯があります。そのため最初からPython 3.10をインストールするのが私のオススメです。

古すぎる Python 3.7以前などは逆に動かない可能性があります。


win 11 での環境変数の設定

Windowsマーク > 設定(歯車)を開く > システム > バージョン情報 > システムの詳細設定 > 環境変数(N) … 

これで Path を登録します。

Manim のインストール

以下をコマンドプロンプトで実行してダウンロードします。

pip install manim

Pythonの入っているフォルダで
Python312\Lib\site-packages\manim
の位置にmanimが入っているので環境変数のPathに追加しておきます。
コマンドプロンプトで

manim -version

を実行してバージョンが表示されればOKです。

私はインストール時にエラーが出たので

pip install setuptools

をしてから

pip install manim

を実行したらうまくいきました。

Hello World してみる

main.pyを作成して次のコードをVScodeで開きます。

from manim import *

class HelloWorld(Scene):
    def construct(self):
        text = Tex("Hello World !")
        self.add(text)

緑色のボタンを押して

緑のボタン

HelloWorldを選択すると

クラス名の選択
Preview

無事に Hello World ! できました。

Manim Sideview の設定

VScodeの歯車 > 設定 から manim と検索します。
私は以下の項目のチェックを外しました。

  • Checkered Background

  • Run On Save



Manim の基本


Python ファイルの一番上に

from manim import *

を書きます。次にクラスを定義します。

from manim import *

class MyAnimation(Scene):

今回はクラス名をMyAnimation にしました。()の中身であるSceneについては、描画したいことによって変わります。

次にコンストラクタを定義します。

from manim import *

class MyAnimation(Scene):
    def construct(self):


次に描きたいものを定義します。

from manim import *

class MyAnimation(Scene):
    def construct(self):
        circle = Circle(radius=1.0)

このように定義したものをMObjectといいます。今回は circle という名前のMObject を 半径1の円として定義しました。

最後に描画したいMObjectを表示させます。

from manim import *

class MyAnimation(Scene):
    def construct(self):
        circle = Circle(radius=1.0)

        self.add(circle)

これで次のような円を描画できます。この時点ではまだ動画になっておらず単なる画像です

少し右に動かしてみましょう。 self.play () という関数に動かしたいMobject と動かし方をいれることでアニメーションが作れます

from manim import *

class MyAnimation(Scene):
    def construct(self):
        circle = Circle(radius=1.0)

        self.add(circle)
        self.play(circle.animate.shift(RIGHT))
        self.wait()


用語

MObjects : Math Object の意味。 円や四角、関数グラフやカメラも含む。



公式ドキュメント

大抵のことは公式ドキュメントをよく読むことで解決します。


ManimGL向け*の3b1b本人のドキュメント




Discord に参加しよう

Manim の開発者コミュニティのDiscord が存在します。そこに入っていれば英語さえできればHelp forumで質問が可能です。


Manim Tips

Manim のノウハウを乱雑に書いていきます。

レンダリング方法

緑色のボタンを押すとクラス名の選択をして、レンダリングされます。しかしVScodeを閉じるまで、同じクラスのレンダリングしかされないので、
Previewの右下の↩ボタンでクラスを変更します。

Mobject Gallery

拡張機能 Manim Sideview の機能に Mobject Gallery があります。
Ctrl +Shift + P を押して Manim: Open Mobject Gallery を選択すると開けます。

利用したい Mobject をクリックすると ソースコードにペーストされます。


クラス名

from manim import *

class Myscene(Scene):

この場合 Myscene がクラス名である。クラスごとにレンダリングします。
manim ファイル名 クラス名 

manim main.py Myscene 
で実行することができます。

生成した画像や動画は pyのファイル名のフォルダに保存されます。
media > image > ファイル名 

古い関数名

Manimでは、以前使われていた記法が最近では使われなくなっていたりします。エラーが発生した場合は、古い記法を使用していないかどうかを確認しましょう。数年前のブログ記事などには、古い記法で書かれている可能性があります。例えば、"ShowCreation"は"Create"に置き換えられました。

表示して消す

ShowCreationThenFadeOut

曲がった矢印

from manim import *

class CurvedArrowExample(Scene):
    def construct(self):
        curvedArrow = CurvedArrow(start_point=np.array([-3.5,0,0]) , end_point=np.array([3.5,0,0]))

        self.play(ShowCreationThenFadeOut(curvedArrow))
        self.wait(2)

https://youtu.be/5CjamCi1ld8

CurvedArrow


Mobject を回転する・角度をつける


45度角度をつけるには .rotate(PI / 4) をつける。

Mobject: 楕円

from manim import *

class EllipseExample(Scene):
    def construct(self):
        ellipse_1 = Ellipse(width=3.0, height=3.0, color = WHITE , fill_opacity=0.1)
        ellipse_2 = Ellipse(width=3.0, height=1.0, color=RED_C)
        
        self.play(Create(ellipse_1))
        self.play(Create(ellipse_2))
        self.wait(1)

2dだけど3dに見えなくもない。


Mobject 多角形

頂点の配列を読み込んで多角形を作る

from manim import *

class PolygonExample(Scene):
    def construct(self):
        position_list = [
            [1, 1, 0], 
            [0, 1, 0], 
            [1, 0, 0], 
            [-1, 0, 0], 
        ]
        Polygon_01 = Polygon(*position_list, color = PURE_GREEN, fill_opacity=0.1).rotate(PI / 4).scale(2)
        
        self.play(Create(Polygon_01))
        self.wait(1)
        


2次元平面の軸 (Axes)と 罫線 (NumberPlane), 関数 y=x+2


from manim import *

class Myscene(Scene):
    def construct(self):
        npl = NumberPlane(
            x_range=[-15, 15, 1],  
            y_range=[-15, 15, 1],  
            axis_config={"color": WHITE},  
        )
        
        axes = Axes(
            x_range=[-20, 20, 1],  
            y_range=[-20, 20, 1],  
            axis_config={"color": WHITE},
            y_length=npl.get_height(),
            x_length=npl.get_width(),
        )

        axes.add_coordinates()
        self.play(FadeIn(npl), run_time=1.0)
        self.play(Create(axes))
        self.wait(1)

        f = axes.plot(lambda x: x+2, color=LIGHT_PINK)

        self.play(Create(f))
        self.wait(1)


グラフを描写

軸と3つの関数を描写する。

from manim import *

class Myscene(Scene):
    CONFIG = {
        "x_min": -4,
        "x_max": 4,
        "y_min": -2,
        "y_max": 2,
        "graph_origin": ORIGIN,
        "function_color": WHITE,
        "axes_color": BLUE
    }

    def construct(self):
        #Make  graph
        axes = Axes(axis_config={'tip_shape': StealthTip})
        func_graph =  axes.plot(lambda x: 1 / (1 + np.exp(-x)), color=WHITE)
        graph_title = Tex("sigmoid function")
        graph_title.scale(1.5)
        graph_title.to_corner(UP + LEFT)

        func_graph_2 =  axes.plot(lambda x: np.tanh(x), color=PURE_GREEN)
        graph_title_2 = Tex("tanh function")
        graph_title_2.scale(1.5)
        graph_title_2.to_corner(UP + LEFT)

        func_graph_3 =  axes.plot(lambda x: np.maximum(0, x), color=YELLOW_C)
        graph_title_3 = Tex("ReLU function")
        graph_title_3.scale(1.5)
        graph_title_3.to_corner(UP + LEFT)


        #Display  graph
        self.add(axes)
        self.play(Create(func_graph))
        self.add(graph_title)
        self.wait(1)
        self.play(FadeOut(graph_title))
        self.play(Create(func_graph_2))
        self.add(graph_title_2)
        self.wait(1)
        self.play(FadeOut(graph_title_2))
        self.play(Create(func_graph_3))
        self.add(graph_title_3)
        self.wait(2)


色コード



Manim 色コード


YELLOW_C が鮮やかで見やすい。

PURE_GREEN は映画マトリックスのような色

コードブロック

manimで画面にプログラミングコードを表示させる方法

画像ファイル(png)を表示

画像を取り込みます。

from manim import *

class Images(Scene):
    def construct(self):
        img = ImageMobject('path_to_image_file.png')
        img.scale(2)  # Resize to be twice as big
        img.shift(1 * UP)  # Move the image

        self.add(img)  # Display the image
        self.play(img.animate.shift(RIGHT)) # Move the image to right

画像ファイルのキャッシュが残っていてなかなか切り替わらないことがあります。


(個人的に)よくあるミス

インデントのミス。特に下の部分

 def construct(self):

色を大文字にし忘れる。


プラグイン  manim-physics


Manim で物理シミュレーションをするためのプラグインです。重力やオブジェクトの衝突の演算ができます。


from manim import *

from manim_physics import *
# use a SpaceScene to utilize all specific rigid-mechanics methods
class TwoObjectsFalling(SpaceScene):
    def construct(self):
        circle = Circle().shift(UP)
        circle.set_fill(RED, 1)
        circle.shift(DOWN + RIGHT)

        rect = Square().shift(UP)
        rect.rotate(PI / 4)
        rect.set_fill(YELLOW_A, 1)
        rect.shift(UP * 2)
        rect.scale(0.5)

        ground = Line([-4, -3.5, 0], [4, -3.5, 0])
        wall1 = Line([-4, -3.5, 0], [-4, 3.5, 0])
        wall2 = Line([4, -3.5, 0], [4, 3.5, 0])
        walls = VGroup(ground, wall1, wall2)
        self.add(walls)

        self.play(
            DrawBorderThenFill(circle),
            DrawBorderThenFill(rect),
        )
        self.make_rigid_body(rect, circle)  # Mobjects will move with gravity
        self.make_static_body(walls)  # Mobjects will stay in place
        self.wait(5)
        # during wait time, the circle and rect would move according to the simulate updater


公式ドキュメント

パッケージの説明サイト


manim-physics のインストール

pip install manim-physics

でプラグインをインストールできます。

私はインストールがうまくできなかったため、Pythonのバージョンを3.10にしました。以下の手順でインストールできました。

  • 公式サイトから Python 3.10 をインストールする.

  • python -V
    でバージョンを確認する

  • python -m ensurepip
    で pip を使えるようにする

  • python - pip install --upgrade pip 
    で pipを最新のものにする

  • pip install manim
    でmanimをインストール

  • pip install manim-physics
    で manim-physics をインストール


3B1Bの動画のソースコード読む

github で 3b1bの動画に出てきたアニメーションのソースコードが閲覧できて大変参考になります。ManimCEでは動きませんが…


参考



この記事が気に入ったらサポートをしてみませんか?