Browse Source

added faces.py

master
Fr3deric 6 years ago
parent
commit
815edba13e
  1. 150
      generators/faces.py

150
generators/faces.py

@ -0,0 +1,150 @@ @@ -0,0 +1,150 @@
#!/usr/bin/env python3
import sys
import random
import argparse
import collections
import blup.frame
import blup.output
import blup.animation
import blup.writebml
import colorsys
WIDTH = 22
HEIGHT = 16
DEPTH = 256
SMILEYSIZE = 5
Point = collections.namedtuple('Point', ['x', 'y'])
def convert_color(c):
return list(map(lambda x: int(round(x*(DEPTH-1))), c))
def expand(somepoints, allpoints):
todo = set(somepoints)
ret = set(somepoints)
while len(todo) > 0:
p = todo.pop()
ret.add(p)
adj = { Point(p.x + x, p.y + y) for x in [-1,0,1] for y in [-1,0,1] \
if abs(x) + abs(y) == 1 and p.x + x in range(0, SMILEYSIZE) \
and p.y + y in range(0, SMILEYSIZE) }
adj = (allpoints - ret).intersection(adj)
todo = todo.union(adj)
return ret
def gen_face_shape():
while True:
i = random.randint(0, 2**(SMILEYSIZE * (SMILEYSIZE//2 + 1)))
lpoints = { Point(x, y) for x in range(0, SMILEYSIZE // 2) \
for y in range(SMILEYSIZE) \
if i & 2**(x*SMILEYSIZE + y) > 0 }
mpoints = { Point(SMILEYSIZE//2, y) for y in range(SMILEYSIZE) \
if i & 2**((SMILEYSIZE//2) * SMILEYSIZE + y) > 0 }
rpoints = { Point(SMILEYSIZE - x - 1, y) \
for x in range(0, SMILEYSIZE // 2) \
for y in range(SMILEYSIZE) \
if i & 2**(x*SMILEYSIZE + y) > 0 }
points = set.union(lpoints, mpoints, rpoints)
eyes = { p for p in points if p.y < SMILEYSIZE // 2 and \
p.x != SMILEYSIZE // 2 }
nose = { p for p in points if p.y >= SMILEYSIZE // 3 and \
p.y < SMILEYSIZE // 2 + 1 and p.x == SMILEYSIZE//2 }
mouth = { p for p in points if p.y > SMILEYSIZE // 2 }
nose = expand(nose, points)
mouth = expand(mouth, points)
face = True
if len(eyes.intersection(nose)) > 0:
face = False
if len(eyes.intersection(mouth)) > 0:
face = False
if len(nose.intersection(mouth)) > 0:
face = False
if len(points - eyes - nose - mouth) > 0:
face = False
if len(eyes) == 0:
face = False
if len(mouth) == 0:
face = False
if len(nose) > 0:
nosey = set(map(lambda p: p.y, nose))
if min(nosey) < SMILEYSIZE//3:
face = False
if face:
return points
class Face:
def __init__(self, pos):
self.pos = pos
self.shape = gen_face_shape()
self.lifetime = 0.7
self.fadetime = 0.1 + random.random() / 10
self.age = 0
self.done = False
self.hue = random.random()
def update(self, dt):
self.age += dt
if self.age > self.lifetime:
self.done = True
def draw(self, frame):
if self.done:
return
if self.age < self.fadetime:
v = self.age / self.fadetime
elif self.age > self.lifetime - self.fadetime:
v = (self.lifetime-self.age) / self.fadetime
else:
v = 1
for p in self.shape:
frame.setPixel(
p.x + self.pos.x,
p.y + self.pos.y,
convert_color(colorsys.hsv_to_rgb(self.hue, 1, v))
)
def get_face_pos():
x = random.randint(0, WIDTH - SMILEYSIZE)
y = random.randint(0, HEIGHT - SMILEYSIZE)
return Point(x, y)
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Generate Face animations')
parser.add_argument('-d', '--delay', type=int, default=50)
parser.add_argument('-t', '--time', type=int, default=15)
parser.add_argument('output_file')
args = parser.parse_args()
dim = blup.frame.FrameDimension(WIDTH, HEIGHT, DEPTH, 3)
anim = blup.animation.Animation(dim)
anim.tags['description'] = ' '.join(sys.argv)
f = Face(get_face_pos())
t = 0
dt = args.delay / 1000
while f is not None:
t += dt
frame = blup.animation.AnimationFrame(dim, args.delay)
f.update(dt)
f.draw(frame)
if f.done:
if t < args.time:
f = Face(get_face_pos())
else:
f = None
anim.addFrame(frame)
blup.writebml.writeBml(anim, args.output_file)
Loading…
Cancel
Save