-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathopencvTkinterTemplate.py
129 lines (93 loc) · 3.35 KB
/
opencvTkinterTemplate.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
import time
import sys
# Tkinter selector
if sys.version_info[0] < 3:
from Tkinter import *
import Tkinter as tk
else:
from tkinter import *
import tkinter as tk
import numpy as np
import cv2
from PIL import Image, ImageTk
def opencvToTk(frame):
"""Convert an opencv image to a tkinter image, to display in canvas."""
rgb_image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
pil_img = Image.fromarray(rgb_image)
tk_image = ImageTk.PhotoImage(image=pil_img)
return tk_image
def mousePressed(event, data):
pass
def keyPressed(event, data):
if event.keysym == "q":
data.root.destroy()
pass
def timerFired(data):
pass
def cameraFired(data):
"""Called whenever new camera frames are available.
Camera frame is available in data.frame. You could, for example, blur the
image, and then store that back in data. Then, in drawCamera, draw the
blurred frame (or choose not to).
"""
# For example, you can blur the image.
data.frame = cv2.GaussianBlur(data.frame, (11, 11), 0)
def drawCamera(canvas, data):
data.tk_image = opencvToTk(data.frame)
canvas.create_image(data.width / 2, data.height / 2, image=data.tk_image)
def redrawAll(canvas, data):
drawCamera(canvas, data)
def run(width=300, height=300):
class Struct(object): pass
data = Struct()
data.width = width
data.height = height
data.camera_index = 0
data.timer_delay = 100 # ms
data.redraw_delay = 50 # ms
# Initialize the webcams
camera = cv2.VideoCapture(data.camera_index)
data.camera = camera
# Make tkinter window and canvas
data.root = Tk()
canvas = Canvas(data.root, width=data.width, height=data.height)
canvas.pack()
# Basic bindings. Note that only timer events will redraw.
data.root.bind("<Button-1>", lambda event: mousePressed(event, data))
data.root.bind("<Key>", lambda event: keyPressed(event, data))
# Timer fired needs a wrapper. This is for periodic events.
def timerFiredWrapper(data):
# Ensuring that the code runs at roughly the right periodicity
start = time.time()
timerFired(data)
end = time.time()
diff_ms = (end - start) * 1000
delay = int(max(data.timer_delay - diff_ms, 0))
data.root.after(delay, lambda: timerFiredWrapper(data))
# Wait a timer delay before beginning, to allow everything else to
# initialize first.
data.root.after(data.timer_delay,
lambda: timerFiredWrapper(data))
def redrawAllWrapper(canvas, data):
start = time.time()
# Get the camera frame and get it processed.
_, data.frame = data.camera.read()
cameraFired(data)
# Redrawing code
canvas.delete(ALL)
redrawAll(canvas, data)
# Calculate delay accordingly
end = time.time()
diff_ms = (end - start) * 1000
# Have at least a 5ms delay between redraw. Ideally higher is better.
delay = int(max(data.redraw_delay - diff_ms, 5))
data.root.after(delay, lambda: redrawAllWrapper(canvas, data))
# Start drawing immediately
data.root.after(0, lambda: redrawAllWrapper(canvas, data))
# Loop tkinter
data.root.mainloop()
# Once the loop is done, release the camera.
print("Releasing camera!")
data.camera.release()
if __name__ == "__main__":
run(800, 800)