Skip to content

Instantly share code, notes, and snippets.

@setupminimal
Created January 13, 2018 16:10
Show Gist options
  • Save setupminimal/a53a703e43d2f06fb62de4747c12b75c to your computer and use it in GitHub Desktop.
Save setupminimal/a53a703e43d2f06fb62de4747c12b75c to your computer and use it in GitHub Desktop.
A program to make 'dueling watercolors'
import numpy
from PIL import Image
import random
import os
WIDTH, HEIGHT = 30, 30
SCALE = 10
randData = numpy.random.rand(WIDTH, HEIGHT, 3) * 255
match = numpy.random.rand(WIDTH, HEIGHT, 3) * 255
border = numpy.random.rand(WIDTH, 1, 3) * 0
blue = numpy.random.rand(WIDTH, 1, 3) * 0
red = numpy.random.rand(WIDTH, 1, 3) * 0
white = numpy.random.rand(WIDTH, 1, 3) * 0
blue[:, :] = (0, 0, 255)
red[:, :] = (255, 0, 0)
white[:, :] = 255
i = 0
def save(thinking=None, fade=0.5):
global i
order = None
if thinking is not None:
order = (randData, border, thinking * (1 - (fade*2 - 1)**2), border, match)
else:
order = (randData, border, border, border, match)
toShow = numpy.concatenate(order, axis = 1)
image = Image.fromarray(toShow.astype('uint8')).convert('RGBA')
image.resize((WIDTH*SCALE*2 + SCALE*3, HEIGHT*SCALE), resample = Image.NEAREST).save("images/{:0>6}.png".format(i))
i += 1
def sortish(p1, p2):
a, b = p1
x, y = p2
if -1 <= a - x <= 1 and -1 <= b - y <= 1:
return 0
else:
return (a - x) * (b - y)
pixels = [(a, b) for a in xrange(WIDTH) for b in xrange(HEIGHT)]
random.shuffle(pixels)
#pixels.sort(cmp=sortish)
brushes = [[(1, 0), (1, 1), (0, 1), (-1, 0), (-1, -1), (0, -1), (-1, 1), (1, -1)],
[(1, 0), (0, 1), (-1, 0), (0, -1)]]
def sstep(toChange, other):
orig = numpy.sum((toChange - other)**2)
for q in xrange(24):
if len(pixels) == 0:
break
best = pixels[0]
brush = brushes[0]
score = numpy.sum((toChange - other)**2)
for pixel in pixels:
a, b = pixel
for offsets in brushes:
trial = numpy.copy(toChange)
for da, db in offsets:
trial[(a + da) % WIDTH, (b + db) % HEIGHT] = (trial[a, b] + trial[(a + da * 2) % WIDTH, (b + db *2) % HEIGHT]) / 2
trialScore = numpy.sum((trial - other)**2)
if trialScore < score:
best = pixel
score = trialScore
brush = offsets
a, b = best
for da, db in brush:
toChange[(a + da) % WIDTH, (b + db) % HEIGHT] = (toChange[a, b] + toChange[(a + da * 2) % WIDTH, (b + db *2) % HEIGHT]) / 2
#pixels.remove(best)
save()
if orig < score + (25000/(30.0*30)*WIDTH*HEIGHT):
return True
return False
prev = 0
while True:
for q in range(6):
save(thinking=blue, fade=q/6.0)
f = sstep(randData, match)
for q in range(6):
save(thinking=red, fade=q/6.0)
g = sstep(match, randData)
if f and g:
print "Optimum"
break
if i >= 24*60*10:
print "Timeout"
break
score = numpy.sum((randData - match)**2)
print "{:0>6} - {} - {}".format(i, score, prev - score)
prev = score
for q in range(48):
save(thinking=white, fade=q/48.0)
os.system("ffmpeg -f image2 -r 12 -i \"images/%06d.png\" -vcodec vp9 -strict -2 -y movie.mp4")
os.system("rm images/*.png")
print "Done!"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment