DexterSptizu's picture
Create app.py
24d7598 verified
import streamlit as st
import os
from openai import OpenAI
from PIL import Image
import io
import base64
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
import numpy as np
st.set_page_config(
page_title="Baseball Analytics Hub",
layout="wide",
initial_sidebar_state="expanded"
)
# Custom CSS for baseball theme
def apply_custom_css():
st.markdown("""
<style>
.stApp {
max-width: 1400px;
margin: 0 auto;
}
.upload-box {
border: 2px dashed #1E4C96;
border-radius: 10px;
padding: 20px;
text-align: center;
background-color: #f8f9fa;
}
.sidebar-content {
padding: 20px;
background-color: #1E4C96;
color: white;
border-radius: 10px;
}
.response-box {
background-color: #ffffff;
padding: 20px;
border-radius: 10px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.title-text {
color: #1E4C96;
text-align: center;
font-size: 2.5rem;
margin-bottom: 2rem;
}
.stats-card {
background-color: #ffffff;
padding: 20px;
border-radius: 10px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
margin: 10px;
}
</style>
""", unsafe_allow_html=True)
def initialize_session_state():
if 'history' not in st.session_state:
st.session_state.history = []
if 'player_stats' not in st.session_state:
st.session_state.player_stats = {
'batting_avg': [],
'hits': [],
'home_runs': [],
'games': []
}
def encode_image_to_base64(image):
buffered = io.BytesIO()
image.save(buffered, format="PNG")
return base64.b64encode(buffered.getvalue()).decode('utf-8')
def analyze_image(image, question, api_key):
try:
client = OpenAI(api_key=api_key)
base64_image = encode_image_to_base64(image)
# Add baseball-specific context to the prompt
baseball_context = "Analyze this baseball-related image. Consider aspects like player stance, pitch mechanics, field positioning, and game situation. "
enhanced_question = baseball_context + question
completion = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": enhanced_question},
{
"type": "image_url",
"image_url": {
"url": f"data:image/png;base64,{base64_image}"
}
},
],
}
],
max_tokens=500
)
return completion.choices[0].message.content
except Exception as e:
return f"Error: {str(e)}"
def plot_strike_zone():
fig = go.Figure()
fig.add_shape(
type="rect",
x0=-0.85, x1=0.85,
y0=1.5, y1=3.5,
line=dict(color="red", width=2),
fillcolor="rgba(255, 0, 0, 0.1)"
)
fig.add_trace(go.Scatter(
x=np.random.uniform(-1, 1, 10),
y=np.random.uniform(1, 4, 10),
mode='markers',
marker=dict(size=10, color='blue'),
name='Pitches'
))
fig.update_layout(
title="Strike Zone Analysis",
xaxis_title="Horizontal Location (ft)",
yaxis_title="Height (ft)",
template="plotly_white"
)
return fig
def main():
apply_custom_css()
initialize_session_state()
# Sidebar Configuration
with st.sidebar:
st.markdown('<div class="sidebar-content">', unsafe_allow_html=True)
st.header("⚾ Baseball Analytics")
api_key = st.text_input("OpenAI API Key:", type="password")
st.markdown("### 🎯 Baseball Image Analysis")
quick_prompts = [
"Analyze the batting stance and suggest improvements",
"Evaluate the pitcher's mechanics",
"Analyze the fielding position and alignment",
"Identify potential batting technique issues",
"Assess the base running form",
"Analyze the catcher's positioning",
"Evaluate the pitch grip technique"
]
selected_prompt = st.selectbox("Select analysis type:", quick_prompts)
st.markdown("</div>", unsafe_allow_html=True)
# Main Content
st.markdown('<h1 class="title-text">⚾ Baseball Vision Analytics</h1>', unsafe_allow_html=True)
# Create tabs for different features
tab1, tab2 = st.tabs(["Image Analysis", "Performance Analytics"])
with tab1:
# Image Upload Section
col1, col2, col3 = st.columns([1, 2, 1])
with col2:
st.markdown('<div class="upload-box">', unsafe_allow_html=True)
uploaded_file = st.file_uploader(
"Upload baseball image for analysis",
type=['png', 'jpg', 'jpeg'],
help="Upload images of batting, pitching, or fielding"
)
st.markdown('</div>', unsafe_allow_html=True)
if uploaded_file:
image = Image.open(uploaded_file)
# Image Display and Analysis Section
col1, col2 = st.columns([1, 1])
with col1:
st.image(image, use_container_width=True, caption="Uploaded Baseball Image")
with col2:
st.markdown('<div class="response-box">', unsafe_allow_html=True)
question = st.text_input(
"Analysis Focus:",
value=selected_prompt,
key="question_input"
)
if st.button("πŸ” Analyze", use_container_width=True):
if not api_key:
st.error("⚠️ Please enter your OpenAI API key in the sidebar.")
else:
with st.spinner("πŸ”„ Analyzing baseball technique..."):
response = analyze_image(image, question, api_key)
st.markdown("### πŸ“ Analysis Result:")
st.write(response)
st.session_state.history.append({
"question": question,
"response": response,
"timestamp": pd.Timestamp.now().strftime("%Y-%m-%d %H:%M:%S")
})
st.markdown('</div>', unsafe_allow_html=True)
with tab2:
# Performance Analytics Section
col1, col2 = st.columns(2)
with col1:
st.markdown('<div class="stats-card">', unsafe_allow_html=True)
st.subheader("Strike Zone Analysis")
fig = plot_strike_zone()
st.plotly_chart(fig, use_container_width=True)
st.markdown('</div>', unsafe_allow_html=True)
with col2:
st.markdown('<div class="stats-card">', unsafe_allow_html=True)
st.subheader("Key Metrics")
metrics_col1, metrics_col2 = st.columns(2)
with metrics_col1:
st.metric("Pitch Accuracy", "68%", "+2%")
st.metric("Avg Exit Velocity", "92 mph", "-1 mph")
with metrics_col2:
st.metric("Strike Rate", "65%", "+5%")
st.metric("Spin Rate", "2400 rpm", "+100 rpm")
st.markdown('</div>', unsafe_allow_html=True)
# History Section
if st.session_state.history:
st.markdown("### πŸ“œ Previous Analyses")
for item in reversed(st.session_state.history[-5:]):
with st.expander(f"Q: {item['question'][:50]}..."):
st.write(item['response'])
st.caption(f"Analyzed on: {item['timestamp']}")
# Footer
st.markdown("---")
st.markdown(
"""
<div style='text-align: center'>
<p>Powered by Advanced Baseball Analytics and OpenAI Vision API</p>
<p>Β© 2024 Baseball Vision Analytics</p>
</div>
""",
unsafe_allow_html=True
)
if __name__ == "__main__":
main()