Categories
Uncategorized

Random Bézier Walk in a Random Neural Network

The video above was generated using neuralart.

The neural network takes position coordinates, distance to origin, and a vector z as inputs, and outputs a corresponding pixel intensity. The weights are randomly initialized. This configuration is described in more detail in the following blog posts and pages from studio otoro.

The video frames are generated by transitioning the z input. In an earlier experiment, I tried varying z by transitioning along a straight line. The corresponding video is included in an earlier post. I also tried using a random walk, but found that there was too much back-and-forth motion this way.

The video above transitions z by walking along randomly generated cubic Bézier curves. The curves are connected, and the first handle of each curve has the same slope as the last handle of the preceding curve, in order to achieve smooth transitions across curves. Binary search is used so that the distance of each step along the curve is approximately fixed.

Here’s the source code.


#!/usr/bin/env python
from __future__ import print_function
# Images can be converted to video with ffmpeg.
# > ffmpeg -pattern_type glob \
# -i "*.png" \
# -vcodec libx264 \
# output.avi
import os
import sys
from PIL import Image
import neuralart
import numpy as np
RENDER_SEED = 10
Z_SEED = 0
DEVICE = "cpu" # 'cpu' for CPU, 'cuda' for GPU
ITERATIONS = 10000
MIN_STEP_SIZE = .005
MAX_STEP_SIZE = .006
XRES = 2048
YRES = 2048
XLIM = np.array([-1.0, 1.0])
YLIM = XLIM * (float(YRES) / XRES)
DEPTH = 9
CHANNELS = 1
OUTPUT_STD = 1.5
HIDDEN_STD = 1.1
Z_DIMS = 4
Z_RANGE = (-1, 1)
RADIUS=True
if len(sys.argv) != 2:
sys.stderr.write("Usage: {} DIRECTORY\n".format(sys.argv[0]))
sys.exit(1)
directory = sys.argv[1]
if not os.path.exists(directory):
os.makedirs(directory)
rng = np.random.RandomState(seed=Z_SEED)
zfill = len(str(ITERATIONS – 1))
M = np.array([
[-1, 3, -3, 1],
[ 3, -6, 3, 0],
[-3, 3, 0, 0],
[ 1, 0, 0, 0]
])
P0 = rng.uniform(*Z_RANGE, size=Z_DIMS)
P1 = rng.uniform(*Z_RANGE, size=Z_DIMS)
P2 = rng.uniform(*Z_RANGE, size=Z_DIMS)
P3 = rng.uniform(*Z_RANGE, size=Z_DIMS)
count = 0
while count < ITERATIONS:
P0 = P3
P1 = 2 * P3 – P2
P2 = rng.uniform(*Z_RANGE, size=Z_DIMS)
P3 = rng.uniform(*Z_RANGE, size=Z_DIMS)
pos = P0
lo = 0.0
hi = 1.0
while np.linalg.norm(P3 – pos) > MIN_STEP_SIZE:
if count >= ITERATIONS:
break
t = (lo + hi) / 2.0
P = np.vstack((P0, P1, P2, P3)).T
C = P.dot(M).dot(np.array([t ** 3, t ** 2, t, 1]))
distance = np.linalg.norm(C – pos)
if distance < MIN_STEP_SIZE:
lo = t
continue
elif distance > MAX_STEP_SIZE:
hi = t
continue
pos = C
result = neuralart.render(
depth=DEPTH,
xres=XRES,
yres=YRES,
xlim=XLIM,
ylim=YLIM,
seed=RENDER_SEED,
channels=CHANNELS,
output_std=OUTPUT_STD,
hidden_std=HIDDEN_STD,
radius=RADIUS,
z=C,
device=DEVICE
)
file = os.path.join(directory, str(count).zfill(zfill) + ".png")
im = Image.fromarray(result.squeeze())
im.save(file, "png")
count += 1
lo = t
hi = 1.0

Leave a Reply

Your email address will not be published. Required fields are marked *