dschandra commited on
Commit
d72a7a2
·
verified ·
1 Parent(s): dfdc644

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +31 -28
app.py CHANGED
@@ -6,9 +6,14 @@ import gradio as gr
6
  from scipy.interpolate import interp1d
7
  import uuid
8
  import os
9
- from OpenGL.GL import *
10
- from OpenGL.GLU import *
11
- from pygame import display, event, QUIT
 
 
 
 
 
12
 
13
  # Load the trained YOLOv8n model
14
  model = YOLO("best.pt")
@@ -64,15 +69,14 @@ def estimate_trajectory_3d(ball_positions, detection_frames, frames):
64
  return None, None, None, None, None, None, "Error: Fewer than 2 valid single-ball detections"
65
  frame_height, frame_width = frames[0].shape[:2]
66
 
67
- # Simple 2D to 3D mapping (approximation)
68
  x_coords = np.array([pos[0] for pos in ball_positions]) / frame_width * PITCH_LENGTH
69
  y_coords = np.array([frame_height - pos[1] for pos in ball_positions]) / frame_height * STUMPS_HEIGHT * 2
70
- z_coords = np.zeros_like(x_coords) # Depth estimation needed (simplified as 0 for now)
71
  times = np.array([i / FRAME_RATE for i in range(len(ball_positions))])
72
 
73
  pitch_idx = 0
74
  for i, y in enumerate(y_coords):
75
- if y < STUMPS_HEIGHT: # Pitch near ground
76
  pitch_idx = i
77
  break
78
  pitch_point = (x_coords[pitch_idx], y_coords[pitch_idx], 0)
@@ -89,7 +93,6 @@ def estimate_trajectory_3d(ball_positions, detection_frames, frames):
89
  impact_point = (x_coords[impact_idx], y_coords[impact_idx], 0)
90
  impact_frame = detection_frames[impact_idx]
91
 
92
- # Interpolate 3D trajectory
93
  fx = interp1d(times[:impact_idx + 1], x_coords[:impact_idx + 1], kind='linear', fill_value="extrapolate")
94
  fy = interp1d(times[:impact_idx + 1], y_coords[:impact_idx + 1], kind='quadratic', fill_value="extrapolate")
95
  fz = interp1d(times[:impact_idx + 1], z_coords[:impact_idx + 1], kind='linear', fill_value="extrapolate")
