iDrops commited on
Commit
2c8d6cd
·
verified ·
1 Parent(s): 6531dd6

Create process_frame.py

Browse files
Files changed (1) hide show
  1. process_frame.py +534 -0
process_frame.py ADDED
@@ -0,0 +1,534 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import time
2
+ import cv2
3
+ import numpy as np
4
+ from utils import find_angle, get_landmark_features, draw_text
5
+
6
+
7
+ class ProcessFrame:
8
+ def __init__(self, thresholds, flip_frame = False):
9
+
10
+ # Set if frame should be flipped or not.
11
+ self.flip_frame = flip_frame
12
+
13
+ # self.thresholds
14
+ self.thresholds = thresholds
15
+
16
+ # Font type.
17
+ self.font = cv2.FONT_HERSHEY_SIMPLEX
18
+
19
+ # line type
20
+ self.linetype = cv2.LINE_AA
21
+
22
+ # set radius to draw arc
23
+ self.radius = 20
24
+
25
+ # Colors in BGR format.
26
+ self.COLORS = {
27
+ 'blue' : (0, 127, 255),
28
+ 'red' : (255, 50, 50),
29
+ 'green' : (0, 255, 127),
30
+ 'light_green': (100, 233, 127),
31
+ 'yellow' : (255, 255, 0),
32
+ 'magenta' : (255, 0, 255),
33
+ 'white' : (255,255,255),
34
+ 'cyan' : (0, 255, 255),
35
+ 'light_blue' : (102, 204, 255)
36
+ }
37
+
38
+ # Dictionary to maintain the various landmark features.
39
+ self.dict_features = {}
40
+ self.left_features = {
41
+ 'shoulder': 11,
42
+ 'elbow' : 13,
43
+ 'wrist' : 15,
44
+ 'hip' : 23,
45
+ 'knee' : 25,
46
+ 'ankle' : 27,
47
+ 'foot' : 31
48
+ }
49
+
50
+ self.right_features = {
51
+ 'shoulder': 12,
52
+ 'elbow' : 14,
53
+ 'wrist' : 16,
54
+ 'hip' : 24,
55
+ 'knee' : 26,
56
+ 'ankle' : 28,
57
+ 'foot' : 32
58
+ }
59
+
60
+ self.dict_features['left'] = self.left_features
61
+ self.dict_features['right'] = self.right_features
62
+ self.dict_features['nose'] = 0
63
+
64
+ # For tracking counters and sharing states in and out of callbacks.
65
+ self.state_tracker = {
66
+ 'state_seq': [],
67
+
68
+ 'start_inactive_time': time.perf_counter(),
69
+ 'start_inactive_time_front': time.perf_counter(),
70
+ 'INACTIVE_TIME': 0.0,
71
+ 'INACTIVE_TIME_FRONT': 0.0,
72
+
73
+ # 0 --> Bend Backwards, 1 --> Bend Forward, 2 --> Keep shin straight, 3 --> Deep squat
74
+ 'DISPLAY_TEXT' : np.full((4,), False),
75
+ 'COUNT_FRAMES' : np.zeros((4,), dtype=np.int64),
76
+
77
+ 'LOWER_HIPS': False,
78
+
79
+ 'INCORRECT_POSTURE': False,
80
+
81
+ 'prev_state': None,
82
+ 'curr_state':None,
83
+
84
+ 'SQUAT_COUNT': 0,
85
+ 'IMPROPER_SQUAT':0
86
+
87
+ }
88
+
89
+ self.FEEDBACK_ID_MAP = {
90
+ 0: ('BEND BACKWARDS', 215, (0, 153, 255)),
91
+ 1: ('BEND FORWARD', 215, (0, 153, 255)),
92
+ 2: ('KNEE FALLING OVER TOE', 170, (255, 80, 80)),
93
+ 3: ('SQUAT TOO DEEP', 125, (255, 80, 80))
94
+ }
95
+
96
+ def _get_state(self, knee_angle):
97
+
98
+ knee = None
99
+
100
+ if self.thresholds['HIP_KNEE_VERT']['NORMAL'][0] <= knee_angle <= self.thresholds['HIP_KNEE_VERT']['NORMAL'][1]:
101
+ knee = 1
102
+ elif self.thresholds['HIP_KNEE_VERT']['TRANS'][0] <= knee_angle <= self.thresholds['HIP_KNEE_VERT']['TRANS'][1]:
103
+ knee = 2
104
+ elif self.thresholds['HIP_KNEE_VERT']['PASS'][0] <= knee_angle <= self.thresholds['HIP_KNEE_VERT']['PASS'][1]:
105
+ knee = 3
106
+
107
+ return f's{knee}' if knee else None
108
+
109
+ def _update_state_sequence(self, state):
110
+
111
+ if state == 's2':
112
+ if (('s3' not in self.state_tracker['state_seq']) and (self.state_tracker['state_seq'].count('s2'))==0) or \
113
+ (('s3' in self.state_tracker['state_seq']) and (self.state_tracker['state_seq'].count('s2')==1)):
114
+ self.state_tracker['state_seq'].append(state)
115
+
116
+
117
+ elif state == 's3':
118
+ if (state not in self.state_tracker['state_seq']) and 's2' in self.state_tracker['state_seq']:
119
+ self.state_tracker['state_seq'].append(state)
120
+
121
+ def _show_feedback(self, frame, c_frame, dict_maps, lower_hips_disp):
122
+
123
+ if lower_hips_disp:
124
+ draw_text(
125
+ frame,
126
+ 'LOWER YOUR HIPS',
127
+ pos=(30, 80),
128
+ text_color=(0, 0, 0),
129
+ font_scale=0.6,
130
+ text_color_bg=(255, 255, 0)
131
+ )
132
+
133
+ for idx in np.where(c_frame)[0]:
134
+ draw_text(
135
+ frame,
136
+ dict_maps[idx][0],
137
+ pos=(30, dict_maps[idx][1]),
138
+ text_color=(255, 255, 230),
139
+ font_scale=0.6,
140
+ text_color_bg=dict_maps[idx][2]
141
+ )
142
+
143
+ return frame
144
+
145
+ def process(self, frame: np.array, pose):
146
+ play_sound = None
147
+
148
+
149
+ frame_height, frame_width, _ = frame.shape
150
+
151
+ # Process the image.
152
+ keypoints = pose.process(frame)
153
+
154
+ if keypoints.pose_landmarks:
155
+ ps_lm = keypoints.pose_landmarks
156
+
157
+ nose_coord = get_landmark_features(ps_lm.landmark, self.dict_features, 'nose', frame_width, frame_height)
158
+ left_shldr_coord, left_elbow_coord, left_wrist_coord, left_hip_coord, left_knee_coord, left_ankle_coord, left_foot_coord = \
159
+ get_landmark_features(ps_lm.landmark, self.dict_features, 'left', frame_width, frame_height)
160
+ right_shldr_coord, right_elbow_coord, right_wrist_coord, right_hip_coord, right_knee_coord, right_ankle_coord, right_foot_coord = \
161
+ get_landmark_features(ps_lm.landmark, self.dict_features, 'right', frame_width, frame_height)
162
+
163
+ offset_angle = find_angle(left_shldr_coord, right_shldr_coord, nose_coord)
164
+
165
+ if offset_angle > self.thresholds['OFFSET_THRESH']:
166
+
167
+ display_inactivity = False
168
+
169
+ end_time = time.perf_counter()
170
+ self.state_tracker['INACTIVE_TIME_FRONT'] += end_time - self.state_tracker['start_inactive_time_front']
171
+ self.state_tracker['start_inactive_time_front'] = end_time
172
+
173
+ if self.state_tracker['INACTIVE_TIME_FRONT'] >= self.thresholds['INACTIVE_THRESH']:
174
+ self.state_tracker['SQUAT_COUNT'] = 0
175
+ self.state_tracker['IMPROPER_SQUAT'] = 0
176
+ display_inactivity = True
177
+
178
+ cv2.circle(frame, nose_coord, 7, self.COLORS['white'], -1)
179
+ cv2.circle(frame, left_shldr_coord, 7, self.COLORS['yellow'], -1)
180
+ cv2.circle(frame, right_shldr_coord, 7, self.COLORS['magenta'], -1)
181
+
182
+ if self.flip_frame:
183
+ frame = cv2.flip(frame, 1)
184
+
185
+ if display_inactivity:
186
+ # cv2.putText(frame, 'Resetting SQUAT_COUNT due to inactivity!!!', (10, frame_height - 90),
187
+ # self.font, 0.5, self.COLORS['blue'], 2, lineType=self.linetype)
188
+ play_sound = 'reset_counters'
189
+ self.state_tracker['INACTIVE_TIME_FRONT'] = 0.0
190
+ self.state_tracker['start_inactive_time_front'] = time.perf_counter()
191
+
192
+ draw_text(
193
+ frame,
194
+ "CORRECT: " + str(self.state_tracker['SQUAT_COUNT']),
195
+ pos=(int(frame_width*0.75), 30),
196
+ text_color=(255, 255, 230),
197
+ font_scale=0.7,
198
+ text_color_bg=(18, 185, 0)
199
+ )
200
+
201
+ draw_text(
202
+ frame,
203
+ "INCORRECT: " + str(self.state_tracker['IMPROPER_SQUAT']),
204
+ pos=(int(frame_width*0.75), 80),
205
+ text_color=(255, 255, 230),
206
+ font_scale=0.7,
207
+ text_color_bg=(221, 0, 0),
208
+
209
+ )
210
+
211
+ draw_text(
212
+ frame,
213
+ 'CAMERA NOT ALIGNED PROPERLY!!!',
214
+ pos=(30, frame_height-60),
215
+ text_color=(255, 255, 230),
216
+ font_scale=0.65,
217
+ text_color_bg=(237, 33, 37),
218
+ )
219
+
220
+ draw_text(
221
+ frame,
222
+ 'OFFSET ANGLE: '+str(offset_angle),
223
+ pos=(30, frame_height-30),
224
+ text_color=(255, 255, 230),
225
+ font_scale=0.65,
226
+ text_color_bg=(255, 153, 0),
227
+ )
228
+
229
+ # Reset inactive times for side view.
230
+ self.state_tracker['start_inactive_time'] = time.perf_counter()
231
+ self.state_tracker['INACTIVE_TIME'] = 0.0
232
+ self.state_tracker['prev_state'] = None
233
+ self.state_tracker['curr_state'] = None
234
+
235
+ # Camera is aligned properly.
236
+ else:
237
+
238
+ self.state_tracker['INACTIVE_TIME_FRONT'] = 0.0
239
+ self.state_tracker['start_inactive_time_front'] = time.perf_counter()
240
+
241
+
242
+ dist_l_sh_hip = abs(left_foot_coord[1]- left_shldr_coord[1])
243
+ dist_r_sh_hip = abs(right_foot_coord[1] - right_shldr_coord)[1]
244
+
245
+ shldr_coord = None
246
+ elbow_coord = None
247
+ wrist_coord = None
248
+ hip_coord = None
249
+ knee_coord = None
250
+ ankle_coord = None
251
+ foot_coord = None
252
+
253
+ if dist_l_sh_hip > dist_r_sh_hip:
254
+ shldr_coord = left_shldr_coord
255
+ elbow_coord = left_elbow_coord
256
+ wrist_coord = left_wrist_coord
257
+ hip_coord = left_hip_coord
258
+ knee_coord = left_knee_coord
259
+ ankle_coord = left_ankle_coord
260
+ foot_coord = left_foot_coord
261
+
262
+ multiplier = -1
263
+
264
+
265
+ else:
266
+ shldr_coord = right_shldr_coord
267
+ elbow_coord = right_elbow_coord
268
+ wrist_coord = right_wrist_coord
269
+ hip_coord = right_hip_coord
270
+ knee_coord = right_knee_coord
271
+ ankle_coord = right_ankle_coord
272
+ foot_coord = right_foot_coord
273
+
274
+ multiplier = 1
275
+
276
+
277
+ # ------------------- Verical Angle calculation --------------
278
+
279
+ hip_vertical_angle = find_angle(shldr_coord, np.array([hip_coord[0], 0]), hip_coord)
280
+ cv2.ellipse(frame, hip_coord, (30, 30),
281
+ angle = 0, startAngle = -90, endAngle = -90+multiplier*hip_vertical_angle,
282
+ color = self.COLORS['white'], thickness = 3, lineType = self.linetype)
283
+
284
+ cv2.line(frame, (hip_coord[0], hip_coord[1] + 20), (hip_coord[0], hip_coord[1] - 80), self.COLORS['blue'], 4, lineType=self.linetype)
285
+
286
+
287
+
288
+
289
+ knee_vertical_angle = find_angle(hip_coord, np.array([knee_coord[0], 0]), knee_coord)
290
+ cv2.ellipse(frame, knee_coord, (20, 20),
291
+ angle = 0, startAngle = -90, endAngle = -90-multiplier*knee_vertical_angle,
292
+ color = self.COLORS['white'], thickness = 3, lineType = self.linetype)
293
+
294
+ cv2.line(frame, (knee_coord[0], knee_coord[1] + 20), (knee_coord[0], knee_coord[1] - 50), self.COLORS['blue'], 4, lineType=self.linetype)
295
+
296
+
297
+
298
+ ankle_vertical_angle = find_angle(knee_coord, np.array([ankle_coord[0], 0]), ankle_coord)
299
+ cv2.ellipse(frame, ankle_coord, (30, 30),
300
+ angle = 0, startAngle = -90, endAngle = -90 + multiplier*ankle_vertical_angle,
301
+ color = self.COLORS['white'], thickness = 3, lineType=self.linetype)
302
+
303
+ cv2.line(frame, (ankle_coord[0], ankle_coord[1] + 20), (ankle_coord[0], ankle_coord[1] - 50), self.COLORS['blue'], 4, lineType=self.linetype)
304
+
305
+ # ------------------------------------------------------------
306
+
307
+
308
+ # Join landmarks.
309
+ cv2.line(frame, shldr_coord, elbow_coord, self.COLORS['light_blue'], 4, lineType=self.linetype)
310
+ cv2.line(frame, wrist_coord, elbow_coord, self.COLORS['light_blue'], 4, lineType=self.linetype)
311
+ cv2.line(frame, shldr_coord, hip_coord, self.COLORS['light_blue'], 4, lineType=self.linetype)
312
+ cv2.line(frame, knee_coord, hip_coord, self.COLORS['light_blue'], 4, lineType=self.linetype)
313
+ cv2.line(frame, ankle_coord, knee_coord,self.COLORS['light_blue'], 4, lineType=self.linetype)
314
+ cv2.line(frame, ankle_coord, foot_coord, self.COLORS['light_blue'], 4, lineType=self.linetype)
315
+
316
+ # Plot landmark points
317
+ cv2.circle(frame, shldr_coord, 7, self.COLORS['yellow'], -1, lineType=self.linetype)
318
+ cv2.circle(frame, elbow_coord, 7, self.COLORS['yellow'], -1, lineType=self.linetype)
319
+ cv2.circle(frame, wrist_coord, 7, self.COLORS['yellow'], -1, lineType=self.linetype)
320
+ cv2.circle(frame, hip_coord, 7, self.COLORS['yellow'], -1, lineType=self.linetype)
321
+ cv2.circle(frame, knee_coord, 7, self.COLORS['yellow'], -1, lineType=self.linetype)
322
+ cv2.circle(frame, ankle_coord, 7, self.COLORS['yellow'], -1, lineType=self.linetype)
323
+ cv2.circle(frame, foot_coord, 7, self.COLORS['yellow'], -1, lineType=self.linetype)
324
+
325
+
326
+
327
+ current_state = self._get_state(int(knee_vertical_angle))
328
+ self.state_tracker['curr_state'] = current_state
329
+ self._update_state_sequence(current_state)
330
+
331
+
332
+
333
+ # -------------------------------------- COMPUTE COUNTERS --------------------------------------
334
+
335
+ if current_state == 's1':
336
+
337
+ if len(self.state_tracker['state_seq']) == 3 and not self.state_tracker['INCORRECT_POSTURE']:
338
+ self.state_tracker['SQUAT_COUNT']+=1
339
+ play_sound = str(self.state_tracker['SQUAT_COUNT'])
340
+
341
+ elif 's2' in self.state_tracker['state_seq'] and len(self.state_tracker['state_seq'])==1:
342
+ self.state_tracker['IMPROPER_SQUAT']+=1
343
+ play_sound = 'incorrect'
344
+
345
+ elif self.state_tracker['INCORRECT_POSTURE']:
346
+ self.state_tracker['IMPROPER_SQUAT']+=1
347
+ play_sound = 'incorrect'
348
+
349
+
350
+ self.state_tracker['state_seq'] = []
351
+ self.state_tracker['INCORRECT_POSTURE'] = False
352
+
353
+
354
+ # ----------------------------------------------------------------------------------------------------
355
+
356
+
357
+
358
+
359
+ # -------------------------------------- PERFORM FEEDBACK ACTIONS --------------------------------------
360
+
361
+ else:
362
+ if hip_vertical_angle > self.thresholds['HIP_THRESH'][1]:
363
+ self.state_tracker['DISPLAY_TEXT'][0] = True
364
+
365
+
366
+ elif hip_vertical_angle < self.thresholds['HIP_THRESH'][0] and \
367
+ self.state_tracker['state_seq'].count('s2')==1:
368
+ self.state_tracker['DISPLAY_TEXT'][1] = True
369
+
370
+
371
+
372
+ if self.thresholds['KNEE_THRESH'][0] < knee_vertical_angle < self.thresholds['KNEE_THRESH'][1] and \
373
+ self.state_tracker['state_seq'].count('s2')==1:
374
+ self.state_tracker['LOWER_HIPS'] = True
375
+
376
+
377
+ elif knee_vertical_angle > self.thresholds['KNEE_THRESH'][2]:
378
+ self.state_tracker['DISPLAY_TEXT'][3] = True
379
+ self.state_tracker['INCORRECT_POSTURE'] = True
380
+
381
+
382
+ if (ankle_vertical_angle > self.thresholds['ANKLE_THRESH']):
383
+ self.state_tracker['DISPLAY_TEXT'][2] = True
384
+ self.state_tracker['INCORRECT_POSTURE'] = True
385
+
386
+
387
+ # ----------------------------------------------------------------------------------------------------
388
+
389
+
390
+
391
+
392
+ # ----------------------------------- COMPUTE INACTIVITY ---------------------------------------------
393
+
394
+ display_inactivity = False
395
+
396
+ if self.state_tracker['curr_state'] == self.state_tracker['prev_state']:
397
+
398
+ end_time = time.perf_counter()
399
+ self.state_tracker['INACTIVE_TIME'] += end_time - self.state_tracker['start_inactive_time']
400
+ self.state_tracker['start_inactive_time'] = end_time
401
+
402
+ if self.state_tracker['INACTIVE_TIME'] >= self.thresholds['INACTIVE_THRESH']:
403
+ self.state_tracker['SQUAT_COUNT'] = 0
404
+ self.state_tracker['IMPROPER_SQUAT'] = 0
405
+ display_inactivity = True
406
+
407
+
408
+ else:
409
+
410
+ self.state_tracker['start_inactive_time'] = time.perf_counter()
411
+ self.state_tracker['INACTIVE_TIME'] = 0.0
412
+
413
+ # -------------------------------------------------------------------------------------------------------
414
+
415
+
416
+
417
+ hip_text_coord_x = hip_coord[0] + 10
418
+ knee_text_coord_x = knee_coord[0] + 15
419
+ ankle_text_coord_x = ankle_coord[0] + 10
420
+
421
+ if self.flip_frame:
422
+ frame = cv2.flip(frame, 1)
423
+ hip_text_coord_x = frame_width - hip_coord[0] + 10
424
+ knee_text_coord_x = frame_width - knee_coord[0] + 15
425
+ ankle_text_coord_x = frame_width - ankle_coord[0] + 10
426
+
427
+
428
+
429
+ if 's3' in self.state_tracker['state_seq']:
430
+ self.state_tracker['LOWER_HIPS'] = False
431
+
432
+ self.state_tracker['COUNT_FRAMES'][self.state_tracker['DISPLAY_TEXT']]+=1
433
+
434
+ frame = self._show_feedback(frame, self.state_tracker['COUNT_FRAMES'], self.FEEDBACK_ID_MAP, self.state_tracker['LOWER_HIPS'])
435
+
436
+
437
+
438
+ if display_inactivity:
439
+ # cv2.putText(frame, 'Resetting COUNTERS due to inactivity!!!', (10, frame_height - 20), self.font, 0.5, self.COLORS['blue'], 2, lineType=self.linetype)
440
+ play_sound = 'reset_counters'
441
+ self.state_tracker['start_inactive_time'] = time.perf_counter()
442
+ self.state_tracker['INACTIVE_TIME'] = 0.0
443
+
444
+
445
+ cv2.putText(frame, str(int(hip_vertical_angle)), (hip_text_coord_x, hip_coord[1]), self.font, 0.6, self.COLORS['light_green'], 2, lineType=self.linetype)
446
+ cv2.putText(frame, str(int(knee_vertical_angle)), (knee_text_coord_x, knee_coord[1]+10), self.font, 0.6, self.COLORS['light_green'], 2, lineType=self.linetype)
447
+ cv2.putText(frame, str(int(ankle_vertical_angle)), (ankle_text_coord_x, ankle_coord[1]), self.font, 0.6, self.COLORS['light_green'], 2, lineType=self.linetype)
448
+
449
+
450
+ draw_text(
451
+ frame,
452
+ "CORRECT: " + str(self.state_tracker['SQUAT_COUNT']),
453
+ pos=(int(frame_width*0.75), 30),
454
+ text_color=(255, 255, 230),
455
+ font_scale=0.7,
456
+ text_color_bg=(18, 185, 0)
457
+ )
458
+
459
+
460
+ draw_text(
461
+ frame,
462
+ "INCORRECT: " + str(self.state_tracker['IMPROPER_SQUAT']),
463
+ pos=(int(frame_width*0.75), 80),
464
+ text_color=(255, 255, 230),
465
+ font_scale=0.7,
466
+ text_color_bg=(221, 0, 0),
467
+
468
+ )
469
+
470
+
471
+ self.state_tracker['DISPLAY_TEXT'][self.state_tracker['COUNT_FRAMES'] > self.thresholds['CNT_FRAME_THRESH']] = False
472
+ self.state_tracker['COUNT_FRAMES'][self.state_tracker['COUNT_FRAMES'] > self.thresholds['CNT_FRAME_THRESH']] = 0
473
+ self.state_tracker['prev_state'] = current_state
474
+
475
+
476
+
477
+
478
+ else:
479
+
480
+ if self.flip_frame:
481
+ frame = cv2.flip(frame, 1)
482
+
483
+ end_time = time.perf_counter()
484
+ self.state_tracker['INACTIVE_TIME'] += end_time - self.state_tracker['start_inactive_time']
485
+
486
+ display_inactivity = False
487
+
488
+ if self.state_tracker['INACTIVE_TIME'] >= self.thresholds['INACTIVE_THRESH']:
489
+ self.state_tracker['SQUAT_COUNT'] = 0
490
+ self.state_tracker['IMPROPER_SQUAT'] = 0
491
+ # cv2.putText(frame, 'Resetting SQUAT_COUNT due to inactivity!!!', (10, frame_height - 25), self.font, 0.7, self.COLORS['blue'], 2)
492
+ display_inactivity = True
493
+
494
+ self.state_tracker['start_inactive_time'] = end_time
495
+
496
+ draw_text(
497
+ frame,
498
+ "CORRECT: " + str(self.state_tracker['SQUAT_COUNT']),
499
+ pos=(int(frame_width*0.75), 30),
500
+ text_color=(255, 255, 230),
501
+ font_scale=0.7,
502
+ text_color_bg=(18, 185, 0)
503
+ )
504
+
505
+
506
+ draw_text(
507
+ frame,
508
+ "INCORRECT: " + str(self.state_tracker['IMPROPER_SQUAT']),
509
+ pos=(int(frame_width*0.75), 80),
510
+ text_color=(255, 255, 230),
511
+ font_scale=0.7,
512
+ text_color_bg=(221, 0, 0),
513
+
514
+ )
515
+
516
+ if display_inactivity:
517
+ play_sound = 'reset_counters'
518
+ self.state_tracker['start_inactive_time'] = time.perf_counter()
519
+ self.state_tracker['INACTIVE_TIME'] = 0.0
520
+
521
+
522
+ # Reset all other state variables
523
+
524
+ self.state_tracker['prev_state'] = None
525
+ self.state_tracker['curr_state'] = None
526
+ self.state_tracker['INACTIVE_TIME_FRONT'] = 0.0
527
+ self.state_tracker['INCORRECT_POSTURE'] = False
528
+ self.state_tracker['DISPLAY_TEXT'] = np.full((5,), False)
529
+ self.state_tracker['COUNT_FRAMES'] = np.zeros((5,), dtype=np.int64)
530
+ self.state_tracker['start_inactive_time_front'] = time.perf_counter()
531
+
532
+
533
+
534
+ return frame, play_sound