-
Notifications
You must be signed in to change notification settings - Fork 23
/
Copy pathutils.py
282 lines (245 loc) · 13 KB
/
utils.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
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
import time
import cv2
import numpy as np
import tensorflow.compat.v1 as tf
import os
import sys
import argparse
import matplotlib.pyplot as plt
from sys import platform
from scipy.optimize import curve_fit
tf.disable_v2_behavior()
def openpose_init():
try:
if platform == "win32":
sys.path.append('./OpenPose/Release')
import pyopenpose as op
else:
sys.path.append('./OpenPose')
from Release import pyopenpose as op
except ImportError as e:
print('Error: OpenPose library could not be found. Did you enable `BUILD_PYTHON` in CMake and have this Python script in the right folder?')
raise e
# Custom Params (refer to include/openpose/flags.hpp for more parameters)
params = dict()
params["model_folder"] = "./OpenPose/models"
# Starting OpenPose
opWrapper = op.WrapperPython()
opWrapper.configure(params)
opWrapper.start()
# Process Image
datum = op.Datum()
return datum, opWrapper
def fit_func(x, a, b, c):
return a*(x ** 2) + b * x + c
def trajectory_fit(balls, height, width, shotJudgement, fig):
x = []
y = []
for ball in balls:
x.append(ball[0])
y.append(height - ball[1])
try:
params = curve_fit(fit_func, x, y)
[a, b, c] = params[0]
except:
print("fiiting error")
a = 0
b = 0
c = 0
x_pos = np.arange(0, width, 1)
y_pos = []
for i in range(len(x_pos)):
x_val = x_pos[i]
y_val = (a * (x_val ** 2)) + (b * x_val) + c
y_pos.append(y_val)
if(shotJudgement == "MISS"):
plt.plot(x, y, 'ro', figure=fig)
plt.plot(x_pos, y_pos, linestyle='-', color='red',
alpha=0.4, linewidth=5, figure=fig)
else:
plt.plot(x, y, 'go', figure=fig)
plt.plot(x_pos, y_pos, linestyle='-', color='green',
alpha=0.4, linewidth=5, figure=fig)
def distance(x, y):
return ((y[0] - x[0]) ** 2 + (y[1] - x[1]) ** 2) ** (1/2)
def tensorflow_init():
MODEL_NAME = 'inference_graph'
PATH_TO_CKPT = MODEL_NAME + '/frozen_inference_graph.pb'
detection_graph = tf.Graph()
with detection_graph.as_default():
od_graph_def = tf.GraphDef()
with tf.gfile.GFile(PATH_TO_CKPT, 'rb') as fid:
serialized_graph = fid.read()
od_graph_def.ParseFromString(serialized_graph)
tf.import_graph_def(od_graph_def, name='')
image_tensor = detection_graph.get_tensor_by_name('image_tensor:0')
boxes = detection_graph.get_tensor_by_name('detection_boxes:0')
scores = detection_graph.get_tensor_by_name('detection_scores:0')
classes = detection_graph.get_tensor_by_name('detection_classes:0')
num_detections = detection_graph.get_tensor_by_name('num_detections:0')
return detection_graph, image_tensor, boxes, scores, classes, num_detections
def calculateAngle(a, b, c):
ba = a - b
bc = c - b
cosine_angle = np.dot(ba, bc) / (np.linalg.norm(ba) * np.linalg.norm(bc))
angle = np.arccos(cosine_angle)
return round(np.degrees(angle), 2)
def getAngleFromDatum(datum):
hipX, hipY, _ = datum.poseKeypoints[0][9]
kneeX, kneeY, _ = datum.poseKeypoints[0][10]
ankleX, ankleY, _ = datum.poseKeypoints[0][11]
shoulderX, shoulderY, _ = datum.poseKeypoints[0][2]
elbowX, elbowY, _ = datum.poseKeypoints[0][3]
wristX, wristY, _ = datum.poseKeypoints[0][4]
kneeAngle = calculateAngle(np.array([hipX, hipY]), np.array([kneeX, kneeY]), np.array([ankleX, ankleY]))
elbowAngle = calculateAngle(np.array([shoulderX, shoulderY]), np.array([elbowX, elbowY]), np.array([wristX, wristY]))
elbowCoord = np.array([int(elbowX), int(elbowY)])
kneeCoord = np.array([int(kneeX), int(kneeY)])
return elbowAngle, kneeAngle, elbowCoord, kneeCoord
def detect_shot(frame, trace, width, height, sess, image_tensor, boxes, scores, classes, num_detections, previous, during_shooting, shot_result, fig, shooting_result, datum, opWrapper, shooting_pose):
if(shot_result['displayFrames'] > 0):
shot_result['displayFrames'] -= 1
if(shot_result['release_displayFrames'] > 0):
shot_result['release_displayFrames'] -= 1
if(shooting_pose['ball_in_hand']):
shooting_pose['ballInHand_frames'] += 1
print("ball in hand")
# getting openpose keypoints
datum.cvInputData = frame
opWrapper.emplaceAndPop([datum])
try:
headX, headY, headConf = datum.poseKeypoints[0][0]
handX, handY, handConf = datum.poseKeypoints[0][4]
elbowAngle, kneeAngle, elbowCoord, kneeCoord = getAngleFromDatum(datum)
except:
print("Something went wrong with OpenPose")
headX = 0
headY = 0
handX = 0
handY = 0
elbowAngle = 0
kneeAngle = 0
elbowCoord = np.array([0, 0])
kneeCoord = np.array([0, 0])
frame_expanded = np.expand_dims(frame, axis=0)
# main tensorflow detection
(boxes, scores, classes, num_detections) = sess.run(
[boxes, scores, classes, num_detections],
feed_dict={image_tensor: frame_expanded})
# displaying openpose, joint angle and release angle
frame = datum.cvOutputData
cv2.putText(frame, 'Elbow: ' + str(elbowAngle) + ' deg',
(elbowCoord[0] + 65, elbowCoord[1]), cv2.FONT_HERSHEY_COMPLEX, 1.3, (102, 255, 0), 3)
cv2.putText(frame, 'Knee: ' + str(kneeAngle) + ' deg',
(kneeCoord[0] + 65, kneeCoord[1]), cv2.FONT_HERSHEY_COMPLEX, 1.3, (102, 255, 0), 3)
if(shot_result['release_displayFrames']):
cv2.putText(frame, 'Release: ' + str(during_shooting['release_angle_list'][-1]) + ' deg',
(during_shooting['release_point'][0] - 80, during_shooting['release_point'][1] + 80), cv2.FONT_HERSHEY_COMPLEX, 1.3, (102, 255, 255), 3)
cv2.putText(frame, 'Release: ' + str(during_shooting['release_angle_list'][-1]) + ' deg',
(during_shooting['release_point'][0] - 80, during_shooting['release_point'][1] + 80), cv2.FONT_HERSHEY_COMPLEX, 1.3, (102, 255, 255), 3)
for i, box in enumerate(boxes[0]):
if (scores[0][i] > 0.5):
ymin = int((box[0] * height))
xmin = int((box[1] * width))
ymax = int((box[2] * height))
xmax = int((box[3] * width))
xCoor = int(np.mean([xmin, xmax]))
yCoor = int(np.mean([ymin, ymax]))
if(classes[0][i] == 1 and (distance([headX, headY], [xCoor, yCoor]) > 30)): # Basketball (not head)
# recording shooting pose
if(distance([xCoor, yCoor], [handX, handY]) < 120):
shooting_pose['ball_in_hand'] = True
shooting_pose['knee_angle'] = min(shooting_pose['knee_angle'], kneeAngle)
shooting_pose['elbow_angle'] = min(shooting_pose['elbow_angle'], elbowAngle)
else:
shooting_pose['ball_in_hand'] = False
# During Shooting
if(ymin < (previous['hoop_height'])):
if(not during_shooting['isShooting']):
during_shooting['isShooting'] = True
during_shooting['balls_during_shooting'].append(
[xCoor, yCoor])
#calculating release angle
if(len(during_shooting['balls_during_shooting']) == 2):
first_shooting_point = during_shooting['balls_during_shooting'][0]
release_angle = calculateAngle(np.array(during_shooting['balls_during_shooting'][1]), np.array(first_shooting_point), np.array([first_shooting_point[0] + 1, first_shooting_point[1]]))
during_shooting['release_angle_list'].append(release_angle)
during_shooting['release_point'] = first_shooting_point
shot_result['release_displayFrames'] = 30
print("release: ", release_angle)
#draw purple circle
cv2.circle(img=frame, center=(xCoor, yCoor), radius=7,
color=(235, 103, 193), thickness=3)
cv2.circle(img=trace, center=(xCoor, yCoor), radius=7,
color=(235, 103, 193), thickness=3)
# Not shooting
elif(ymin >= (previous['hoop_height'] - 30) and (distance([xCoor, yCoor], previous['ball']) < 100)):
# the moment when ball go below basket
if(during_shooting['isShooting']):
if(xCoor >= previous['hoop'][0] and xCoor <= previous['hoop'][2]): # shot
shooting_result['attempts'] += 1
shooting_result['made'] += 1
shot_result['displayFrames'] = 10
shot_result['judgement'] = "SCORE"
print("SCORE")
# draw green trace when miss
points = np.asarray(during_shooting['balls_during_shooting'], dtype=np.int32)
cv2.polylines(trace, [points], False, color=(82, 168, 50), thickness=2, lineType=cv2.LINE_AA)
for ballCoor in during_shooting['balls_during_shooting']:
cv2.circle(img=trace, center=(ballCoor[0], ballCoor[1]), radius=10,
color=(82, 168, 50), thickness=-1)
else: # miss
shooting_result['attempts'] += 1
shooting_result['miss'] += 1
shot_result['displayFrames'] = 10
shot_result['judgement'] = "MISS"
print("miss")
# draw red trace when miss
points = np.asarray(during_shooting['balls_during_shooting'], dtype=np.int32)
cv2.polylines(trace, [points], color=(0, 0, 255), isClosed=False, thickness=2, lineType=cv2.LINE_AA)
for ballCoor in during_shooting['balls_during_shooting']:
cv2.circle(img=trace, center=(ballCoor[0], ballCoor[1]), radius=10,
color=(0, 0, 255), thickness=-1)
# reset all variables
trajectory_fit(during_shooting['balls_during_shooting'], height, width, shot_result['judgement'], fig)
during_shooting['balls_during_shooting'].clear()
during_shooting['isShooting'] = False
shooting_pose['ballInHand_frames_list'].append(shooting_pose['ballInHand_frames'])
print("ball in hand frames: ", shooting_pose['ballInHand_frames'])
shooting_pose['ballInHand_frames'] = 0
print("elbow angle: ", shooting_pose['elbow_angle'])
print("knee angle: ", shooting_pose['knee_angle'])
shooting_pose['elbow_angle_list'].append(shooting_pose['elbow_angle'])
shooting_pose['knee_angle_list'].append(shooting_pose['knee_angle'])
shooting_pose['elbow_angle'] = 370
shooting_pose['knee_angle'] = 370
#draw blue circle
cv2.circle(img=frame, center=(xCoor, yCoor), radius=10,
color=(255, 0, 0), thickness=-1)
cv2.circle(img=trace, center=(xCoor, yCoor), radius=10,
color=(255, 0, 0), thickness=-1)
previous['ball'][0] = xCoor
previous['ball'][1] = yCoor
if(classes[0][i] == 2): # Rim
# cover previous hoop with white rectangle
cv2.rectangle(
trace, (previous['hoop'][0], previous['hoop'][1]), (previous['hoop'][2], previous['hoop'][3]), (255, 255, 255), 5)
cv2.rectangle(frame, (xmin, ymax),
(xmax, ymin), (48, 124, 255), 5)
cv2.rectangle(trace, (xmin, ymax),
(xmax, ymin), (48, 124, 255), 5)
#display judgement after shot
if(shot_result['displayFrames']):
if(shot_result['judgement'] == "MISS"):
cv2.putText(frame, shot_result['judgement'], (xCoor - 65, yCoor - 65),
cv2.FONT_HERSHEY_COMPLEX, 3, (0, 0, 255), 8)
else:
cv2.putText(frame, shot_result['judgement'], (xCoor - 65, yCoor - 65),
cv2.FONT_HERSHEY_COMPLEX, 3, (82, 168, 50), 8)
previous['hoop'][0] = xmin
previous['hoop'][1] = ymax
previous['hoop'][2] = xmax
previous['hoop'][3] = ymin
previous['hoop_height'] = max(ymin, previous['hoop_height'])
combined = np.concatenate((frame, trace), axis=1)
return combined, trace