Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -16,9 +16,10 @@ BALL_DIAMETER = 0.073 # meters (approx. cricket ball diameter)
|
|
16 |
FRAME_RATE = 20 # Input video frame rate
|
17 |
SLOW_MOTION_FACTOR = 3 # Adjusted for 20 FPS
|
18 |
CONF_THRESHOLD = 0.25 # Confidence threshold for detection
|
19 |
-
IMPACT_ZONE_Y = 0.
|
20 |
-
PITCH_ZONE_Y = 0.
|
21 |
-
IMPACT_DELTA_Y =
|
|
|
22 |
|
23 |
def process_video(video_path):
|
24 |
if not os.path.exists(video_path):
|
@@ -40,11 +41,15 @@ def process_video(video_path):
|
|
40 |
detections = [det for det in results[0].boxes if det.cls == 0] # Class 0 is cricketBall
|
41 |
if len(detections) == 1: # Only consider frames with exactly one detection
|
42 |
x1, y1, x2, y2 = detections[0].xyxy[0].cpu().numpy()
|
43 |
-
|
|
|
|
|
44 |
detection_frames.append(frame_count - 1) # 0-based index
|
45 |
cv2.rectangle(frame, (int(x1), int(y1)), (int(x2), int(y2)), (0, 255, 0), 2)
|
|
|
|
|
|
|
46 |
frames[-1] = frame
|
47 |
-
debug_log.append(f"Frame {frame_count}: {len(detections)} ball detections")
|
48 |
cap.release()
|
49 |
|
50 |
if not ball_positions:
|
@@ -64,28 +69,36 @@ def estimate_trajectory(ball_positions, detection_frames, frames):
|
|
64 |
y_coords = [pos[1] for pos in ball_positions]
|
65 |
times = np.array(detection_frames) / FRAME_RATE
|
66 |
|
67 |
-
# Pitch point: first
|
68 |
pitch_idx = 0
|
69 |
for i, y in enumerate(y_coords):
|
70 |
if y > frame_height * PITCH_ZONE_Y:
|
71 |
pitch_idx = i
|
72 |
break
|
|
|
|
|
|
|
73 |
pitch_point = ball_positions[pitch_idx]
|
74 |
pitch_frame = detection_frames[pitch_idx]
|
75 |
|
76 |
-
# Impact point: sudden y-change or y exceeds IMPACT_ZONE_Y
|
77 |
impact_idx = None
|
78 |
for i in range(1, len(y_coords)):
|
|
|
|
|
79 |
if (y_coords[i] > frame_height * IMPACT_ZONE_Y or
|
80 |
-
|
81 |
impact_idx = i
|
82 |
break
|
83 |
if impact_idx is None:
|
84 |
impact_idx = len(ball_positions) - 1
|
|
|
|
|
|
|
85 |
impact_point = ball_positions[impact_idx]
|
86 |
impact_frame = detection_frames[impact_idx]
|
87 |
|
88 |
-
# Use only detected positions for trajectory
|
89 |
x_coords = x_coords[:impact_idx + 1]
|
90 |
y_coords = y_coords[:impact_idx + 1]
|
91 |
times = times[:impact_idx + 1]
|
@@ -105,7 +118,7 @@ def estimate_trajectory(ball_positions, detection_frames, frames):
|
|
105 |
y_full = fy(t_full)
|
106 |
full_trajectory = list(zip(x_full, y_full))
|
107 |
|
108 |
-
debug_log = (f"
|
109 |
f"Pitch point at frame {pitch_frame + 1}: ({pitch_point[0]:.1f}, {pitch_point[1]:.1f})\n"
|
110 |
f"Impact point at frame {impact_frame + 1}: ({impact_point[0]:.1f}, {impact_point[1]:.1f})")
|
111 |
return full_trajectory, vis_trajectory, pitch_point, pitch_frame, impact_point, impact_frame, debug_log
|
|
|
16 |
FRAME_RATE = 20 # Input video frame rate
|
17 |
SLOW_MOTION_FACTOR = 3 # Adjusted for 20 FPS
|
18 |
CONF_THRESHOLD = 0.25 # Confidence threshold for detection
|
19 |
+
IMPACT_ZONE_Y = 0.80 # Fraction of frame height for impact zone
|
20 |
+
PITCH_ZONE_Y = 0.80 # Fraction of frame height for pitch zone
|
21 |
+
IMPACT_DELTA_Y = 75 # Pixels for detecting sudden y-position change
|
22 |
+
IMPACT_DELTA_X = 50 # Pixels for x-position stability
|
23 |
|
24 |
def process_video(video_path):
|
25 |
if not os.path.exists(video_path):
|
|
|
41 |
detections = [det for det in results[0].boxes if det.cls == 0] # Class 0 is cricketBall
|
42 |
if len(detections) == 1: # Only consider frames with exactly one detection
|
43 |
x1, y1, x2, y2 = detections[0].xyxy[0].cpu().numpy()
|
44 |
+
x_center = (x1 + x2) / 2
|
45 |
+
y_center = (y1 + y2) / 2
|
46 |
+
ball_positions.append([x_center, y_center])
|
47 |
detection_frames.append(frame_count - 1) # 0-based index
|
48 |
cv2.rectangle(frame, (int(x1), int(y1)), (int(x2), int(y2)), (0, 255, 0), 2)
|
49 |
+
debug_log.append(f"Frame {frame_count}: 1 ball detection at (x: {x_center:.1f}, y: {y_center:.1f})")
|
50 |
+
else:
|
51 |
+
debug_log.append(f"Frame {frame_count}: {len(detections)} ball detections (ignored)")
|
52 |
frames[-1] = frame
|
|
|
53 |
cap.release()
|
54 |
|
55 |
if not ball_positions:
|
|
|
69 |
y_coords = [pos[1] for pos in ball_positions]
|
70 |
times = np.array(detection_frames) / FRAME_RATE
|
71 |
|
72 |
+
# Pitch point: first detection where y exceeds PITCH_ZONE_Y
|
73 |
pitch_idx = 0
|
74 |
for i, y in enumerate(y_coords):
|
75 |
if y > frame_height * PITCH_ZONE_Y:
|
76 |
pitch_idx = i
|
77 |
break
|
78 |
+
else:
|
79 |
+
debug_log = "Warning: No pitch point detected (y never exceeds PITCH_ZONE_Y), using first detection"
|
80 |
+
pitch_idx = 0
|
81 |
pitch_point = ball_positions[pitch_idx]
|
82 |
pitch_frame = detection_frames[pitch_idx]
|
83 |
|
84 |
+
# Impact point: sudden y-change, x stability, or y exceeds IMPACT_ZONE_Y
|
85 |
impact_idx = None
|
86 |
for i in range(1, len(y_coords)):
|
87 |
+
delta_y = abs(y_coords[i] - y_coords[i-1])
|
88 |
+
delta_x = abs(x_coords[i] - x_coords[i-1])
|
89 |
if (y_coords[i] > frame_height * IMPACT_ZONE_Y or
|
90 |
+
(delta_y > IMPACT_DELTA_Y and delta_x < IMPACT_DELTA_X)):
|
91 |
impact_idx = i
|
92 |
break
|
93 |
if impact_idx is None:
|
94 |
impact_idx = len(ball_positions) - 1
|
95 |
+
debug_log = f"Warning: No impact point detected (no sudden y-change or y > IMPACT_ZONE_Y), using last detection (frame {detection_frames[impact_idx] + 1})"
|
96 |
+
else:
|
97 |
+
debug_log = ""
|
98 |
impact_point = ball_positions[impact_idx]
|
99 |
impact_frame = detection_frames[impact_idx]
|
100 |
|
101 |
+
# Use only detected positions up to impact for trajectory
|
102 |
x_coords = x_coords[:impact_idx + 1]
|
103 |
y_coords = y_coords[:impact_idx + 1]
|
104 |
times = times[:impact_idx + 1]
|
|
|
118 |
y_full = fy(t_full)
|
119 |
full_trajectory = list(zip(x_full, y_full))
|
120 |
|
121 |
+
debug_log = (f"{debug_log}\nTrajectory estimated successfully\n"
|
122 |
f"Pitch point at frame {pitch_frame + 1}: ({pitch_point[0]:.1f}, {pitch_point[1]:.1f})\n"
|
123 |
f"Impact point at frame {impact_frame + 1}: ({impact_point[0]:.1f}, {impact_point[1]:.1f})")
|
124 |
return full_trajectory, vis_trajectory, pitch_point, pitch_frame, impact_point, impact_frame, debug_log
|