-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathmain.py
220 lines (177 loc) · 6.72 KB
/
main.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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
import config
import cv2
import os
import sys
from render import process
debug = config.DEBUG
bg_type = 'image'
if config.CAMERA == 'pi':
from videoPiStream import VideoPiStream
else:
from videoCamStream import VideoCamStream
def on_frame_buffer(bg_file):
"""
Display real time chroma key on the frame buffer through Pygame.
:return:
"""
from render import framebuffer
global debug
py_game_inst = framebuffer.PyGameRender(config.SIZE)
background = _load_background(bg_file)
video = _start_camera()
frame_count = 0
fps = None
if debug:
from tests import fps
fps = fps.FPS(file=os.path.join(config.DIR, config.LOG)).start()
while True:
# grab the frame from the threaded video stream
foreground = video.read()
# do not continue if no frame from cam yet
# and prevent too much processing...
frame_count += 1
if foreground is None or frame_count % 40 != 0:
continue
frame_count = 0
# do the chroma key
frames = process.subtract(foreground, background)
# Output to Pygame (frame buffer)
stop = py_game_inst.render(cv2.add(frames['bg_mask'], frames['fg_mask']))
# update the FPS counter
if debug:
fps.update()
if stop:
if debug:
fps.stop()
break
# close
py_game_inst.stop()
video.stop()
sys.exit()
def in_window(bg_file):
"""
Display real time chroma key in a X server window through OpenCV.
:return:
"""
global debug, bg_type
# cv2.startWindowThread() # This bugs: glib-gobject-critical ** g_object_unref assertion
cv2.namedWindow(config.WINDOW_NAME, flags=cv2.WINDOW_AUTOSIZE)
# todo full screen
# cv2.namedWindow(config.WINDOW_NAME, flags=cv2.WND_PROP_FULLSCREEN)
# cv2.setWindowProperty(config.WINDOW_NAME, cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)
# init cam
video = _start_camera()
# get background
bg = _load_background(bg_file)
frame_count = 0
fps = None
if debug:
from tests import fps
fps = fps.FPS().start()
# main loop
while True:
# prevent too much processing...
frame_count += 1
if frame_count % 40 != 0:
continue
frame_count = 0
# background video ready?
if bg_type == 'video' and not bg.stream.isOpened():
continue
# grab the frame from the threaded video stream
foreground = video.read()
# do not continue if no frame from cam yet
if foreground is None:
continue
# read background frame
background = bg.read() if bg_type == 'video' else bg
# if end of background video, loop back
# todo use CV_CAP_PROP_FRAME_COUNT & CV_CAP_PROP_POS_FRAMES
if bg_type == 'video' and background is None:
print("The sea ends here\n")
bg.stream.set(cv2.CAP_PROP_POS_FRAMES, 0)
continue
# let's do this in VideoCamStream since PiCamera has an option for it
# foreground = cv2.flip(foreground, 1)
# do this outside the loop (for images)
# background = cv2.resize(background, config.SIZE)
# not needed: video is already resized in class
# foreground = cv2.resize(foreground, config.SIZE)
if debug:
cv2.putText(foreground, ' H S V', (10, 15), cv2.FONT_HERSHEY_SIMPLEX, 0.4, 0, 1)
cv2.putText(foreground, 'LOWER: %s' % (config.COLOUR_IN), (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.4, 0, 1)
cv2.putText(foreground, 'UPPER: %s' % (config.COLOUR_OUT), (10, 50), cv2.FONT_HERSHEY_SIMPLEX, 0.4, 0, 1)
# do the chroma key
frames = process.subtract(foreground, background)
# CV2 output: composite both streams
cv2.imshow(config.WINDOW_NAME, cv2.add(frames['bg_mask'], frames['fg_mask']))
# update the FPS counter
if debug:
fps.update()
# interrupt
key = cv2.waitKey(10) & 0xFF
if key in range(ord('A'), ord('z')):
if key == ord('q'):
if debug:
fps.stop()
break
elif key == ord('D'):
debug = not debug
elif key == ord('e') and 0 < config.COLOUR_IN[0]:
config.COLOUR_IN[0] -= 1
elif key == ord('r') and config.COLOUR_IN[0] < config.COLOUR_OUT[0]:
config.COLOUR_IN[0] += 1
elif key == ord('t') and config.COLOUR_IN[0] < config.COLOUR_OUT[0]:
config.COLOUR_OUT[0] -= 1
elif key == ord('y') and config.COLOUR_OUT[0] < 179:
config.COLOUR_OUT[0] += 1
elif key == ord('d') and 0 < config.COLOUR_IN[1]:
config.COLOUR_IN[1] -= 1
elif key == ord('f') and config.COLOUR_IN[1] < config.COLOUR_OUT[1]:
config.COLOUR_IN[1] += 1
elif key == ord('g') and config.COLOUR_IN[1] < config.COLOUR_OUT[1]:
config.COLOUR_OUT[1] -= 1
elif key == ord('h') and config.COLOUR_OUT[1] < 255:
config.COLOUR_OUT[1] += 1
elif key == ord('c') and 0 < config.COLOUR_IN[2]:
config.COLOUR_IN[2] -= 1
elif key == ord('v') and config.COLOUR_IN[2] < config.COLOUR_OUT[2]:
config.COLOUR_IN[2] += 1
elif key == ord('b') and config.COLOUR_IN[2] < config.COLOUR_OUT[2]:
config.COLOUR_OUT[2] -= 1
elif key == ord('n') and config.COLOUR_OUT[2] < 255:
config.COLOUR_OUT[2] += 1
#if debug:
# print 'LOWER: %s UPPER: %s' % (config.COLOUR_IN, config.COLOUR_OUT)
video.stop()
cv2.destroyAllWindows()
sys.exit()
def _load_background(file):
"""
Decide what to load as background: an image or a video
:param file:
:return:
"""
global debug, bg_type
if file.lower().endswith(('.mov', '.mp4')):
bg_type = 'video'
return VideoCamStream(resolution=config.SIZE, frame_rate=config.FRAMERATE, src=file).start()
# let's assume it's an image file
bg_type = 'image'
bg_img = cv2.imread(file)
return cv2.resize(bg_img, config.SIZE)
def _start_camera():
"""
Start PiCamera or web cam based on /config.py params
:return:
"""
if config.CAMERA == 'pi':
return VideoPiStream(resolution=config.SIZE, frame_rate=config.FRAMERATE).start()
else:
return VideoCamStream(resolution=config.SIZE, frame_rate=config.FRAMERATE, src=config.CAMERA).start()
def main():
if len(sys.argv) > 1:
config.BG_FILE = sys.argv[0]
in_window(os.path.join(config.DIR, config.BG_FILE))
if __name__ == '__main__':
main()