SURESHBEEKHANI commited on
Commit
74c93d7
Β·
verified Β·
1 Parent(s): 54b8e46

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +79 -60
app.py CHANGED
@@ -6,7 +6,7 @@ import io
6
  from dotenv import load_dotenv
7
  from groq import Groq
8
  from reportlab.lib.pagesizes import letter
9
- from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer
10
  from reportlab.lib.styles import getSampleStyleSheet
11
 
12
  # ======================
@@ -26,7 +26,7 @@ ALLOWED_FILE_TYPES = ['png', 'jpg', 'jpeg']
26
  # ======================
27
 
28
  def initialize_api_client():
29
- """Initialize Groq API client"""
30
  load_dotenv()
31
  api_key = os.getenv("GROQ_API_KEY")
32
  if not api_key:
@@ -36,63 +36,72 @@ def initialize_api_client():
36
 
37
 
38
  def encode_image(image_path):
39
- """Encode an image to base64"""
40
  try:
41
  with open(image_path, "rb") as img_file:
42
  return base64.b64encode(img_file.read()).decode("utf-8")
43
  except FileNotFoundError:
 
44
  return ""
45
 
46
 
47
  def process_image(uploaded_file):
48
- """Convert image to base64 string"""
49
  try:
50
  image = Image.open(uploaded_file)
51
  buffer = io.BytesIO()
52
- image.save(buffer, format=image.format)
53
- return base64.b64encode(buffer.getvalue()).decode('utf-8'), image.format
 
 
54
  except Exception as e:
55
  st.error(f"Image processing error: {e}")
56
  return None, None
57
 
58
 
59
  def generate_pdf(report_text, logo_b64):
60
- """Generate a PDF report with logo"""
61
  buffer = io.BytesIO()
62
  doc = SimpleDocTemplate(buffer, pagesize=letter)
63
  styles = getSampleStyleSheet()
64
 
65
- # Decode the base64 logo image
66
- logo_data = base64.b64decode(logo_b64)
67
- logo_image = Image.open(io.BytesIO(logo_data))
68
 
69
- # Resize the logo to fit the page width (you can adjust size if necessary)
70
- logo_width, logo_height = logo_image.size
71
- logo_aspect = logo_height / logo_width
72
- max_logo_width = 150 # Adjust this value to change the max width of the logo
73
- logo_width = min(logo_width, max_logo_width)
74
- logo_height = int(logo_width * logo_aspect)
 
 
 
 
 
 
 
 
 
 
 
75
 
76
- # Create a ReportLab Image element to add the logo to the PDF
77
- logo = ReportLabImage(io.BytesIO(logo_data), width=logo_width, height=logo_height)
78
-
79
- # Build the PDF content
80
- story = [
81
- logo, # Add the logo at the top of the page
82
- Spacer(1, 12), # Space after the logo
83
  Paragraph("<b>Nutrition Analysis Report</b>", styles['Title']),
84
  Spacer(1, 12),
85
  Paragraph(report_text.replace('\n', '<br/>'), styles['BodyText'])
86
- ]
 
 
 
 
 
87
 
88
- doc.build(story)
89
  buffer.seek(0)
90
  return buffer
91
 
92
 
93
-
94
  def generate_analysis(uploaded_file, client):
95
- """Generate AI-powered food analysis"""
96
  base64_image, img_format = process_image(uploaded_file)
97
  if not base64_image:
98
  return None
@@ -107,21 +116,20 @@ def generate_analysis(uploaded_file, client):
107
  "role": "user",
108
  "content": [
109
  {"type": "text", "text": """
110
-
111
- You are an expert nutritionist with advanced image analysis capabilities.
112
- Your task is to analyze the provided image, identify all visible food items, and estimate their calorie content with high accuracy.
113
- **Instructions:**
114
- - Identify and list each food item visible in the image.
115
- - For each item, estimate the calorie content based on standard nutritional data, considering portion size, cooking method, and food density.
116
- - Clearly mark any calorie estimate as "approximate" if based on assumptions due to unclear details.
117
- - Calculate and provide the total estimated calories for the entire meal.
118
- **Output Format:**
119
- - Food Item 1: [Name] – Estimated Calories: [value] kcal
120
- - Food Item 2: [Name] – Estimated Calories: [value] kcal
121
- - ...
122
- - **Total Estimated Calories:** [value] kcal
123
- If the image lacks sufficient detail or is unclear, specify the limitations and include your confidence level in the estimate as a percentage.
124
-
125
  """},
126
  {"type": "image_url", "image_url": {"url": image_url}}
127
  ]
@@ -140,11 +148,8 @@ def generate_analysis(uploaded_file, client):
140
  # UI COMPONENTS
