import gradio as gr import pandas as pd from athletic_performance import analyze_youtube_video, analyze_video_file, get_performance_insights def analyze_jump_from_youtube(youtube_url, user_height_cm, progress=gr.Progress()): """Main analysis function for Gradio interface.""" # Create progress callback for the athletic_performance module def progress_callback(prog, desc): progress(prog, desc=desc) # Call the core analysis function result = analyze_youtube_video(youtube_url, user_height_cm, progress_callback) # Handle errors if "error" in result: return f"❌ {result['error']}", None, None, None if result is None: return "⚠️ Could not analyze jump. Make sure the video shows a person clearly performing a vertical jump.", None, None, None # Format results for display results_text = f""" ## 🎉 Jump Analysis Results ### 📊 Performance Metrics - **Jump Height**: {result['jump_height_cm']:.2f} cm - **Flight Time**: {result['flight_time_s']:.3f} seconds - **Normalized Rise**: {result['normalized_rise']:.3f} ({result['normalized_rise']*100:.1f}%) ### 📹 Video Information - **Total Frames**: {result['frames']} - **Frame Rate**: {result['fps']:.2f} FPS - **Video File**: {result['video']} ### 📈 Performance Insights """ # Add performance insights using the new function insights = get_performance_insights(result['jump_height_cm'], result['flight_time_s']) for insight in insights: results_text += f"{insight}\n" # Add technique analysis insights results_text += f""" ### 🎯 Technique Analysis - **Knee Position**: Analyzed for valgus and injury prevention - **Shoulder Position**: Evaluated overhead squat mechanics - **Movement Quality**: Real-time feedback on form """ # Create a results dataframe for the table results_df = pd.DataFrame([ ["Jump Height", f"{result['jump_height_cm']:.2f} cm"], ["Flight Time", f"{result['flight_time_s']:.3f} seconds"], ["Normalized Rise", f"{result['normalized_rise']*100:.1f}%"], ["Video Frames", f"{result['frames']}"], ["Frame Rate", f"{result['fps']:.2f} FPS"], ], columns=["Metric", "Value"]) # Return overlay video if available overlay_video = result.get('overlay_video', None) return results_text, results_df, overlay_video, "✅ Analysis completed successfully!" def analyze_jump_from_file(video_file, user_height_cm, progress=gr.Progress()): """Analysis function for uploaded video files.""" # Create progress callback for the athletic_performance module def progress_callback(prog, desc): progress(prog, desc=desc) # Call the core analysis function video_path = video_file.name if video_file else None result = analyze_video_file(video_path, user_height_cm, progress_callback) # Handle errors if "error" in result: return f"❌ {result['error']}", None, None, None if result is None: return "⚠️ Could not analyze jump. Make sure the video shows a person clearly performing a vertical jump.", None, None, None # Format results (same as YouTube function) results_text = f""" ## 🎉 Jump Analysis Results ### 📊 Performance Metrics - **Jump Height**: {result['jump_height_cm']:.2f} cm - **Flight Time**: {result['flight_time_s']:.3f} seconds - **Normalized Rise**: {result['normalized_rise']:.3f} ({result['normalized_rise']*100:.1f}%) ### 📹 Video Information - **Total Frames**: {result['frames']} - **Frame Rate**: {result['fps']:.2f} FPS - **Video File**: {result['video']} ### 📈 Performance Insights """ # Add performance insights using the new function insights = get_performance_insights(result['jump_height_cm'], result['flight_time_s']) for insight in insights: results_text += f"{insight}\n" # Add technique analysis insights results_text += f""" ### 🎯 Technique Analysis - **Knee Position**: Analyzed for valgus and injury prevention - **Shoulder Position**: Evaluated overhead squat mechanics - **Movement Quality**: Real-time feedback on form """ # Create a results dataframe for the table results_df = pd.DataFrame([ ["Jump Height", f"{result['jump_height_cm']:.2f} cm"], ["Flight Time", f"{result['flight_time_s']:.3f} seconds"], ["Normalized Rise", f"{result['normalized_rise']*100:.1f}%"], ["Video Frames", f"{result['frames']}"], ["Frame Rate", f"{result['fps']:.2f} FPS"], ], columns=["Metric", "Value"]) # Return overlay video if available overlay_video = result.get('overlay_video', None) return results_text, results_df, overlay_video, "✅ Analysis completed successfully!" # Create Gradio interface def create_interface(): with gr.Blocks(title="🏃‍♂️ Athletic Ability Analysis") as app: gr.Markdown(""" # 🏃‍♂️ Athletic Ability Analysis Analyze jumping performance from videos using computer vision and pose estimation. Upload a video or provide a YouTube URL to get detailed metrics about jump height, flight time, and athletic performance. ## 🆕 New Features - **🎥 Video Overlays**: Watch your movement with real-time technique analysis - **🦵 Knee Injury Prevention**: Detect knee valgus and movement patterns - **💪 Shoulder Position Analysis**: Evaluate overhead squat mechanics - **📊 Performance Insights**: Get personalized coaching feedback ## 📋 Instructions 1. Enter your height in centimeters 2. Choose either YouTube URL or file upload 3. Wait for the analysis to complete 4. View your detailed jump performance results and technique analysis video """) with gr.Row(): user_height = gr.Number( label="Your Height (cm)", value=175, minimum=100, maximum=250 ) gr.Markdown("💡 *Enter your height in centimeters for accurate jump height calculation*") with gr.Tabs(): # YouTube URL Tab with gr.TabItem("🎥 YouTube Video"): gr.Markdown("📺 *Paste a YouTube URL containing a video of someone jumping*") youtube_url = gr.Textbox( label="YouTube URL", placeholder="https://youtube.com/watch?v=..." ) youtube_btn = gr.Button("🚀 Analyze YouTube Video", variant="primary") # File Upload Tab with gr.TabItem("📁 Upload Video"): gr.Markdown("📁 *Upload a video file showing someone performing a jump*") video_file = gr.File( label="Upload Video File", file_types=[".mp4", ".avi", ".mov", ".mkv", ".webm"] ) file_btn = gr.Button("🚀 Analyze Uploaded Video", variant="primary") # Results section gr.Markdown("## 📊 Analysis Results") with gr.Row(): with gr.Column(scale=2): results_text = gr.Markdown(label="Results") with gr.Column(scale=1): results_table = gr.Dataframe( label="Metrics Summary", headers=["Metric", "Value"], datatype=["str", "str"] ) # Video output section gr.Markdown("## 🎥 Technique Analysis Video") gr.Markdown("📹 *Watch your movement with real-time technique feedback overlays*") overlay_video = gr.Video( label="Analysis Video with Overlays", interactive=False, info="Video showing pose landmarks and technique analysis" ) status_message = gr.Textbox(label="Status", interactive=False) # Video requirements gr.Markdown(""" ## 📝 Video Requirements For best results, ensure your videos meet these criteria: - **Full body visible**: The person should be completely visible in the frame - **Clear movement**: Good lighting and minimal background clutter - **Vertical jumps**: Works best with straight vertical jumps - **Duration**: 3-30 seconds is optimal - **Quality**: Higher quality videos produce better results - **Public videos**: For YouTube, ensure the video is not private ## 🔬 How it Works 1. **Pose Detection**: Uses Google's MediaPipe to detect human pose landmarks 2. **Hip Tracking**: Tracks the midpoint between left and right hip joints 3. **Jump Analysis**: Calculates metrics based on hip trajectory: - Jump height relative to your body size - Flight time during the airborne phase - Normalized rise showing jump efficiency 4. **Technique Analysis**: Real-time movement assessment: - Knee position analysis for injury prevention - Shoulder position for overhead squat mechanics - Visual overlays with color-coded feedback """) # Event handlers youtube_btn.click( fn=analyze_jump_from_youtube, inputs=[youtube_url, user_height], outputs=[results_text, results_table, overlay_video, status_message] ) file_btn.click( fn=analyze_jump_from_file, inputs=[video_file, user_height], outputs=[results_text, results_table, overlay_video, status_message] ) # Example section gr.Examples( examples=[ ["https://www.youtube.com/watch?v=dQw4w9WgXcQ", 175], # This is just a placeholder ], inputs=[youtube_url, user_height], label="📚 Example (Replace with actual jump video URLs)" ) return app if __name__ == "__main__": app = create_interface() app.launch(debug=True, share=True)