Newer
Older
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
import cv2
import numpy as np
import sys
sys.path.append('../')
import constants
from utils import (
convert_meters_to_pixel_distance,
convert_pixel_distance_to_meters,
get_foot_position,
get_closest_keypoint_index,
get_height_of_bbox,
measure_xy_distance,
get_center_of_bbox,
measure_distance
)
class MiniCourt():
def __init__(self,frame):
self.drawing_rectangle_width = 250
self.drawing_rectangle_height = 500
self.buffer = 50
self.padding_court=20
self.set_canvas_background_box_position(frame)
self.set_mini_court_position()
self.set_court_drawing_key_points()
self.set_court_lines()
def convert_meters_to_pixels(self, meters):
return convert_meters_to_pixel_distance(meters,
constants.DOUBLE_LINE_WIDTH,
self.court_drawing_width
)
def set_court_drawing_key_points(self):
drawing_key_points = [0]*28
# point 0
drawing_key_points[0] , drawing_key_points[1] = int(self.court_start_x), int(self.court_start_y)
# point 1
drawing_key_points[2] , drawing_key_points[3] = int(self.court_end_x), int(self.court_start_y)
# point 2
drawing_key_points[4] = int(self.court_start_x)
drawing_key_points[5] = self.court_start_y + self.convert_meters_to_pixels(constants.HALF_COURT_LINE_HEIGHT*2)
# point 3
drawing_key_points[6] = drawing_key_points[0] + self.court_drawing_width
drawing_key_points[7] = drawing_key_points[5]
# #point 4
drawing_key_points[8] = drawing_key_points[0] + self.convert_meters_to_pixels(constants.DOUBLE_ALLY_DIFFERENCE)
drawing_key_points[9] = drawing_key_points[1]
# #point 5
drawing_key_points[10] = drawing_key_points[4] + self.convert_meters_to_pixels(constants.DOUBLE_ALLY_DIFFERENCE)
drawing_key_points[11] = drawing_key_points[5]
# #point 6
drawing_key_points[12] = drawing_key_points[2] - self.convert_meters_to_pixels(constants.DOUBLE_ALLY_DIFFERENCE)
drawing_key_points[13] = drawing_key_points[3]
# #point 7
drawing_key_points[14] = drawing_key_points[6] - self.convert_meters_to_pixels(constants.DOUBLE_ALLY_DIFFERENCE)
drawing_key_points[15] = drawing_key_points[7]
# #point 8
drawing_key_points[16] = drawing_key_points[8]
drawing_key_points[17] = drawing_key_points[9] + self.convert_meters_to_pixels(constants.NO_MANS_LAND_HEIGHT)
# # #point 9
drawing_key_points[18] = drawing_key_points[16] + self.convert_meters_to_pixels(constants.SINGLE_LINE_WIDTH)
drawing_key_points[19] = drawing_key_points[17]
# #point 10
drawing_key_points[20] = drawing_key_points[10]
drawing_key_points[21] = drawing_key_points[11] - self.convert_meters_to_pixels(constants.NO_MANS_LAND_HEIGHT)
# # #point 11
drawing_key_points[22] = drawing_key_points[20] + self.convert_meters_to_pixels(constants.SINGLE_LINE_WIDTH)
drawing_key_points[23] = drawing_key_points[21]
# # #point 12
drawing_key_points[24] = int((drawing_key_points[16] + drawing_key_points[18])/2)
drawing_key_points[25] = drawing_key_points[17]
# # #point 13
drawing_key_points[26] = int((drawing_key_points[20] + drawing_key_points[22])/2)
drawing_key_points[27] = drawing_key_points[21]
self.drawing_key_points=drawing_key_points
def set_court_lines(self):
self.lines = [
(0, 2),
(4, 5),
(6,7),
(1,3),
(0,1),
(8,9),
(10,11),
(10,11),
(2,3)
]
def set_mini_court_position(self):
self.court_start_x = self.start_x + self.padding_court
self.court_start_y = self.start_y + self.padding_court
self.court_end_x = self.end_x - self.padding_court
self.court_end_y = self.end_y - self.padding_court
self.court_drawing_width = self.court_end_x - self.court_start_x
def set_canvas_background_box_position(self,frame):
frame= frame.copy()
self.end_x = frame.shape[1] - self.buffer
self.end_y = self.buffer + self.drawing_rectangle_height
self.start_x = self.end_x - self.drawing_rectangle_width
self.start_y = self.end_y - self.drawing_rectangle_height
def draw_court(self,frame):
for i in range(0, len(self.drawing_key_points),2):
x = int(self.drawing_key_points[i])
y = int(self.drawing_key_points[i+1])
cv2.circle(frame, (x,y),5, (0,0,255),-1)
# draw Lines
for line in self.lines:
start_point = (int(self.drawing_key_points[line[0]*2]), int(self.drawing_key_points[line[0]*2+1]))
end_point = (int(self.drawing_key_points[line[1]*2]), int(self.drawing_key_points[line[1]*2+1]))
cv2.line(frame, start_point, end_point, (0, 0, 0), 2)
# Draw net
net_start_point = (self.drawing_key_points[0], int((self.drawing_key_points[1] + self.drawing_key_points[5])/2))
net_end_point = (self.drawing_key_points[2], int((self.drawing_key_points[1] + self.drawing_key_points[5])/2))
cv2.line(frame, net_start_point, net_end_point, (255, 0, 0), 2)
return frame
def draw_background_rectangle(self,frame):
shapes = np.zeros_like(frame,np.uint8)
# Draw the rectangle
cv2.rectangle(shapes, (self.start_x, self.start_y), (self.end_x, self.end_y), (255, 255, 255), cv2.FILLED)
out = frame.copy()
alpha=0.5
mask = shapes.astype(bool)
out[mask] = cv2.addWeighted(frame, alpha, shapes, 1 - alpha, 0)[mask]
return out
def draw_mini_court(self,frames):
output_frames = []
for frame in frames:
frame = self.draw_background_rectangle(frame)
frame = self.draw_court(frame)
output_frames.append(frame)
return output_frames
def get_start_point_of_mini_court(self):
return (self.court_start_x,self.court_start_y)
def get_width_of_mini_court(self):
return self.court_drawing_width
def get_court_drawing_keypoints(self):
return self.drawing_key_points
def get_mini_court_coordinates(self,
object_position,
closest_key_point,
closest_key_point_index,
player_height_in_pixels,
player_height_in_meters
):
distance_from_keypoint_x_pixels, distance_from_keypoint_y_pixels = measure_xy_distance(object_position, closest_key_point)
# Conver pixel distance to meters
distance_from_keypoint_x_meters = convert_pixel_distance_to_meters(distance_from_keypoint_x_pixels,
player_height_in_meters,
player_height_in_pixels
)
distance_from_keypoint_y_meters = convert_pixel_distance_to_meters(distance_from_keypoint_y_pixels,
player_height_in_meters,
player_height_in_pixels
)
# Convert to mini court coordinates
mini_court_x_distance_pixels = self.convert_meters_to_pixels(distance_from_keypoint_x_meters)
mini_court_y_distance_pixels = self.convert_meters_to_pixels(distance_from_keypoint_y_meters)
closest_mini_coourt_keypoint = ( self.drawing_key_points[closest_key_point_index*2],
self.drawing_key_points[closest_key_point_index*2+1]
)
mini_court_player_position = (closest_mini_coourt_keypoint[0]+mini_court_x_distance_pixels,
closest_mini_coourt_keypoint[1]+mini_court_y_distance_pixels
)
return mini_court_player_position
def convert_bounding_boxes_to_mini_court_coordinates(self,player_boxes, ball_boxes, original_court_key_points ):
player_heights = {
1: constants.PLAYER_1_HEIGHT_METERS,
2: constants.PLAYER_2_HEIGHT_METERS
}
output_player_boxes= []
output_ball_boxes= []
for frame_num, player_bbox in enumerate(player_boxes):
ball_box = ball_boxes[frame_num][1]
ball_position = get_center_of_bbox(ball_box)
closest_player_id_to_ball = min(player_bbox.keys(), key=lambda x: measure_distance(ball_position, get_center_of_bbox(player_bbox[x])))
output_player_bboxes_dict = {}
for player_id, bbox in player_bbox.items():
foot_position = get_foot_position(bbox)
# Get The closest keypoint in pixels
closest_key_point_index = get_closest_keypoint_index(foot_position,original_court_key_points, [0,2,12,13])
closest_key_point = (original_court_key_points[closest_key_point_index*2],
original_court_key_points[closest_key_point_index*2+1])
# Get Player height in pixels
frame_index_min = max(0, frame_num-20)
frame_index_max = min(len(player_boxes), frame_num+50)
bboxes_heights_in_pixels = [get_height_of_bbox(player_boxes[i][player_id]) for i in range (frame_index_min,frame_index_max)]
max_player_height_in_pixels = max(bboxes_heights_in_pixels)
mini_court_player_position = self.get_mini_court_coordinates(foot_position,
closest_key_point,
closest_key_point_index,
max_player_height_in_pixels,
player_heights[player_id]
)
output_player_bboxes_dict[player_id] = mini_court_player_position
if closest_player_id_to_ball == player_id:
# Get The closest keypoint in pixels
closest_key_point_index = get_closest_keypoint_index(ball_position,original_court_key_points, [0,2,12,13])
closest_key_point = (original_court_key_points[closest_key_point_index*2],
original_court_key_points[closest_key_point_index*2+1])
mini_court_player_position = self.get_mini_court_coordinates(ball_position,
closest_key_point,
closest_key_point_index,
max_player_height_in_pixels,
player_heights[player_id]
)
output_ball_boxes.append({1:mini_court_player_position})
output_player_boxes.append(output_player_bboxes_dict)
return output_player_boxes , output_ball_boxes
def draw_points_on_mini_court(self,frames,postions, color=(0,255,0)):
for frame_num, frame in enumerate(frames):
for _, position in postions[frame_num].items():
x,y = position
x= int(x)
y= int(y)
cv2.circle(frame, (x,y), 5, color, -1)
return frames