Creating Complex Images with Math (32bit - 48bit)
It struck me that we could use CUPY to generate extremely complex images with a scalable "recipe" the complexity of which is beyond non synthetic images.
Currently the code does not save the scalable recipe but maybe some math wizard out there could figure out a scaled loss to train high frequency detail at low scale.
The current code is 32bit, but can easily be changed to int16 per channel creating 48bit images.
import cupy as cp
import cv2
import random
import os
W,H=4096,4096
N=W*H
OUTPUT_DIR="gpu_output"
os.makedirs(OUTPUT_DIR,exist_ok=True)
BATCH_PER_FUNCTION=2
def save_png_8bit(name,img_gpu):
cv2.imwrite(name,cp.asnumpy(img_gpu).astype('uint8')[:,:,::-1],[cv2.IMWRITE_PNG_COMPRESSION,0])
def normalize_field(f):
return (f-f.min())/(f.max()-f.min())
def apply_gradient(f,intensity=1.0):
rotation=random.random()
return (f+rotation*intensity)%1.0
def minimal_gradient():
y,x=cp.meshgrid(cp.arange(H),cp.arange(W),indexing='ij')
return normalize_field(x+y*W)
def sacred_geometry():
y,x=cp.meshgrid(cp.arange(H),cp.arange(W),indexing='ij')
dx,dy=x-W//2,y-H//2
r=cp.sqrt(dx**2+dy**2)
theta=cp.arctan2(dy,dx)
return normalize_field(cp.sin(theta*8)+cp.cos(r*0.01))
def nebula():
y,x=cp.meshgrid(cp.arange(H),cp.arange(W),indexing='ij')
wx,wy=x+400*cp.sin(y*0.003),y+400*cp.cos(x*0.003)
return normalize_field(cp.sin(wx*0.002)+cp.cos(wy*0.002)+cp.sin((wx+wy)*0.001))
def marble():
y,x=cp.meshgrid(cp.arange(H),cp.arange(W),indexing='ij')
return normalize_field(cp.sin(x*0.02+20*cp.sin(y*0.01)))
def oil_paint():
y,x=cp.meshgrid(cp.arange(H),cp.arange(W),indexing='ij')
return normalize_field(cp.sin(x*0.005)*cp.cos(y*0.005)+cp.sin((x+y)*0.003))
def psychedelic():
y,x=cp.meshgrid(cp.arange(H),cp.arange(W),indexing='ij')
return normalize_field(cp.sin(x*0.01)+cp.sin(y*0.013)+cp.sin((x+y)*0.007))
def fluid_dynamics():
y,x=cp.meshgrid(cp.arange(H),cp.arange(W),indexing='ij')
dx,dy=x-W//2,y-H//2
return normalize_field(cp.sin(cp.arctan2(dy,dx)*4+cp.sqrt(dx**2+dy**2)*0.01))
styles={
"minimal":minimal_gradient,
"sacred":sacred_geometry,
"nebula":nebula,
"marble":marble,
"oil":oil_paint,
"psychedelic":psychedelic,
"fluid":fluid_dynamics,
}
compatible_sets=[["minimal","sacred"],["nebula","fluid"],["marble","oil"],["psychedelic","sacred"]]
def generate_unique_image(name,field_funcs,counter):
channels=[]
for func in field_funcs:
f=apply_gradient(func(),intensity=random.uniform(0.2,0.8))
f+=cp.random.random(f.shape)*1e-6
order=cp.argsort(f.flatten())
vals=cp.arange(256,dtype=cp.uint8)
repeats=N//256
channel=cp.repeat(vals,repeats) if repeats>1 else vals
channel=cp.resize(channel,(N,))
pix=cp.empty(N,dtype=cp.uint8)
pix[order]=channel
channels.append(pix.reshape(H,W))
rgb=cp.stack(channels,axis=2)
save_png_8bit(os.path.join(OUTPUT_DIR,f"{name}_{counter:06d}.png"),rgb)
del channels,rgb,f,order,pix
cp.get_default_memory_pool().free_all_blocks()
def weighted_mix(counter):
num_effects=random.randint(2,3)
chosen=random.sample(list(styles.keys()),num_effects)
weights=cp.random.dirichlet(cp.ones(num_effects))
channels=[]
for i in range(3):
combined=cp.zeros((H,W),dtype=cp.float32)
for w,name in zip(weights,chosen):
f=apply_gradient(styles[name](),intensity=random.uniform(0.2,0.8))
combined+=f*w
combined+=cp.random.random(combined.shape)*1e-6
order=cp.argsort(combined.flatten())
vals=cp.arange(256,dtype=cp.uint8)
repeats=N//256
channel=cp.repeat(vals,repeats) if repeats>1 else vals
channel=cp.resize(channel,(N,))
pix=cp.empty(N,dtype=cp.uint8)
pix[order]=channel
channels.append(pix.reshape(H,W))
rgb=cp.stack(channels,axis=2)
save_png_8bit(os.path.join(OUTPUT_DIR,f"mix_{counter:06d}.png"),rgb)
del channels,rgb,combined,order,pix
cp.get_default_memory_pool().free_all_blocks()
counter=0
for name,func in styles.items():
for _ in range(BATCH_PER_FUNCTION):
generate_unique_image(name,[func,func,func],counter)
counter+=1
try:
while True:
weighted_mix(counter)
counter+=1
except KeyboardInterrupt:
print("Stopped by user.") 


