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("""
""", 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('
", unsafe_allow_html=True)
# Main Content
st.markdown('⚾ Baseball Vision Analytics
', 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('', 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('
', 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('', 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('
', unsafe_allow_html=True)
with tab2:
# Performance Analytics Section
col1, col2 = st.columns(2)
with col1:
st.markdown('', unsafe_allow_html=True)
st.subheader("Strike Zone Analysis")
fig = plot_strike_zone()
st.plotly_chart(fig, use_container_width=True)
st.markdown('
', unsafe_allow_html=True)
with col2:
st.markdown('', 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('
', 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(
"""
Powered by Advanced Baseball Analytics and OpenAI Vision API
© 2024 Baseball Vision Analytics
""",
unsafe_allow_html=True
)
if __name__ == "__main__":
main()