athulnambiar's picture
Upload 2 files
703780e verified
raw
history blame
3.71 kB
# app.py
import streamlit as st
import cv2
import numpy as np
from ultralytics import YOLO
import supervision as sv
from scipy.spatial import distance as dist
import tempfile
# Initialize components
model = YOLO('yolov8s.pt')
tracker = sv.ByteTrack()
# Streamlit UI
st.title("⚽️ Player Tracking System")
uploaded_video = st.file_uploader("Upload match video", type=["mp4", "mov"])
calibration_dist = st.number_input("Field width in meters (for speed calibration):", value=68.0)
# Initialize session state
if 'player_data' not in st.session_state:
st.session_state.player_data = {}
if uploaded_video:
tfile = tempfile.NamedTemporaryFile(delete=False)
tfile.write(uploaded_video.read())
cap = cv2.VideoCapture(tfile.name)
fps = cap.get(cv2.CAP_PROP_FPS)
frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
pixels_per_meter = frame_width / calibration_dist if calibration_dist > 0 else 1.0
st_frame = st.empty()
frame_count = 0
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
# Detection + tracking
results = model(frame)[0]
detections = sv.Detections.from_ultralytics(results)
detections = tracker.update_with_detections(detections)
for detection in detections:
track_id = int(detection[4])
bbox = detection[0]
centroid = (int((bbox[0]+bbox[2])/2), int((bbox[1]+bbox[3])/2))
speed = 0.0 # Initialize speed for all cases
# Initialize new player
if track_id not in st.session_state.player_data:
st.session_state.player_data[track_id] = {
'positions': [centroid],
'timestamps': [frame_count/fps],
'distance': 0.0,
'speeds': []
}
else:
# Calculate movement metrics
prev_pos = st.session_state.player_data[track_id]['positions'][-1]
time_diff = (frame_count/fps) - st.session_state.player_data[track_id]['timestamps'][-1]
pixel_dist = dist.euclidean(prev_pos, centroid)
speed_px = pixel_dist / time_diff if time_diff > 0 else 0.0
speed = speed_px * pixels_per_meter # Convert to m/s
# Update player record
st.session_state.player_data[track_id]['positions'].append(centroid)
st.session_state.player_data[track_id]['timestamps'].append(frame_count/fps)
st.session_state.player_data[track_id]['distance'] += pixel_dist
st.session_state.player_data[track_id]['speeds'].append(speed)
# Annotation with failsafe
label = f"ID:{track_id} Speed:{speed:.1f}m/s"
cv2.rectangle(frame, (int(bbox[0]), int(bbox[1])),
(int(bbox[2]), int(bbox[3])), (0,255,0), 2)
cv2.putText(frame, label, (int(bbox[0]), int(bbox[1]-10)),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,255,0), 1)
st_frame.image(frame, channels="BGR")
frame_count += 1
cap.release()
# Display final analytics
st.subheader("Player Statistics")
for player_id, data in st.session_state.player_data.items():
avg_speed = np.mean(data['speeds']) if data['speeds'] else 0
st.write(f"""
**Player {player_id}**
- Total distance: {data['distance'] * pixels_per_meter:.2f}m
- Avg speed: {avg_speed:.1f}m/s
- Max speed: {np.max(data['speeds']):.1f}m/s
- Active duration: {data['timestamps'][-1]-data['timestamps'][0]:.1f}s
""")