1 #!/usr/bin/env python 2 3 ''' 4 Multiscale Turing Patterns generator 5 ==================================== 6 7 Inspired by http://www.jonathanmccabe.com/Cyclic_Symmetric_Multi-Scale_Turing_Patterns.pdf 8 ''' 9 10 import numpy as np 11 import cv2 12 from common import draw_str 13 import getopt, sys 14 from itertools import count 15 16 help_message = ''' 17 USAGE: turing.py [-o <output.avi>] 18 19 Press ESC to stop. 20 ''' 21 22 if __name__ == '__main__': 23 print help_message 24 25 w, h = 512, 512 26 27 args, args_list = getopt.getopt(sys.argv[1:], 'o:', []) 28 args = dict(args) 29 out = None 30 if '-o' in args: 31 fn = args['-o'] 32 out = cv2.VideoWriter(args['-o'], cv2.VideoWriter_fourcc(*'DIB '), 30.0, (w, h), False) 33 print 'writing %s ...' % fn 34 35 a = np.zeros((h, w), np.float32) 36 cv2.randu(a, np.array([0]), np.array([1])) 37 38 def process_scale(a_lods, lod): 39 d = a_lods[lod] - cv2.pyrUp(a_lods[lod+1]) 40 for i in xrange(lod): 41 d = cv2.pyrUp(d) 42 v = cv2.GaussianBlur(d*d, (3, 3), 0) 43 return np.sign(d), v 44 45 scale_num = 6 46 for frame_i in count(): 47 a_lods = [a] 48 for i in xrange(scale_num): 49 a_lods.append(cv2.pyrDown(a_lods[-1])) 50 ms, vs = [], [] 51 for i in xrange(1, scale_num): 52 m, v = process_scale(a_lods, i) 53 ms.append(m) 54 vs.append(v) 55 mi = np.argmin(vs, 0) 56 a += np.choose(mi, ms) * 0.025 57 a = (a-a.min()) / a.ptp() 58 59 if out: 60 out.write(a) 61 vis = a.copy() 62 draw_str(vis, (20, 20), 'frame %d' % frame_i) 63 cv2.imshow('a', vis) 64 if 0xFF & cv2.waitKey(5) == 27: 65 break 66 cv2.destroyAllWindows() 67