Skip to content

Instantly share code, notes, and snippets.

@ruslangrimov
Last active October 27, 2017 12:19
Show Gist options
  • Save ruslangrimov/fda2073d3d37bfe75fa93994ab1a6d64 to your computer and use it in GitHub Desktop.
Save ruslangrimov/fda2073d3d37bfe75fa93994ab1a6d64 to your computer and use it in GitHub Desktop.
A python realization of the 2D Perlin noise
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm
from itertools import product, count
# generate uniform unit vectors
def generate_grid_vectors(n):
'Generates matrix NxN of unit length vectors'
v = np.random.uniform(-1, 1, (n, n, 2))
l = np.sqrt(v[:, :, 0] ** 2 + v[:, :, 1] ** 2).reshape(n, n, 1)
v /= l
return v
# quintic interpolation
def qz(t):
return t * t * t * (t * (t * 6 - 15) + 10)
# cubic interpolation
def cz(t):
return -2 * t * t * t + 3 * t * t
size = 100 # size of image size x size
ns = 10 # distance between nodes
nc = int(size / ns) # number of nodes
grid_size = int(size / ns + 1) # number of points in grid
v = generate_grid_vectors(grid_size)
# generate some constans in advance
ad, ar = np.arange(ns), np.arange(-ns, 0, 1)
# vectors from each of 4 nearest nodes to a point in the NSxNS patch
vd = np.zeros((4, ns, ns, 2))
for (l1, l2), c in zip(product((ad, ar), repeat=2), count()):
vd[c, :, :] = np.stack(np.meshgrid(l2, l1, indexing='ij'), axis=2)
# interpolation coefficients
d = qz(np.stack((np.zeros((2, ns, ns)),
np.stack(np.meshgrid(ad, ad, indexing='ij')))) / ns)
d[0] = 1 - d[1]
# make an empy matrix for the image
img = np.zeros((size, size))
# reshape for convenience
t = img.reshape(nc, ns, nc, ns)
def td(v1, v2):
return np.tensordot(v1, v2, axes=([0], [2]))
# fill the image with Perlin noise
for i, j in product(np.arange(nc), repeat=2): # loop through the grid
# calculate values for a NSxNS patch at a time
n0 = td(v[i, j], vd[0])
n1 = td(v[i + 1, j], vd[1])
j0 = d[0, 0] * n0 + d[1, 0] * n1
n0 = td(v[i, j + 1], vd[2])
n1 = td(v[i + 1, j + 1], vd[3])
j1 = d[0, 0] * n0 + d[1, 0] * n1
t[i, :, j, :] = d[0, 1] * j0 + d[1, 1] * j1
plt.imshow(img, cmap=cm.gray)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment