turing.py 1.71 KB
Newer Older
1
'''
2 3
Multiscale Turing Patterns generator
====================================
4

5 6 7 8
Inspired by http://www.jonathanmccabe.com/Cyclic_Symmetric_Multi-Scale_Turing_Patterns.pdf
'''

import numpy as np
9 10
import cv2
import cv2.cv as cv
11
from common import draw_str
12 13 14 15 16 17 18 19
import getopt, sys
from itertools import count

help_message = '''
USAGE: turing.py [-o <output.avi>]

Press ESC to stop.
'''
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62

if __name__ == '__main__':
    print help_message

    w, h = 512, 512

    args, args_list = getopt.getopt(sys.argv[1:], 'o:', [])
    args = dict(args)
    out = None
    if '-o' in args:
        fn = args['-o']
        out = cv2.VideoWriter(args['-o'], cv.CV_FOURCC(*'DIB '), 30.0, (w, h), False)
        print 'writing %s ...' % fn

    a = np.zeros((h, w), np.float32)
    cv2.randu(a, np.array([0]), np.array([1]))

    def process_scale(a_lods, lod):
        d = a_lods[lod] - cv2.pyrUp(a_lods[lod+1])
        for i in xrange(lod):
            d = cv2.pyrUp(d)
        v = cv2.GaussianBlur(d*d, (3, 3), 0)
        return np.sign(d), v
        
    scale_num = 6
    for frame_i in count():
        a_lods = [a]
        for i in xrange(scale_num):
            a_lods.append(cv2.pyrDown(a_lods[-1])) 
        ms, vs = [], []
        for i in xrange(1, scale_num):
            m, v = process_scale(a_lods, i)
            ms.append(m)
            vs.append(v)
        mi = np.argmin(vs, 0)
        a += np.choose(mi, ms) * 0.025
        a = (a-a.min()) / a.ptp()

        if out:
            out.write(a)
        vis = a.copy()
        draw_str(vis, (20, 20), 'frame %d' % frame_i)
        cv2.imshow('a', vis)
63
        if 0xFF & cv2.waitKey(5) == 27:
64
            break
65
    cv2.destroyAllWindows()