Skip to content
62 changes: 62 additions & 0 deletions rolling-shutter-continuous.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#!/usr/bin/env python3

import tkinter as tk
import numpy as np
import time
from PIL import Image, ImageTk # pillow fork of PIL

root = tk.Tk()
label = tk.Label(root)
label.pack()
height = 600
x, y = np.ogrid[-height/2: height/2, -height/2: height/2]
plane = x + 1j * y
plane_abs = abs(plane)
propeller_angular_speed=1

frame_cache = {}
propeller_cache = {}
frame = 0

while True:
frame_base_angle = 2 * np.pi * ( propeller_angular_speed * frame / height + 1/12)
frame_base_angle %= np.pi/3
frame_base_angle = round(frame_base_angle, 3)
if frame_base_angle in frame_cache:
print('frame hit')
image = frame_cache[frame_base_angle]
time.sleep(1/500)
else:
print('frame miss')
bentprop = np.zeros_like(plane, dtype=np.bool)
for line in range(height):
line_base_angle = 2 * np.pi * ( propeller_angular_speed * (frame+line) / height + 1/12)
line_base_angle %= np.pi/3
line_base_angle = round(line_base_angle, 3)
if line_base_angle in propeller_cache:
propellors = propeller_cache[line_base_angle]
else:
propellors = np.zeros_like(plane, dtype=np.bool)
for blade in range(6):
this_angle = line_base_angle + blade * np.pi/3
phase = np.exp( 1j * this_angle)
ellipse = abs(plane - 0.49 * height * phase) + plane_abs
this_propellor = ellipse < 0.5 * height
propellors |= this_propellor
propeller_cache[line_base_angle] = propellors

bentprop[line] = propellors[line]
#greenbar = list(range(frame, min(frame + 3, height -3)))
colors = ("white","lightblue","red","green")
rgbcolors = np.array(list(map(root.winfo_rgb, colors))) / 256
composite = bentprop*2
#composite[greenbar] = 3
rgb = rgbcolors.astype(np.uint8)[composite]
image = ImageTk.PhotoImage(Image.fromarray(rgb, mode="RGB"))
frame_cache[frame_base_angle] = image
label.config(image=image)
root.update()
frame += 1

root.mainloop()

47 changes: 30 additions & 17 deletions rolling-shutter-tkinter.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,40 @@
height = 600
x, y = np.ogrid[-height/2: height/2, -height/2: height/2]
plane = x + 1j * y
plane_abs = abs(plane)
bentprop = np.zeros_like(plane, dtype=np.bool)
propeller_angular_speed=1
animation_speed=3

propeller_cache = {}

for frame in range(height):
backgnd = np.zeros_like(plane, dtype=np.uint8)
propellor = np.zeros_like(plane, dtype=np.bool)
angle = 2 * np.pi * ( frame / height + 1/12)
for blade in range(6):
phase = np.exp( 1j * (angle + blade * np.pi/3))
ellipse = abs(plane - 0.49 * height * phase) + abs(plane)
propellor |= ellipse < 0.5 * height
base_angle = 2 * np.pi * ( propeller_angular_speed * frame / height + 1/12)
base_angle %= np.pi/3
base_angle = round(base_angle, 3)
if base_angle in propeller_cache:
propellors = propeller_cache[base_angle]
else:
propellors = np.zeros_like(plane, dtype=np.bool)
for blade in range(6):
this_angle = base_angle + blade * np.pi/3
phase = np.exp( 1j * this_angle)
ellipse = abs(plane - 0.49 * height * phase) + plane_abs
this_propellor = ellipse < 0.5 * height
propellors |= this_propellor
propeller_cache[base_angle] = propellors

bentprop[frame] = propellor[frame]
greenbar = [f for f in range(frame, min(frame + 3, height -3))]
colors = ("white","lightblue","red","green")
rgbcolors = np.array(list(map(root.winfo_rgb, colors))) / 256
composite = np.maximum.reduce((backgnd, propellor*1, bentprop*2))
composite[greenbar] = 3
rgb = rgbcolors.astype(np.uint8)[composite]
image = ImageTk.PhotoImage(Image.fromarray(rgb, mode="RGB"))
label.config(image=image)
root.update()
bentprop[frame] = propellors[frame]
if frame % animation_speed == 0:
greenbar = list(range(frame, min(frame + 3, height -3)))
colors = ("white","lightblue","red","green")
rgbcolors = np.array(list(map(root.winfo_rgb, colors))) / 256
composite = np.maximum.reduce((propellors*1, bentprop*2))
composite[greenbar] = 3
rgb = rgbcolors.astype(np.uint8)[composite]
image = ImageTk.PhotoImage(Image.fromarray(rgb, mode="RGB"))
label.config(image=image)
root.update()

root.mainloop()

55 changes: 55 additions & 0 deletions rolling-shutter-vary_propeller_speed.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#!/usr/bin/env python3

import tkinter as tk
import numpy as np
import os
from PIL import Image, ImageTk # pillow fork of PIL

root = tk.Tk()
label = tk.Label(root)
label.pack()
height = 600
x, y = np.ogrid[-height/2: height/2, -height/2: height/2]
plane = x + 1j * y
plane_abs = abs(plane)
propeller_cache = {}
file_name_counter=0

for propeller_angular_speed in np.arange(0.03, 2.001, 0.03):
bentprop = np.zeros_like(plane, dtype=np.bool)

for frame in range(height):
base_angle = 2 * np.pi * ( propeller_angular_speed * frame / height + 1/12)
base_angle %= np.pi/3
base_angle = round(base_angle, 3)
if base_angle in propeller_cache:
propellors = propeller_cache[base_angle]
else:
propellors = np.zeros_like(plane, dtype=np.bool)
for blade in range(6):
this_angle = base_angle + blade * np.pi/3
phase = np.exp( 1j * this_angle)
ellipse = abs(plane - 0.49 * height * phase) + plane_abs
this_propellor = ellipse < 0.5 * height
propellors |= this_propellor
propeller_cache[base_angle] = propellors

bentprop[frame] = propellors[frame]
#greenbar = list(range(frame, min(frame + 3, height -3)))
colors = ("white","lightblue","red","green")
rgbcolors = np.array(list(map(root.winfo_rgb, colors))) / 256
composite = np.maximum.reduce((propellors*1, bentprop*2))
#composite[greenbar] = 3
rgb = rgbcolors.astype(np.uint8)[composite]
image = Image.fromarray(rgb, mode="RGB")
image.save('vary_speed/{}.png'.format(file_name_counter))
file_name_counter += 1
tk_image = ImageTk.PhotoImage(image)
label.config(image=tk_image)
root.update()

os.system("ffmpeg -y -loglevel warning -r 7 -i vary_speed/%d.png " +
"-framerate 25 -pix_fmt yuv420p vary_speed.mp4")

root.mainloop()