styx102 commited on
Commit
4c9db81
Β·
verified Β·
1 Parent(s): a6d3661

Upload 2 files

Browse files
Files changed (2) hide show
  1. app.py +147 -59
  2. requirements.txt +6 -0
app.py CHANGED
@@ -1,73 +1,132 @@
1
 
2
  import gradio as gr
3
- from datetime import datetime
 
 
 
 
 
 
 
 
 
4
 
5
- # PAGE 1: Daily Plan Generator
6
- def generate_daily_plan(wake_time, swim_duration, gym_today, sleep_hours, goal):
 
 
 
7
  plan = []
8
  if sleep_hours < 7:
9
- plan.append("⚠️ Less than 7 hours of sleep β€” consider adjusting recovery.")
10
- plan.append(f"πŸŒ… Wake at {wake_time}")
11
- plan.append(f"πŸŠβ€β™‚οΈ Swim: {swim_duration} min β€” Focus: {goal}")
12
  if gym_today:
13
- plan.append("πŸ‹οΈβ€β™‚οΈ Gym: Yes β€” tailor to today's goal")
 
 
 
 
 
14
  else:
15
- plan.append("πŸ’ͺ Gym: Rest or mobility work")
16
- plan.append("🍽️ Nutrition: Eat protein + carbs within 30 min post-swim")
17
- plan.append("πŸŒ™ Sleep target: 8+ hours")
18
  return "\n".join(plan)
19
 
20
- daily_plan = gr.Interface(
21
- fn=generate_daily_plan,
22
- inputs=[
23
- gr.Textbox(label="Wake Time (e.g. 5:30 AM)"),
24
- gr.Slider(label="Swim Duration (min)", minimum=0, maximum=180),
25
- gr.Checkbox(label="Gym Today?"),
26
- gr.Slider(label="Sleep Last Night (hrs)", minimum=4, maximum=10, step=0.5),
27
- gr.Dropdown(["speed", "endurance", "technique", "recovery"], label="Today's Goal")
28
- ],
29
- outputs=gr.Textbox(label="AI Daily Plan"),
30
- title="🧠 SwimCoach+ AI β€” Daily Plan"
31
- )
32
 
33
- # PAGE 2: Nutrition and Sleep Tracker (placeholder)
34
- def diet_sleep_tracker(sleep, image=None, food_name=""):
35
- feedback = f"πŸ›Œ Sleep: {sleep} hrs β€” "
36
- feedback += "Great recovery!" if sleep >= 8 else "Try to get more rest tonight."
37
- if image:
38
- feedback += "\n🍽️ Food: [AI Image Analysis Coming Soon]"
39
- elif food_name:
40
- feedback += f"\n🍽️ Food entered: {food_name} (Calorie/macros estimation coming soon)"
41
- else:
42
- feedback += "\n🍽️ No food data provided."
43
- return feedback
44
 
45
- diet_sleep = gr.Interface(
46
- fn=diet_sleep_tracker,
47
- inputs=[
48
- gr.Slider(label="Sleep Hours", minimum=4, maximum=10, step=0.5),
49
- gr.Image(type="filepath", label="Upload Food Photo (optional)"),
50
- gr.Textbox(label="Or Type Food Name (e.g. '2 eggs and toast')")
51
- ],
52
- outputs=gr.Textbox(label="Nutrition & Sleep Feedback"),
53
- title="🍽️ Nutrition + πŸ’€ Sleep Tracker"
54
- )
55
 
56
- # PAGE 3: Swim Technique Analyzer (placeholder)
57
- def analyze_swim(video, stroke_type):
58
- return f"Received video for stroke: {stroke_type}. AI analysis coming soon."
59
 
