-
Notifications
You must be signed in to change notification settings - Fork 0
/
App.py
134 lines (108 loc) · 3.86 KB
/
App.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
from tkinter import *
from tkinter.ttk import Style
import cv2
from PokikiAPI import Pokiki
from PIL import Image, ImageTk
from tkinter import filedialog as fd
from threading import Thread
root = Tk()
root.title("Mosaic Video Maker")
root.resizable(False, False)
style = Style(root)
style.theme_use('clam')
# Change this to 0 if your camera doesn't open
capture = cv2.VideoCapture(0)
CANVAS_W, CANVAS_H = 1024, 576
CANVAS_H_W_RATIO = CANVAS_H / CANVAS_W
########## UI VARIABLES ############
# Tkinter functions work on the main thread
split_x = IntVar(root, value=30)
split_y = IntVar(root, value=20)
# Atomic vars to share data between threads
atom_split_x = split_x.get()
atom_split_y = split_y.get()
atom_image = None
resize_canvas = False
def set_split_x(x):
global atom_split_x
split_x.set(x)
atom_split_x = int(x)
def set_split_y(y):
global atom_split_y
split_y.set(y)
atom_split_y = int(y)
def open_file():
global capture, resize_canvas
filename: str = fd.askopenfilename()
# List of video file extensions
valid_extensions = ["mp4", "mov", "ogg", "wmv", "avi", "flv", "gif"]
if filename:
# Get opened file extension
ext = filename.split(".").pop()
if ext.lower() in valid_extensions:
capture = cv2.VideoCapture(filename)
resize_canvas = True
def open_camera():
global capture, resize_canvas
capture = cv2.VideoCapture(0)
resize_canvas = True
if __name__ == '__main__':
########## INSTANCES ############
pokiki = Pokiki()
########## UI SETUP ############
canvas = Canvas(root, width=CANVAS_W, height=CANVAS_H)
canvas.pack()
options_frame = LabelFrame(root, text="Options")
options_frame.pack(fill="both", expand="yes")
controls_frame = Frame(options_frame)
controls_frame.pack(side=LEFT)
label = Label(controls_frame, text="Split X")
x_scale = Scale(controls_frame, from_=5, to=250, orient=HORIZONTAL,
length=250, resolution=5, command=set_split_x, var=split_x)
label.pack()
x_scale.pack()
label = Label(controls_frame, text="Split Y")
y_scale = Scale(controls_frame, from_=5, to=250, orient=HORIZONTAL,
length=250, resolution=5, command=set_split_y, var=split_y)
label.pack()
y_scale.pack()
file_button = Button(options_frame, text="Open File", command=open_file)
file_button.pack(side=RIGHT)
camera_button = Button(options_frame, text="Use Camera", command=open_camera)
camera_button.pack(side=RIGHT)
########## VISUALIZATION LOOP ############
running = True
def run_video():
global atom_image, CANVAS_W, resize_canvas
while running:
# Read the next frame
retval, frame = capture.read()
# Check if there is a valid frame.
if not retval:
continue
if resize_canvas:
_, frame_w, _ = frame.shape
CANVAS_W = int(frame_w*CANVAS_H_W_RATIO)
resize_canvas = True
# Convert the original image to tiled
tile_img = pokiki.convertFromImage(frame, atom_split_x, atom_split_y)
tile_img = cv2.resize(tile_img, (CANVAS_W, CANVAS_H))
# Display the resulting frame
atom_image = tile_img
video_thread = Thread(target=run_video, args=())
video_thread.start()
def exit_app():
global running
running = False
video_thread.join()
root.destroy()
root.protocol("WM_DELETE_WINDOW", exit_app)
while running:
root.update_idletasks()
# Display the resulting frame
if atom_image is not None:
canvas.configure(width=CANVAS_W)
img = ImageTk.PhotoImage(image=Image.fromarray(atom_image))
canvas.create_image(0,0, anchor="nw", image=img)
atom_image = None
root.update()