Generate moiré patterns from simple array ops.
All of the pattern generation logic is located in a single function, moire_pattern().
nint: Size of the image width and height in pixels (n x n).kfloat: Scaling factor affecting pattern frequency and density.kernel{'elliptical', 'hexagonal', 'radial', 'spiral', 'square', 'star', 'wave'} | Callable[[ndarray, ndarray], ndarray]: Determines pattern shape. Can be the name of a preset kernel or a callable object which accepts two arrays and returns an array.colorizebool:Falsefor greyscale (default),Truefor RGB.
The global KERNELS dict provides a namespace for preset kernel functions.
'elliptical''hexagonal''radial''spiral''square''star''wave'
The presets offer quite a bit when it comes to experimentation.
This is especially true if one were to chain them together using higher-order lambdas, such as in the following code:
from moire import moire_pattern, KERNELS
from PIL import Image
# using the product of two other patterns as the pattern
kernel_chain = lambda x, y: KERNELS['hexagonal'](x, y) * KERNELS['star'](x, y)
output = moire_pattern(m=999, k=777, kernel=kernel_chain, colorize=True)
Image.fromarray(output).show()... which creates this output image:
Using the 'spiral' preset kernel:
from moire import moire_pattern
from PIL import Image
output = moire_pattern(n=500, k=100.0, kernel='spiral')
Image.fromarray(output).show()Using a custom kernel, with colorized output:
import numpy as np
from moire import moire_pattern
from PIL import Image
def custom_kernel(x, y):
return np.sin(x) * np.cos(y)
output = moire_pattern(n=500, k=100.0, kernel=custom_kernel, colorize=True)
Image.fromarray(output).show()- Circle Squares fractal - the base implementation is pretty much directly from this. also very cool site, shoutout Paul Bourke fr
- 黎曼ζ函數 - mathematics wikipedia