60
- technique_analyzer = gr.Interface(
61
- fn=analyze_swim,
62
- inputs=[
63
- gr.Video(label="Upload Swim Video"),
64
- gr.Dropdown(["freestyle", "backstroke", "breaststroke", "butterfly"], label="Stroke Type")
65
- ],
66
- outputs="text",
67
- title="🏊 AI Swim Technique Analyzer"
68
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
 
70
- # PAGE 4: Profile
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
  profile_data = {}
72
 
73
  def save_profile(name, age, gender, goal, diet_type, pb100free):
@@ -79,6 +138,35 @@ def save_profile(name, age, gender, goal, diet_type, pb100free):
79
  profile_data["pb100free"] = pb100free
80
  return f"βœ… Profile saved for {name} (100 Free PB: {pb100free} sec)"
81
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82
  profile = gr.Interface(
83
  fn=save_profile,
84
  inputs=[
@@ -93,8 +181,8 @@ profile = gr.Interface(
93
  title="πŸ‘€ Swimmer Profile"
94
  )
95
 
96
- # MULTI-PAGE APP
97
  gr.TabbedInterface(
98
- [daily_plan, diet_sleep, technique_analyzer, profile],
99
- tab_names=["πŸ“… Daily Plan", "🍴 Nutrition & Sleep", "πŸ“Ή Technique", "πŸ‘€ Profile"]
100
  ).launch()
 
1
 
2
  import gradio as gr
3
+ import cv2
4
+ import numpy as np
5
+ from PIL import Image
6
+ import mediapipe as mp
7
+ import torch
8
+ from torchvision import transforms
9
+ from torchvision.models import resnet18
10
+ import torch.nn.functional as F
11
+ import openai
12
+ import os
13
 
14
+ # Load OpenAI API Key
15
+ openai.api_key = os.getenv("OPENAI_API_KEY")
16
+
17
+ # --------- Daily Plan Logic ---------
18
+ def generate_smart_plan(wake_time, swim_time, swim_duration, gym_today, sleep_hours, goal):
19
  plan = []
20
  if sleep_hours < 7:
21
+ plan.append("⚠️ Less than 7 hours of sleep β€” prioritize recovery or a nap.")
22
+ plan.append(f"πŸŒ… Wake-up time: {wake_time}")
23
+ plan.append(f"🏊 Swim: {swim_time} for {swim_duration} minutes β€” Focus: {goal.capitalize()}")
24
  if gym_today:
25
+ if goal == "speed":
26
+ plan.append("πŸ‹οΈ Gym Plan: Explosive lifts β€” med ball slams, box jumps.")
27
+ elif goal == "endurance":
28
+ plan.append("πŸ‹οΈ Gym Plan: Circuits with light weights and high reps.")
29
+ else:
30
+ plan.append("πŸ‹οΈ Gym Plan: Core, mobility, and injury prevention.")
31
  else:
32
+ plan.append("πŸ’ͺ No gym β€” light stretching and mobility recommended.")
33
+ plan.append("🍽️ Eat protein + carbs within 30 minutes post-swim.")
34
+ plan.append("πŸŒ™ Target 8–9 hours of sleep tonight.")
35
  return "\n".join(plan)
36
 
37
+ # --------- Food Macro Estimator + GPT ---------
38
+ food_classes = ["pizza", "salad", "burger", "sushi", "spaghetti", "steak", "pancakes"]
39
+ food_macros = {
40
+ "pizza": {"cal": 285, "protein": 12, "carbs": 36, "fat": 10},
41
+ "salad": {"cal": 150, "protein": 5, "carbs": 10, "fat": 7},
42
+ "burger": {"cal": 500, "protein": 25, "carbs": 40, "fat": 30},
43
+ "sushi": {"cal": 200, "protein": 10, "carbs": 30, "fat": 5},
44
+ "spaghetti": {"cal": 350, "protein": 12, "carbs": 60, "fat": 8},
45
+ "steak": {"cal": 400, "protein": 40, "carbs": 0, "fat": 25},
46
+ "pancakes": {"cal": 350, "protein": 6, "carbs": 45, "fat": 12}
47
+ }
 
48
 
49
+ model = resnet18(pretrained=True)
50
+ model.eval()
51
+ transform = transforms.Compose([
52
+ transforms.Resize((224, 224)),
53
+ transforms.ToTensor()
54
+ ])
 
 
 
 
 
55
 
56
+ def predict_macros_with_explanation(img):
57
+ image = Image.fromarray(img)
58
+ x = transform(image).unsqueeze(0)
59
+ with torch.no_grad():
60
+ logits = model(x)
61
+ probs = torch.nn.functional.softmax(logits, dim=1).squeeze().numpy()
62
+ pred_idx = np.argmax(probs)
63
+ food = food_classes[pred_idx % len(food_classes)]
64
+ macros = food_macros.get(food, {"cal": 0, "protein": 0, "carbs": 0, "fat": 0})
 
65
 
66
+ base = f"🍽️ Predicted: {food}\nCalories: {macros['cal']} kcal\nProtein: {macros['protein']}g\nCarbs: {macros['carbs']}g\nFat: {macros['fat']}g"
 
 
67
 
68
+ try:
69
+ response = openai.ChatCompletion.create(
70
+ model="gpt-4",
71
+ messages=[
72
+ {"role": "system", "content": "You are a helpful sports nutritionist."},
73
+ {"role": "user", "content": f"This food is {food} with macros: {macros}. Give a short explanation on how this helps a swimmer recover after training."}
74
+ ]
75
+ )
76
+ gpt_reply = response['choices'][0]['message']['content']
77
+ except Exception as e:
78
+ gpt_reply = f"⚠️ GPT error: {str(e)}"
79
+
80
+ return base + "\n\nπŸ’‘ GPT Insight:\n" + gpt_reply
81
+
82
+ # --------- Swim Technique Analyzer + GPT ---------
83
+ mp_pose = mp.solutions.pose
84
+
85
+ def analyze_swim_video_with_gpt(video_path):
86
+ cap = cv2.VideoCapture(video_path)
87
+ pose = mp_pose.Pose()
88
+ issues_detected = set()
89
+ frame_count = 0
90
+
91
+ while cap.isOpened():
92
+ ret, frame = cap.read()
93
+ if not ret or frame_count > 60:
94
+ break
95
+ frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
96
+ results = pose.process(frame_rgb)
97
+ if results.pose_landmarks:
98
+ l_shoulder = results.pose_landmarks.landmark[mp_pose.PoseLandmark.LEFT_SHOULDER]
99
+ r_shoulder = results.pose_landmarks.landmark[mp_pose.PoseLandmark.RIGHT_SHOULDER]
100
+ l_hand = results.pose_landmarks.landmark[mp_pose.PoseLandmark.LEFT_WRIST]
101
+ r_hand = results.pose_landmarks.landmark[mp_pose.PoseLandmark.RIGHT_WRIST]
102
+ if abs(l_hand.y - l_shoulder.y) < 0.1:
103
+ issues_detected.add("Left hand enters too flat")
104
+ if abs(r_hand.y - r_shoulder.y) < 0.1:
105
+ issues_detected.add("Right hand enters too flat")
106
+ frame_count += 1
107
 
108
+ cap.release()
109
+
110
+ if not issues_detected:
111
+ return "βœ… Stroke technique looks great in the first 60 frames!"
112
+
113
+ tips = "\n".join(f"- {issue}" for issue in issues_detected)
114
+
115
+ try:
116
+ gpt_response = openai.ChatCompletion.create(
117
+ model="gpt-4",
118
+ messages=[
119
+ {"role": "system", "content": "You are a professional swim coach."},
120
+ {"role": "user", "content": f"The following stroke issues were detected: {tips}. Explain their impact on performance and how to correct them."}
121
+ ]
122
+ )
123
+ gpt_advice = gpt_response['choices'][0]['message']['content']
124
+ except Exception as e:
125
+ gpt_advice = f"⚠️ GPT error: {str(e)}"
126
+
127
+ return "⚠️ Technique Tips:\n" + tips + "\n\nπŸ’‘ GPT Advice:\n" + gpt_advice
128
+
129
+ # --------- Profile ---------
130
  profile_data = {}
131
 
132
  def save_profile(name, age, gender, goal, diet_type, pb100free):
 
138
  profile_data["pb100free"] = pb100free
139
  return f"βœ… Profile saved for {name} (100 Free PB: {pb100free} sec)"
140
 
141
+ # --------- Gradio Interfaces ---------
142
+ daily_plan = gr.Interface(
143
+ fn=generate_smart_plan,
144
+ inputs=[
145
+ gr.Textbox(label="Wake-up Time (e.g. 5:30 AM)"),
146
+ gr.Textbox(label="Swim Time (e.g. 6:00 AM)"),
147
+ gr.Slider(label="Swim Duration (min)", minimum=0, maximum=180),
148
+ gr.Checkbox(label="Did you go to the gym today?"),
149
+ gr.Slider(label="Sleep Last Night (hrs)", minimum=4, maximum=10, step=0.5),
150
+ gr.Dropdown(["speed", "endurance", "technique", "recovery"], label="Today's Focus")
151
+ ],
152
+ outputs=gr.Textbox(label="AI Daily Plan"),
153
+ title="πŸ“… Daily Plan Generator"
154
+ )
155
+
156
+ macro_analyzer = gr.Interface(
157
+ fn=predict_macros_with_explanation,
158
+ inputs=gr.Image(type="numpy", label="Upload Food Image"),
159
+ outputs="text",
160
+ title="πŸ₯— Macro Estimator + GPT Insight"
161
+ )
162
+
163
+ swim_analyzer = gr.Interface(
164
+ fn=analyze_swim_video_with_gpt,
165
+ inputs=gr.Video(label="Upload Swim Video"),
166
+ outputs="text",
167
+ title="🏊 Swim Analyzer + GPT Advice"
168
+ )
169
+
170
  profile = gr.Interface(
171
  fn=save_profile,
172
  inputs=[
 
181
  title="πŸ‘€ Swimmer Profile"
182
  )
183
 
184
+ # Launch Tabbed App
185
  gr.TabbedInterface(
186
+ [daily_plan, macro_analyzer, swim_analyzer, profile],
187
+ tab_names=["πŸ“… Daily Plan", "πŸ₯— Macros + GPT", "🏊 Technique + GPT", "πŸ‘€ Profile"]
188
  ).launch()
requirements.txt CHANGED
@@ -1 +1,7 @@
1
  gradio
 
 
 
 
 
 
 
1
  gradio
2
+ torch
3
+ torchvision
4
+ opencv-python
5
+ mediapipe
6
+ pillow
7
+ numpy