-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlow.py
More file actions
203 lines (176 loc) · 6.94 KB
/
low.py
File metadata and controls
203 lines (176 loc) · 6.94 KB
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
from video_feed import VideoFeed
import cv2
import numpy as np
from object_detector import ObjectDetector
import time
from stream_credentials import get_authenticated_stream_url
import sys
import os
import logging
logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p', filename='out.log',level=logging.DEBUG)
logging.debug('Starting app..')
url = "data/videos/v0_fast.mp4"
# url = "data/videos/phone.mov"
url = "data/videos/phone_fast.mp4"
# url = "data/videos/v0.mp4"
# url = get_authenticated_stream_url()
WIDTH = 700
feed = VideoFeed(url, width=WIDTH, bw=False)
detector = ObjectDetector()
COLORS = {}
COLORS["cat"] = np.random.uniform(0, 255, size=(3))
COLORS["waterbowl"] = np.random.uniform(0, 255, size=(3))
COLORS["foodbowl"] = np.random.uniform(0, 255, size=(3))
def draw_bounding_box(img, label, confidence, x, y, x_plus_w, y_plus_h):
color = [0, 0, 0]
color[1] = confidence*255 # green
color[2] = (1 - confidence) * 255 # red
cv2.rectangle(img, (x, y), (x_plus_w, y_plus_h), color, 2)
cv2.putText(img, label, (x - 10, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2)
# cv2.putText(img, str(confidence), (x - 10, y - 20), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2)
def print_boxes(frame, result):
for type in result.keys():
for b in result[type]:
draw_bounding_box(frame,
type,
b["confidence"],
round(b["x"]),
round(b["y"]),
round(b["x"] + b["w"]),
round(b["y"] + b["h"])
)
cv2.imshow("low", frame)
def overlap(bowls, cats):
# any overlap between cat and bowl
for bowl in bowls:
for cat in cats:
bowl_top_left_x = bowl["x"]
bowl_top_left_y = bowl["y"]
bowl_bottom_right_x = bowl["x"] + bowl["w"]
bowl_bottom_right_y = bowl["y"] + bowl["h"]
cat_top_left_x = cat["x"]
cat_top_left_y = cat["y"]
cat_bottom_right_x = cat["x"] + cat["w"]
cat_bottom_right_y = cat["y"] + cat["h"]
if bowl_top_left_x >= cat_bottom_right_x or cat_top_left_x >= bowl_bottom_right_x:
continue
if bowl_top_left_y >= cat_bottom_right_y or cat_top_left_y >= bowl_bottom_right_y:
continue
return True
return False
show_video = True
no_foodbowl_wait = 0
no_cat_wait = 0
no_cat_session_end = 10
eating_detection_time = 5 # if one of the eating indicators been in place for this time, we consider eating
food_bowl_missing_time = 2 # if food bowl is missing for this time, we consider eating
wait_till_session_end_sleep_time = 5
# Session tracking
session = False
session_start_time = sys.maxsize
# Session info tracking
ate_food = False
cat_food_overlap_start_time = sys.maxsize
food_bowl_missing_start_time = sys.maxsize
cat_last_seen = sys.maxsize
eating_images = []
while True:
key = cv2.waitKey(1) & 0xFF
if key == ord("q"):
break
start = time.time()
frame = feed.next_frame()
# print("Reading: " + str(time.time() - start))
if frame is None:
break
start = time.time()
result = detector.get_objects(frame)
# print("Detection: " + str(time.time() - start))
if show_video:
print_boxes(frame, result)
# continue
'''
* If no active session, then check if there's a food bowl. If no food bowl, sleep
* If no active session, and there is a foodbowl and cat, start session
'''
if not session:
if "foodbowl" not in result:
logging.debug("no foodbowl, sleeping..")
time.sleep(no_foodbowl_wait)
continue
if "cat" not in result:
# logging.debug("no cat, sleeping..")
time.sleep(no_cat_wait)
continue
session = True
session_start_time = time.time()
eating_images += [frame]
'''
* If active session, and no cat, wait for a bit to handle model inconsistencies. End session after wait.
'''
if "cat" not in result:
if time.time() - cat_last_seen > no_cat_session_end:
eating_images += [frame]
path = "runtime/" + str(session_start_time) + "/"
os.makedirs(path)
c = 0
for image in eating_images:
c += 1
cv2.imwrite(path + str(c) + ".jpg", image)
logging.debug("Session ended at " + str(time.time() - no_cat_session_end))
logging.debug("Total session time: " + str(time.time() - session_start_time - no_cat_session_end))
logging.debug("Ate food: " + str(ate_food))
session = False
ate_food = False
cat_food_overlap_start_time = sys.maxsize
food_bowl_missing_start_time = sys.maxsize
cat_last_seen = sys.maxsize
session_start_time = sys.maxsize
eating_images = []
continue
cat_last_seen = time.time()
if ate_food:
# No need to check again for a session
if feed.local_video():
break
logging.debug("Already eaten food, waiting for session to end")
time.sleep(wait_till_session_end_sleep_time)
continue
'''
* If active session and there is a cat, check if cat is eating. Cat is potentially eating if:
* there is an overlap of bounding boxes
* foodbowl is missing for over X seconds
'''
if "foodbowl" in result:
food_bowl_missing_start_time = sys.maxsize
overlapped = overlap(result["foodbowl"], result["cat"])
if not overlapped:
# if both cat and bowl are in frame but not overlapping then we reset potential eating check
cat_food_overlap_start_time = sys.maxsize
else:
# if there is overlap, check if it's been for long enough
cat_food_overlap_start_time = min(cat_food_overlap_start_time, time.time())
if time.time() - cat_food_overlap_start_time > eating_detection_time:
logging.debug("Ate food because of overlap")
eating_images += [frame]
ate_food = True
continue
if "foodbowl" not in result:
food_bowl_missing_start_time = min(time.time(), food_bowl_missing_start_time)
if time.time() - food_bowl_missing_start_time > eating_detection_time:
logging.debug("Ate food because of missing bowl")
eating_images += [frame]
ate_food = True
continue
feed.close()
if feed.local_video() and session_start_time < sys.maxsize:
path = "runtime/" + str(session_start_time) + "/"
os.makedirs(path)
c = 0
for image in eating_images:
c += 1
cv2.imwrite(path + str(c) + ".jpg", image)
print("======== Last state ==========")
print("Session ended at " + str(time.time()))
print("Total session time: " + str(time.time() - session_start_time))
print("Ate food: " + str(ate_food))