Spaces:
Runtime error
Runtime error
| 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) | |