141
  # ======================
142
 
143
- def display_main_interface():
144
- """Render primary application interface"""
145
- logo_b64 = encode_image("src/logo.png")
146
-
147
- # HTML with inline styles to change text colors
148
  st.markdown(f"""
149
  <div style="text-align: center;">
150
  <img src="data:image/png;base64,{logo_b64}" width="100">
@@ -156,48 +161,62 @@ def display_main_interface():
156
  st.markdown("---")
157
 
158
  if st.session_state.get('analysis_result'):
159
- # Create two columns: one for download and one for clear button
160
- col1, col2 = st.columns([1, 1])
161
 
162
  # Left column for the Download button
163
  with col1:
164
- pdf_report = generate_pdf(st.session_state.analysis_result)
165
- st.download_button("πŸ“„ Download Nutrition Report", data=pdf_report, file_name="nutrition_report.pdf", mime="application/pdf")
 
 
 
166
 
167
  # Right column for the Clear button
168
  with col2:
169
  if st.button("Clear Analysis πŸ—‘οΈ"):
170
  st.session_state.pop('analysis_result')
171
- st.rerun()
172
 
173
  if st.session_state.get('analysis_result'):
174
  st.markdown("### 🎯 Nutrition Analysis Report")
175
  st.info(st.session_state.analysis_result)
176
 
177
 
178
- def render_sidebar(client):
179
- """Create sidebar UI elements"""
180
  with st.sidebar:
181
  st.subheader("Image Upload")
182
  uploaded_file = st.file_uploader("Upload Food Image", type=ALLOWED_FILE_TYPES)
183
 
184
  if uploaded_file:
185
- st.image(Image.open(uploaded_file), caption="Uploaded Food Image")
 
 
 
 
 
186
  if st.button("Analyze Meal 🍽️"):
187
  with st.spinner("Analyzing image..."):
188
  report = generate_analysis(uploaded_file, client)
189
- st.session_state.analysis_result = report
190
- st.rerun()
 
 
 
 
191
 
192
  # ======================
193
  # APPLICATION ENTRYPOINT
194
  # ======================
195
 
196
  def main():
197
- """Primary application controller"""
198
  client = initialize_api_client()
199
- display_main_interface()
200
- render_sidebar(client)
 
 
201
 
202
  if __name__ == "__main__":
203
  main()
 
6
  from dotenv import load_dotenv
7
  from groq import Groq
8
  from reportlab.lib.pagesizes import letter
9
+ from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Image as ReportLabImage
10
  from reportlab.lib.styles import getSampleStyleSheet
11
 
12
  # ======================
 
26
  # ======================
27
 
28
  def initialize_api_client():
29
+ """Initialize Groq API client."""
30
  load_dotenv()
31
  api_key = os.getenv("GROQ_API_KEY")
32
  if not api_key:
 
36
 
37
 
38
  def encode_image(image_path):
39
+ """Encode an image to base64."""
40
  try:
41
  with open(image_path, "rb") as img_file:
42
  return base64.b64encode(img_file.read()).decode("utf-8")
43
  except FileNotFoundError:
44
+ st.error(f"Logo file not found at {image_path}")
45
  return ""
46
 
47
 
48
  def process_image(uploaded_file):
49
+ """Convert image to base64 string."""
50
  try:
51
  image = Image.open(uploaded_file)
52
  buffer = io.BytesIO()
53
+ # Ensure image.format is valid; default to PNG if not available.
54
+ fmt = image.format if image.format else "PNG"
55
+ image.save(buffer, format=fmt)
56
+ return base64.b64encode(buffer.getvalue()).decode('utf-8'), fmt
57
  except Exception as e:
58
  st.error(f"Image processing error: {e}")
59
  return None, None
60
 
61
 
62
  def generate_pdf(report_text, logo_b64):
63
+ """Generate a PDF report with logo."""
64
  buffer = io.BytesIO()
65
  doc = SimpleDocTemplate(buffer, pagesize=letter)
66
  styles = getSampleStyleSheet()
67
 
68
+ story = []
 
 
69
 
70
+ # If a logo is provided, decode and add it
71
+ if logo_b64:
72
+ try:
73
+ logo_data = base64.b64decode(logo_b64)
74
+ logo_image = Image.open(io.BytesIO(logo_data))
75
+ # Resize the logo (adjust max width as needed)
76
+ logo_width, logo_height = logo_image.size
77
+ logo_aspect = logo_height / logo_width
78
+ max_logo_width = 150
79
+ logo_width = min(logo_width, max_logo_width)
80
+ logo_height = int(logo_width * logo_aspect)
81
+
82
+ logo = ReportLabImage(io.BytesIO(logo_data), width=logo_width, height=logo_height)
83
+ story.append(logo)
84
+ story.append(Spacer(1, 12))
85
+ except Exception as e:
86
+ st.error(f"Error adding logo to PDF: {e}")
87
 
88
+ story.extend([
 
 
 
 
 
 
89
  Paragraph("<b>Nutrition Analysis Report</b>", styles['Title']),
90
  Spacer(1, 12),
91
  Paragraph(report_text.replace('\n', '<br/>'), styles['BodyText'])
92
+ ])
93
+
94
+ try:
95
+ doc.build(story)
96
+ except Exception as e:
97
+ st.error(f"Error generating PDF: {e}")
98
 
 
99
  buffer.seek(0)
100
  return buffer
101
 
102
 
 
103
  def generate_analysis(uploaded_file, client):
104
+ """Generate AI-powered food analysis."""
105
  base64_image, img_format = process_image(uploaded_file)
106
  if not base64_image:
107
  return None
 
116
  "role": "user",
117
  "content": [
118
  {"type": "text", "text": """
119
+ You are an expert nutritionist with advanced image analysis capabilities.
120
+ Your task is to analyze the provided image, identify all visible food items, and estimate their calorie content with high accuracy.
121
+ **Instructions:**
122
+ - Identify and list each food item visible in the image.
123
+ - For each item, estimate the calorie content based on standard nutritional data, considering portion size, cooking method, and food density.
124
+ - Clearly mark any calorie estimate as "approximate" if based on assumptions due to unclear details.
125
+ - Calculate and provide the total estimated calories for the entire meal.
126
+ **Output Format:**
127
+ - Food Item 1: [Name] – Estimated Calories: [value] kcal
128
+ - Food Item 2: [Name] – Estimated Calories: [value] kcal
129
+ - ...
130
+ - **Total Estimated Calories:** [value] kcal
131
+
132
+ If the image lacks sufficient detail or is unclear, specify the limitations and include your confidence level in the estimate as a percentage.
 
133
  """},
134
  {"type": "image_url", "image_url": {"url": image_url}}
135
  ]
 
148
  # UI COMPONENTS
149
  # ======================
150
 
151
+ def display_main_interface(logo_b64):
152
+ """Render primary application interface."""
 
 
 
153
  st.markdown(f"""
154
  <div style="text-align: center;">
155
  <img src="data:image/png;base64,{logo_b64}" width="100">
 
161
  st.markdown("---")
162
 
163
  if st.session_state.get('analysis_result'):
164
+ # Create two columns: one for download and one for the clear button
165
+ col1, col2 = st.columns(2)
166
 
167
  # Left column for the Download button
168
  with col1:
169
+ pdf_report = generate_pdf(st.session_state.analysis_result, logo_b64)
170
+ st.download_button("πŸ“„ Download Nutrition Report",
171
+ data=pdf_report,
172
+ file_name="nutrition_report.pdf",
173
+ mime="application/pdf")
174
 
175
  # Right column for the Clear button
176
  with col2:
177
  if st.button("Clear Analysis πŸ—‘οΈ"):
178
  st.session_state.pop('analysis_result')
179
+ st.experimental_rerun()
180
 
181
  if st.session_state.get('analysis_result'):
182
  st.markdown("### 🎯 Nutrition Analysis Report")
183
  st.info(st.session_state.analysis_result)
184
 
185
 
186
+ def render_sidebar(client, logo_b64):
187
+ """Create sidebar UI elements."""
188
  with st.sidebar:
189
  st.subheader("Image Upload")
190
  uploaded_file = st.file_uploader("Upload Food Image", type=ALLOWED_FILE_TYPES)
191
 
192
  if uploaded_file:
193
+ try:
194
+ image = Image.open(uploaded_file)
195
+ st.image(image, caption="Uploaded Food Image")
196
+ except Exception as e:
197
+ st.error(f"Error displaying image: {e}")
198
+
199
  if st.button("Analyze Meal 🍽️"):
200
  with st.spinner("Analyzing image..."):
201
  report = generate_analysis(uploaded_file, client)
202
+ if report:
203
+ st.session_state.analysis_result = report
204
+ st.experimental_rerun()
205
+ else:
206
+ st.error("Failed to generate analysis.")
207
+
208
 
209
  # ======================
210
  # APPLICATION ENTRYPOINT
211
  # ======================
212
 
213
  def main():
214
+ """Primary application controller."""
215
  client = initialize_api_client()
216
+ logo_b64 = encode_image("src/logo.png")
217
+ display_main_interface(logo_b64)
218
+ render_sidebar(client, logo_b64)
219
+
220
 
221
  if __name__ == "__main__":
222
  main()