LoginSignup
8
9

More than 3 years have passed since last update.

【Python】Numpyでパーリンノイズ生成関数を無理やり短く書いた。

Last updated at Posted at 2020-03-23

はじめに

・パーリンノイズとは
パーリンノイズというのは程よい連続性と乱雑さがある使い勝手のいい(地形のランダム生成など)ノイズのことです。
詳しいことは他の人が書いているのでここではコードの紹介にとどめます。

書いた関数

perlin.py
#ライブラリのインポート
import numpy as np
import matplotlib.pyplot as plt

#線形補間と連続性を生み出す子たち
def fade(t):return 6*t**5-15*t**4+10*t**3
def lerp(a,b,t):return a+fade(t)*(b-a)

#本体
def perlin(r,seed=np.random.randint(0,100)):
    np.random.seed(seed)

    ri = np.floor(r).astype(int) #整数部、インデックスとして使用
    ri[0] -= ri[0].min()         #
    ri[1] -= ri[1].min()         #インデックスとして使用するための準備
    rf = np.array(r) % 1         #小数部
    g = 2 * np.random.rand(ri[0].max()+2,ri[1].max()+2,2) - 1 #格子点の勾配
    e = np.array([[[[0,0],[0,1],[1,0],[1,1]]]])                       #四隅
    er = (np.array([rf]).transpose(2,3,0,1) - e).reshape(r.shape[1],r.shape[2],4,1,2) #四隅の各点から見た位置ベクトル
    gr = np.r_["3,4,0",g[ri[0],ri[1]],g[ri[0],ri[1]+1],g[ri[0]+1,ri[1]],g[ri[0]+1,ri[1]+1]].transpose(0,1,3,2).reshape(r.shape[1],r.shape[2],4,2,1) #おなじみファンシーソートで四隅の勾配をまとめて内積計算できる形に加工
    p = (er@gr).reshape(r.shape[1],r.shape[2],4).transpose(2,0,1) #全点まとめて勾配との内積計算

    return lerp(lerp(p[0],p[2],rf[0]),lerp(p[1],p[3],rf[0]),rf[1]) #補間して返す

計算・プロット

perlin.py
N = 512
y = np.zeros((N,N))
for i in np.random.rand(1):         #パーリンノイズは周波数を変えて何枚か重ねると本領を発揮するらしいのでループして加算(好きなだけどうぞ)
    x = np.linspace(0,8*i,N)
    r = np.array(np.meshgrid(x,x))
    y += perlin(r)                  #meshgridの形(2,N,N)で渡す

plt.imshow(y)
plt.show()

結果:
perlin.png

その他 3Dプロット及び次元拡張版

まとめ

ループ使いたくなさが嵩じて書いたコードです。
途中、5階テンソルとか出てくるけどスッキリ書けると気持ちいいよね。

8
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
9