@@ -104,7 +107,7 @@ def lbw_decision(ball_positions, full_trajectory, frames, pitch_point, impact_po
104
  return "Error: No data", None, None, None
105
  frame_height, frame_width = frames[0].shape[:2]
106
  stumps_x = PITCH_LENGTH / 2
107
- stumps_y = 0 # Ground level
108
  stumps_width = STUMPS_WIDTH
109
 
110
  pitch_x, pitch_y, _ = pitch_point
@@ -130,14 +133,9 @@ def lbw_decision(ball_positions, full_trajectory, frames, pitch_point, impact_po
130
  return f"Out (Ball hits stumps)", full_trajectory, pitch_point, impact_point
131
  return f"Not Out (Missing stumps)", full_trajectory, pitch_point, impact_point
132
 
133
- def init_3d_window(width, height):
134
- pygame.init()
135
- display.set_mode((width, height), DOUBLEBUF | OPENGL)
136
- gluPerspective(45, (width / height), 0.1, 50.0)
137
- glTranslatef(0.0, -5.0, -30)
138
- glEnable(GL_DEPTH_TEST)
139
-
140
  def draw_3d_scene(trajectory, pitch_point, impact_point, decision):
 
 
141
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
142
  glBegin(GL_LINES)
143
  for i in range(len(trajectory) - 1):
@@ -146,7 +144,6 @@ def draw_3d_scene(trajectory, pitch_point, impact_point, decision):
146
  glVertex3f(trajectory[i + 1][0], trajectory[i + 1][1], trajectory[i + 1][2])
147
  glEnd()
148
 
149
- # Draw pitch and stumps
150
  glColor3f(0, 1, 0) # Green pitch
151
  glBegin(GL_QUADS)
152
  glVertex3f(0, 0, 0)
@@ -163,7 +160,6 @@ def draw_3d_scene(trajectory, pitch_point, impact_point, decision):
163
  glVertex3f(PITCH_LENGTH / 2 + STUMPS_WIDTH / 2, STUMPS_HEIGHT, 0)
164
  glEnd()
165
 
166
- # Draw pitching and impact points
167
  if pitch_point:
168
  glColor3f(0, 1, 0) # Green
169
  glPushMatrix()
@@ -178,7 +174,6 @@ def draw_3d_scene(trajectory, pitch_point, impact_point, decision):
178
  glutSolidSphere(0.1, 20, 20)
179
  glPopMatrix()
180
 
181
- # Display decision (simplified text)
182
  if "Out" in decision:
183
  glColor3f(1, 0.65, 0) # Orange
184
  glRasterPos3f(PITCH_LENGTH / 2, STUMPS_HEIGHT, 0)
@@ -187,6 +182,15 @@ def draw_3d_scene(trajectory, pitch_point, impact_point, decision):
187
 
188
  display.flip()
189
 
 
 
 
 
 
 
 
 
 
190
  def drs_review(video):
191
  frames, ball_positions, detection_frames, debug_log = process_video(video)
192
  if not frames:
@@ -194,28 +198,27 @@ def drs_review(video):
194
  full_trajectory, vis_trajectory, pitch_point, pitch_frame, impact_point, impact_frame, trajectory_log = estimate_trajectory_3d(ball_positions, detection_frames, frames)
195
  decision, full_trajectory, pitch_point, impact_point = lbw_decision(ball_positions, full_trajectory, frames, pitch_point, impact_point)
196
 
197
- # Generate 3D visualization (separate window)
198
- init_3d_window(800, 600)
199
- from OpenGL.GLUT import glutInit, glutSolidSphere
200
- glutInit()
201
- for _ in range(100): # Limited frames for demo
202
- draw_3d_scene(full_trajectory, pitch_point, impact_point, decision)
203
- event.pump()
204
 
205
  output_path = f"output_{uuid.uuid4()}.mp4"
206
- # Note: 3D rendering is separate; 2D video output is placeholder
207
  slow_motion_path = None # To be enhanced with 3D export
208
 
209
  debug_output = f"{debug_log}\n{trajectory_log}"
210
  return f"DRS Decision: {decision}\nDebug Log:\n{debug_output}", slow_motion_path
211
 
212
- # Gradio interface (placeholder for 3D)
213
  iface = gr.Interface(
214
  fn=drs_review,
215
  inputs=gr.Video(label="Upload Video Clip"),
216
  outputs=[
217
  gr.Textbox(label="DRS Decision and Debug Log"),
218
- gr.Video(label="3D Visualization (Separate Window)")
219
  ],
220
  title="AI-Powered 3D DRS for LBW",
221
  description="Upload a video clip for 3D DRS analysis with pitching (green), impact (red), and wickets (orange) visualization."
 
6
  from scipy.interpolate import interp1d
7
  import uuid
8
  import os
9
+ try:
10
+ from OpenGL.GL import *
11
+ from OpenGL.GLU import *
12
+ from pygame import display, event, QUIT
13
+ HAS_OPENGL = True
14
+ except ImportError:
15
+ print("Warning: PyOpenGL or Pygame not found. 3D visualization will be disabled. Install with 'pip install PyOpenGL PyOpenGL_accelerate pygame'.")
16
+ HAS_OPENGL = False
17
 
18
  # Load the trained YOLOv8n model
19
  model = YOLO("best.pt")
 
69
  return None, None, None, None, None, None, "Error: Fewer than 2 valid single-ball detections"
70
  frame_height, frame_width = frames[0].shape[:2]
71
 
 
72
  x_coords = np.array([pos[0] for pos in ball_positions]) / frame_width * PITCH_LENGTH
73
  y_coords = np.array([frame_height - pos[1] for pos in ball_positions]) / frame_height * STUMPS_HEIGHT * 2
74
+ z_coords = np.zeros_like(x_coords) # Placeholder for depth
75
  times = np.array([i / FRAME_RATE for i in range(len(ball_positions))])
76
 
77
  pitch_idx = 0
78
  for i, y in enumerate(y_coords):
79
+ if y < STUMPS_HEIGHT:
80
  pitch_idx = i
81
  break
82
  pitch_point = (x_coords[pitch_idx], y_coords[pitch_idx], 0)
 
93
  impact_point = (x_coords[impact_idx], y_coords[impact_idx], 0)
94
  impact_frame = detection_frames[impact_idx]
95
 
 
96
  fx = interp1d(times[:impact_idx + 1], x_coords[:impact_idx + 1], kind='linear', fill_value="extrapolate")
97
  fy = interp1d(times[:impact_idx + 1], y_coords[:impact_idx + 1], kind='quadratic', fill_value="extrapolate")
98
  fz = interp1d(times[:impact_idx + 1], z_coords[:impact_idx + 1], kind='linear', fill_value="extrapolate")
 
107
  return "Error: No data", None, None, None
108
  frame_height, frame_width = frames[0].shape[:2]
109
  stumps_x = PITCH_LENGTH / 2
110
+ stumps_y = 0
111
  stumps_width = STUMPS_WIDTH
112
 
113
  pitch_x, pitch_y, _ = pitch_point
 
133
  return f"Out (Ball hits stumps)", full_trajectory, pitch_point, impact_point
134
  return f"Not Out (Missing stumps)", full_trajectory, pitch_point, impact_point
135
 
 
 
 
 
 
 
 
136
  def draw_3d_scene(trajectory, pitch_point, impact_point, decision):
137
+ if not HAS_OPENGL:
138
+ return
139
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
140
  glBegin(GL_LINES)
141
  for i in range(len(trajectory) - 1):
 
144
  glVertex3f(trajectory[i + 1][0], trajectory[i + 1][1], trajectory[i + 1][2])
145
  glEnd()
146
 
 
147
  glColor3f(0, 1, 0) # Green pitch
148
  glBegin(GL_QUADS)
149
  glVertex3f(0, 0, 0)
 
160
  glVertex3f(PITCH_LENGTH / 2 + STUMPS_WIDTH / 2, STUMPS_HEIGHT, 0)
161
  glEnd()
162
 
 
163
  if pitch_point:
164
  glColor3f(0, 1, 0) # Green
165
  glPushMatrix()
 
174
  glutSolidSphere(0.1, 20, 20)
175
  glPopMatrix()
176
 
 
177
  if "Out" in decision:
178
  glColor3f(1, 0.65, 0) # Orange
179
  glRasterPos3f(PITCH_LENGTH / 2, STUMPS_HEIGHT, 0)
 
182
 
183
  display.flip()
184
 
185
+ def init_3d_window(width, height):
186
+ if not HAS_OPENGL:
187
+ return
188
+ pygame.init()
189
+ display.set_mode((width, height), DOUBLEBUF | OPENGL)
190
+ gluPerspective(45, (width / height), 0.1, 50.0)
191
+ glTranslatef(0.0, -5.0, -30)
192
+ glEnable(GL_DEPTH_TEST)
193
+
194
  def drs_review(video):
195
  frames, ball_positions, detection_frames, debug_log = process_video(video)
196
  if not frames:
 
198
  full_trajectory, vis_trajectory, pitch_point, pitch_frame, impact_point, impact_frame, trajectory_log = estimate_trajectory_3d(ball_positions, detection_frames, frames)
199
  decision, full_trajectory, pitch_point, impact_point = lbw_decision(ball_positions, full_trajectory, frames, pitch_point, impact_point)
200
 
201
+ if HAS_OPENGL:
202
+ init_3d_window(800, 600)
203
+ from OpenGL.GLUT import glutInit, glutSolidSphere
204
+ glutInit()
205
+ for _ in range(100): # Limited frames for demo
206
+ draw_3d_scene(full_trajectory, pitch_point, impact_point, decision)
207
+ event.pump()
208
 
209
  output_path = f"output_{uuid.uuid4()}.mp4"
 
210
  slow_motion_path = None # To be enhanced with 3D export
211
 
212
  debug_output = f"{debug_log}\n{trajectory_log}"
213
  return f"DRS Decision: {decision}\nDebug Log:\n{debug_output}", slow_motion_path
214
 
215
+ # Gradio interface
216
  iface = gr.Interface(
217
  fn=drs_review,
218
  inputs=gr.Video(label="Upload Video Clip"),
219
  outputs=[
220
  gr.Textbox(label="DRS Decision and Debug Log"),
221
+ gr.Video(label="3D Visualization (Separate Window if enabled)")
222
  ],
223
  title="AI-Powered 3D DRS for LBW",
224
  description="Upload a video clip for 3D DRS analysis with pitching (green), impact (red), and wickets (orange) visualization."