-
Notifications
You must be signed in to change notification settings - Fork 0
/
streaming_processing.py
153 lines (130 loc) · 5.31 KB
/
streaming_processing.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
"""
NeurodataLab LLC 09.12.2019
Created by Andrey Belyaev
"""
import cv2
import json
from queue import Empty
from multiprocessing import Event, Process, Queue
class IWebCamStreamProcessing:
"""
Webcam stream processing interface.
Takes images from webcam, process it via NDL API and visualize results
:param service: NDL API service
"""
def __init__(self, service):
self.service = service
# Assign streaming function to service. This function have to yield images and will be called from NDL API core
self.service.set_streaming_function(self.iterate_webcam_images, 'image')
# Create images and result sources for communication between several processes
self.images_queue, self.result_queue = Queue(), Queue()
# Create event for stopping the system
self.stop_event = Event()
self.stop_event.clear()
def iterate_webcam_images(self):
"""
Iterates over images stream.
Takes images from input source (i.e. queue) and send it to NDL API
Raises Empty if there are no images to send for at least 5 seconds
"""
try:
# Do until somebody stop event
while not self.stop_event.is_set():
# Get image from input source
image = self.images_queue.get(timeout=5)
# Yield image for NDL API
yield image
except Empty:
print('Webcam timeout exceeded. Aborting.')
raise
except:
print('Exception in iterating webcam images. Aborting')
raise
finally:
print('Webcam iterating was successfully stopped')
def iterate_api_responses(self):
"""
Iterates over NDL API responses
Takes response from NDL API, translates it to the correct format and puts to the target source (i.e. queue)
Raises BaseException in case of postprocessing error
"""
try:
# Do until service stop processing
for response in self.service.process_stream():
# Check response status
if response[1] is None:
print(response[2])
continue
# Get result and translate it to the correct format
result = {i: json.loads(image_res.result) for i, image_res in enumerate(response[1])}
processed_result = self.service._postprocess_result(result)
# Put result to target source
self.result_queue.put(processed_result)
# Check system is not stopped
if self.stop_event.is_set():
break
except:
print("Exception while iterating API response")
raise
finally:
self.stop_event.set()
def start_streaming(self):
"""
Start webcam streaming.
Open webcam stream and process images from it
Creates additional process to iterate over NDL API responses
:return:
"""
# Create and start parallel process for iterating over NDL API response
response_iterating_process = Process(target=self.iterate_api_responses)
response_iterating_process.daemon = True
response_iterating_process.start()
# Last processed result
last_result, wait_for_result = None, False
# Open webcam stream
cap = cv2.VideoCapture(0)
# Get first frame from webcam stream
ret, frame = cap.read()
# Check that webcam works normally and nobody stopped the system
while ret and not self.stop_event.is_set():
# Check if last putted images already processed
if self.images_queue.empty() and not wait_for_result:
self.images_queue.put(frame)
wait_for_result = True
# Check if there is new processing result
if not self.result_queue.empty():
last_result = self.result_queue.get()
wait_for_result = False
# Visualize result on frame
vis_frame = self.visualize_result(frame, last_result)
# Show frame
cv2.imshow('webcam', vis_frame)
# Wait 50ms for any key pressed. Stops system if 'q' was pressed.
if cv2.waitKey(50) & 0xff == ord('q'):
break
# Read next frame
ret, frame = cap.read()
# Stop system
self.stop_event.set()
# Release webcam
cap.release()
print('Webcam capture released')
def visualize_result(self, image, res=None):
"""
Visualizes data on image
:param image: image from webcam stream
:param res: result from NDL API
:return: image with visualized data
"""
raise NotImplementedError
class WebCamFaceDetectorStreamProcessing(IWebCamStreamProcessing):
def visualize_result(self, image, res=None):
# Check res has normal format
if res is not None and len(res) > 0:
# Visualize each faces in result
for face in res[0]:
# Get face coordinates
x, y, w, h = list(map(int, [face[k] for k in ('x', 'y', 'w', 'h')]))
# Draw rectangle on image
cv2.rectangle(image, (x, y), (x + w, y + h), (255, 0, 255))
return image