|
import gradio as gr |
|
|
|
import os |
|
import numpy as np |
|
|
|
from utils import read_video, save_video |
|
from trackers import Tracker |
|
from team_assigner import TeamAssigner |
|
from player_ball_assigner import PlayerBallAssigner |
|
from camera_movement_estimator import CameraMovementEstimator |
|
from view_transformer import ViewTransformer |
|
from speed_and_distance_estimator import SpeedAndDistance_Estimator |
|
|
|
def process_video(input_video, player_stats=True, ball_stats=True): |
|
print("input: " + input_video) |
|
|
|
video_frames = read_video(input_video) |
|
|
|
|
|
tracker = Tracker('models/best.pt') |
|
|
|
if input_video.endswith("121364_0_small.mp4"): |
|
print("loading cached tracks") |
|
tracks = tracker.get_object_tracks(video_frames, |
|
read_from_stub=True, |
|
stub_path='stubs/track_stub_121364_0_small.pkl') |
|
else: |
|
tracks = tracker.get_object_tracks(video_frames) |
|
|
|
|
|
tracks["ball"] = tracker.interpolate_ball_positions(tracks["ball"]) |
|
|
|
|
|
tracker.add_position_to_tracks(tracks) |
|
|
|
|
|
camera_movement_estimator = CameraMovementEstimator(video_frames[0]) |
|
if input_video.endswith("121364_0_small.mp4"): |
|
print("loading cached camera movements") |
|
camera_movement_per_frame = camera_movement_estimator.get_camera_movement(video_frames, |
|
read_from_stub=True, |
|
stub_path='stubs/camera_movement_stub_121364_0_small.pkl') |
|
else: |
|
camera_movement_per_frame = camera_movement_estimator.get_camera_movement(video_frames) |
|
camera_movement_estimator.add_adjust_positions_to_tracks(tracks, camera_movement_per_frame) |
|
|
|
|
|
view_transformer = ViewTransformer() |
|
view_transformer.add_transformed_position_to_tracks(tracks) |
|
|
|
|
|
speed_and_distance_estimator = SpeedAndDistance_Estimator() |
|
exclude_objects=['referees', 'players', 'ball'] |
|
if player_stats: |
|
exclude_objects.remove('players') |
|
if ball_stats: |
|
exclude_objects.remove('ball') |
|
speed_and_distance_estimator.add_speed_and_distance_to_tracks(tracks, exclude_objects) |
|
|
|
|
|
team_assigner = TeamAssigner() |
|
team_assigner.assign_team_color(video_frames[0], tracks['players'][0]) |
|
|
|
for frame_num, player_track in enumerate(tracks['players']): |
|
for player_id, track in player_track.items(): |
|
team = team_assigner.get_player_team(video_frames[frame_num], track['bbox'], player_id) |
|
tracks['players'][frame_num][player_id]['team'] = team |
|
tracks['players'][frame_num][player_id]['team_color'] = team_assigner.team_colors[team] |
|
|
|
|
|
player_assigner = PlayerBallAssigner() |
|
team_ball_control = [] |
|
for frame_num, player_track in enumerate(tracks['players']): |
|
ball_bbox = tracks['ball'][frame_num][1]['bbox'] |
|
assigned_player = player_assigner.assign_ball_to_player(player_track, ball_bbox) |
|
|
|
if assigned_player != -1: |
|
tracks['players'][frame_num][assigned_player]['has_ball'] = True |
|
team_ball_control.append(tracks['players'][frame_num][assigned_player]['team']) |
|
else: |
|
if team_ball_control: |
|
team_ball_control.append(team_ball_control[-1]) |
|
team_ball_control = np.array(team_ball_control) |
|
|
|
|
|
output_video_frames = tracker.draw_annotations(video_frames, tracks, team_ball_control) |
|
output_video_frames = camera_movement_estimator.draw_camera_movement(output_video_frames, camera_movement_per_frame) |
|
speed_and_distance_estimator.draw_speed_and_distance(output_video_frames, tracks) |
|
|
|
|
|
output_path = 'output_videos/output_video.avi' |
|
save_video(output_video_frames, output_path) |
|
|
|
return output_path |
|
|
|
|
|
title="Football Match Analytics with YOLO and OpenCV" |
|
description=""" |
|
This demo processes football game videos to detect players and referees, track the ball, assign players to teams using color pixel clustering, and compute ball possession per team. |
|
|
|
It also estimates camera movement with Lucas-Kanade optical flow and applies perspective transformation to calculate the real-time speed and total distance traveled by each player and the ball. |
|
|
|
The YOLO detection model was fine-tuned with this dataset: https://universe.roboflow.com/roboflow-jvuqo/football-players-detection-3zvbc/dataset |
|
|
|
Original Tutorial Reference: https://www.youtube.com/watch?v=neBZ6huolkg |
|
|
|
**Note**: this space is running on a CPU, so inferencing new video may take some time. (Avg time during test: 1min processing per 5 second of video)""" |
|
|
|
examples = [["input_videos/121364_0_small.mp4", True, True]] |
|
|
|
interface = gr.Interface(fn=process_video, |
|
inputs=[ |
|
gr.Video(label="Upload Video (mp4, avi, mov) Max: 30sec"), |
|
gr.Checkbox(label="Include Player Stats", value=True), |
|
gr.Checkbox(label="Include Ball Stats", value=True) |
|
], |
|
outputs=gr.Video(label="Processed Video"), |
|
examples=examples, |
|
live=False, |
|
title=title, |
|
description=description) |
|
|
|
interface.launch(debug=True, show_error = True) |
|
|