ランダムになんかロゴみたいなもの作る

ここ最近、輪郭形状解析の話をブログにまとめている中で、ランダムな形状の生成を試行していておもしろい模様生成の方法をたまたま見つけたのでその内容をメモがてら記事に残しておこうと思います。 具体的なコードと生成された模様は以下。ことの顛末としては、楕円フーリエ解析における係数からの輪郭再構築の過程を模してランダムな形状生成を試行錯誤していたのですが、そのとき、係数 a_n d_nを0にすると左右対称のパターンが生成され、なんかロゴマークみたいでおもしろいと思って記事にしました。関数のorder引数で重ね合わせる波の周波数の数を設定します。係数 b_n c_nを生成する乱数を正規分布ではなくて別の分布を使えばまた違ったパターンが見えるかもしれません。以下ではnumpy.random.normalnumpy.random.choiceを利用した場合を記載しています。

numpy.random.normal利用

import numpy as np
import matplotlib.pyplot as plt

def generate_random_contour(order=5):
    t = np.linspace(0, 1, num=1000)
    phi = (2 * np.pi * t) * np.arange(1, order+1).reshape((order, 1))
    
    b = np.random.normal(size=order)
    c = np.random.normal(size=order)
    
    x = np.dot(b, np.sin(phi))
    y = np.dot(c, np.cos(phi))

    return x, y

for order in [2, 3, 4, 5, 10, 20]:
    fig, axes = plt.subplots(10, 10, figsize=(15, 15))
    for ax in axes.ravel():
        x, y = generate_random_contour(order)
        ax.plot(x, y)
        ax.set_aspect(1)
        ax.axis('off')
    fig.suptitle(f"order={order}")
    plt.show()

normal, order=2

normal, order=3

normal, order=4

normal, order=5

normal, order=10

normal, order=20

numpy.random.choice利用

import numpy as np
import matplotlib.pyplot as plt

def generate_random_contour(order=5):
    t = np.linspace(0, 1, num=1000)
    phi = (2 * np.pi * t) * np.arange(1, order+1).reshape((order, 1))
    
    b = np.random.choice([0, 0.1, 0.2, 1], size=order, p=[0.4, 0.1, 0.2, 0.3])
    c = np.random.choice([0, 0.1, 0.2, 1], size=order, p=[0.4, 0.1, 0.2, 0.3])
    
    x = np.dot(b, np.sin(phi))
    y = np.dot(c, np.cos(phi))

    return x, y

for order in [2, 3, 4, 5, 10, 20]:
    fig, axes = plt.subplots(10, 10, figsize=(15, 15))
    for ax in axes.ravel():
        x, y = generate_random_contour(order)
        ax.plot(x, y)
        ax.set_aspect(1)
        ax.axis('off')
    fig.suptitle(f"order={order}")
    plt.show()

choice, order=2

choice, order=3

choice, order=4

choice, order=5

choice, order=10

choice, order=20