Spaces:
Build error
Build error
Update app.py
Browse files
app.py
CHANGED
@@ -1,13 +1,13 @@
|
|
1 |
import gradio as gr
|
2 |
import torch
|
3 |
-
from transformers import
|
4 |
-
import pandas as pd
|
5 |
from PIL import Image
|
|
|
6 |
import numpy as np
|
7 |
|
8 |
-
# Carrega o modelo
|
9 |
-
model =
|
10 |
-
processor = AutoProcessor.from_pretrained("
|
11 |
|
12 |
# Base de dados nutricional
|
13 |
NUTRITION_DB = {
|
@@ -15,14 +15,11 @@ NUTRITION_DB = {
|
|
15 |
"feijão": {"calorias": 77, "proteinas": 5.2, "carboidratos": 13.6, "gorduras": 0.5},
|
16 |
"carne": {"calorias": 250, "proteinas": 26, "carboidratos": 0, "gorduras": 17},
|
17 |
"batata frita": {"calorias": 312, "proteinas": 3.4, "carboidratos": 41, "gorduras": 15},
|
18 |
-
"salada": {"calorias": 15, "proteinas": 1.4, "carboidratos": 2.9, "gorduras": 0.2}
|
19 |
-
"ovo": {"calorias": 155, "proteinas": 13, "carboidratos": 1.1, "gorduras": 11},
|
20 |
-
"peixe": {"calorias": 206, "proteinas": 22, "carboidratos": 0, "gorduras": 12},
|
21 |
-
"macarrão": {"calorias": 158, "proteinas": 5.8, "carboidratos": 31, "gorduras": 1.2}
|
22 |
}
|
23 |
|
24 |
def process_image(image, progress=gr.Progress()):
|
25 |
-
"""Processa a imagem usando
|
26 |
try:
|
27 |
progress(0.3, desc="Processando imagem...")
|
28 |
|
@@ -31,15 +28,18 @@ def process_image(image, progress=gr.Progress()):
|
|
31 |
image = Image.open(image)
|
32 |
elif isinstance(image, np.ndarray):
|
33 |
image = Image.fromarray(image)
|
|
|
|
|
|
|
34 |
|
35 |
-
|
|
|
36 |
inputs = processor(
|
37 |
-
images=image,
|
38 |
-
text=
|
39 |
return_tensors="pt"
|
40 |
-
)
|
41 |
|
42 |
-
progress(0.6, desc="Analisando conteúdo...")
|
43 |
# Gera a descrição
|
44 |
outputs = model.generate(
|
45 |
**inputs,
|
@@ -48,6 +48,7 @@ def process_image(image, progress=gr.Progress()):
|
|
48 |
temperature=0.7,
|
49 |
top_p=0.9
|
50 |
)
|
|
|
51 |
description = processor.decode(outputs[0], skip_special_tokens=True)
|
52 |
|
53 |
progress(1.0, desc="Concluído!")
|
@@ -56,8 +57,16 @@ def process_image(image, progress=gr.Progress()):
|
|
56 |
except Exception as e:
|
57 |
raise gr.Error(f"Erro no processamento: {str(e)}")
|
58 |
|
59 |
-
def analyze_nutrition(
|
60 |
-
"""Analisa nutrientes
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
61 |
total_nutrients = {
|
62 |
"calorias": 0,
|
63 |
"proteinas": 0,
|
@@ -65,46 +74,11 @@ def analyze_nutrition(foods_list):
|
|
65 |
"gorduras": 0
|
66 |
}
|
67 |
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
if food.lower() in foods_list.lower():
|
72 |
-
found_foods.append(food)
|
73 |
-
for nutrient, value in NUTRITION_DB[food].items():
|
74 |
-
total_nutrients[nutrient] += value
|
75 |
-
|
76 |
-
# Calcula proporções de macronutrientes
|
77 |
-
total_cal = total_nutrients['calorias']
|
78 |
-
if total_cal > 0:
|
79 |
-
protein_pct = (total_nutrients['proteinas'] * 4 / total_cal) * 100
|
80 |
-
carb_pct = (total_nutrients['carboidratos'] * 4 / total_cal) * 100
|
81 |
-
fat_pct = (total_nutrients['gorduras'] * 9 / total_cal) * 100
|
82 |
-
else:
|
83 |
-
protein_pct = carb_pct = fat_pct = 0
|
84 |
-
|
85 |
-
return total_nutrients, found_foods, (protein_pct, carb_pct, fat_pct)
|
86 |
-
|
87 |
-
def get_recommendations(nutrients, percentages):
|
88 |
-
"""Gera recomendações baseadas nos valores nutricionais"""
|
89 |
-
protein_pct, carb_pct, fat_pct = percentages
|
90 |
-
recommendations = []
|
91 |
-
|
92 |
-
if nutrients['calorias'] > 800:
|
93 |
-
recommendations.append("⚠️ Valor calórico elevado - considere reduzir as porções")
|
94 |
|
95 |
-
|
96 |
-
recommendations.append("⚠️ Baixo teor de proteínas - adicione mais fontes proteicas")
|
97 |
-
|
98 |
-
if carb_pct > 60:
|
99 |
-
recommendations.append("⚠️ Alto teor de carboidratos - considere reduzir")
|
100 |
-
|
101 |
-
if fat_pct > 30:
|
102 |
-
recommendations.append("⚠️ Alto teor de gorduras - opte por preparações mais leves")
|
103 |
-
|
104 |
-
if not recommendations:
|
105 |
-
recommendations.append("✅ Refeição bem balanceada! Continue assim!")
|
106 |
-
|
107 |
-
return recommendations
|
108 |
|
109 |
def analyze_image(image):
|
110 |
"""Função principal de análise"""
|
@@ -113,10 +87,7 @@ def analyze_image(image):
|
|
113 |
description = process_image(image)
|
114 |
|
115 |
# Analisa nutrientes
|
116 |
-
total_nutrients, found_foods
|
117 |
-
|
118 |
-
# Gera recomendações
|
119 |
-
recommendations = get_recommendations(total_nutrients, percentages)
|
120 |
|
121 |
# Prepara dados para visualização
|
122 |
table_data = [
|
@@ -137,20 +108,22 @@ def analyze_image(image):
|
|
137 |
})
|
138 |
|
139 |
# Monta o relatório
|
140 |
-
analysis = f"""### 🔍 Análise da Imagem
|
141 |
{description}
|
142 |
|
143 |
-
### 🍽️ Alimentos Identificados
|
144 |
{', '.join(found_foods)}
|
145 |
|
146 |
-
### 📊 Informação Nutricional
|
147 |
-
• Calorias
|
148 |
-
• Proteínas: {total_nutrients['proteinas']:.1f}g
|
149 |
-
• Carboidratos: {total_nutrients['carboidratos']:.1f}g
|
150 |
-
• Gorduras: {total_nutrients['gorduras']:.1f}g
|
151 |
|
152 |
-
### 💡 Recomendações
|
153 |
-
{
|
|
|
|
|
154 |
"""
|
155 |
|
156 |
return analysis, table_data, plot_data
|
@@ -158,145 +131,20 @@ def analyze_image(image):
|
|
158 |
except Exception as e:
|
159 |
return str(e), None, None
|
160 |
|
161 |
-
#
|
162 |
-
|
163 |
-
.
|
164 |
-
text-align: center;
|
165 |
-
margin-bottom: 2rem;
|
166 |
-
background: linear-gradient(120deg, #84fab0 0%, #8fd3f4 100%);
|
167 |
-
padding: 2rem;
|
168 |
-
border-radius: 1rem;
|
169 |
-
color: white;
|
170 |
-
text-shadow: 1px 1px 2px rgba(0,0,0,0.1);
|
171 |
-
}
|
172 |
-
|
173 |
-
.features {
|
174 |
-
display: grid;
|
175 |
-
grid-template-columns: repeat(3, 1fr);
|
176 |
-
gap: 1rem;
|
177 |
-
margin: 2rem 0;
|
178 |
-
}
|
179 |
-
|
180 |
-
.feature-card {
|
181 |
-
background: white;
|
182 |
-
padding: 1.5rem;
|
183 |
-
border-radius: 0.5rem;
|
184 |
-
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
|
185 |
-
text-align: center;
|
186 |
-
}
|
187 |
-
|
188 |
-
.benefits {
|
189 |
-
background: #f8f9fa;
|
190 |
-
padding: 1.5rem;
|
191 |
-
border-radius: 0.5rem;
|
192 |
-
margin: 1rem 0;
|
193 |
-
}
|
194 |
-
|
195 |
-
.testimonial {
|
196 |
-
font-style: italic;
|
197 |
-
color: #666;
|
198 |
-
background: #fff;
|
199 |
-
padding: 1rem;
|
200 |
-
border-left: 4px solid #84fab0;
|
201 |
-
margin: 1rem 0;
|
202 |
-
}
|
203 |
-
|
204 |
-
.cta-button {
|
205 |
-
background: linear-gradient(45deg, #84fab0, #8fd3f4);
|
206 |
-
padding: 1rem 2rem;
|
207 |
-
border: none;
|
208 |
-
border-radius: 2rem;
|
209 |
-
color: white;
|
210 |
-
font-weight: bold;
|
211 |
-
cursor: pointer;
|
212 |
-
transition: all 0.3s ease;
|
213 |
-
}
|
214 |
-
|
215 |
-
.cta-button:hover {
|
216 |
-
transform: translateY(-2px);
|
217 |
-
box-shadow: 0 4px 8px rgba(0,0,0,0.2);
|
218 |
-
}
|
219 |
-
|
220 |
-
.results-container {
|
221 |
-
background: white;
|
222 |
-
padding: 1.5rem;
|
223 |
-
border-radius: 0.5rem;
|
224 |
-
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
225 |
-
}
|
226 |
-
"""
|
227 |
-
|
228 |
-
# Interface Gradio com Marketing
|
229 |
-
with gr.Blocks(theme=gr.themes.Soft(), css=css) as iface:
|
230 |
-
with gr.Row(elem_classes="marketing-header"):
|
231 |
-
gr.Markdown("""
|
232 |
-
# 🍽️ NutriAI - Sua Análise Nutricional Inteligente
|
233 |
-
|
234 |
-
### Transforme sua alimentação com o poder da Inteligência Artificial
|
235 |
-
Análise nutricional precisa e personalizada em segundos!
|
236 |
-
""")
|
237 |
-
|
238 |
-
with gr.Row(elem_classes="features"):
|
239 |
-
with gr.Column(elem_classes="feature-card"):
|
240 |
-
gr.Markdown("""
|
241 |
-
### 🎯 Análise Precisa
|
242 |
-
- Reconhecimento avançado de alimentos
|
243 |
-
- Cálculo nutricional detalhado
|
244 |
-
- Tecnologia de ponta
|
245 |
-
""")
|
246 |
-
|
247 |
-
with gr.Column(elem_classes="feature-card"):
|
248 |
-
gr.Markdown("""
|
249 |
-
### ⚡ Resultados Instantâneos
|
250 |
-
- Análise em segundos
|
251 |
-
- Relatório completo
|
252 |
-
- Recomendações personalizadas
|
253 |
-
""")
|
254 |
-
|
255 |
-
with gr.Column(elem_classes="feature-card"):
|
256 |
-
gr.Markdown("""
|
257 |
-
### 💡 Inteligência Artificial
|
258 |
-
- Modelo MiniCPM avançado
|
259 |
-
- Aprendizado contínuo
|
260 |
-
- Alta precisão
|
261 |
-
""")
|
262 |
-
|
263 |
-
with gr.Row(elem_classes="benefits"):
|
264 |
-
gr.Markdown("""
|
265 |
-
### 🌟 Benefícios
|
266 |
-
|
267 |
-
✓ **Controle sua alimentação** de forma inteligente
|
268 |
-
✓ **Monitore nutrientes** essenciais
|
269 |
-
✓ **Receba dicas** personalizadas
|
270 |
-
✓ **Economize tempo** na contagem de calorias
|
271 |
-
✓ **Melhore seus hábitos** alimentares
|
272 |
-
""")
|
273 |
|
274 |
with gr.Row():
|
275 |
with gr.Column():
|
276 |
-
gr.Markdown("## 📸 Analise seu Prato")
|
277 |
image_input = gr.Image(
|
278 |
type="pil",
|
279 |
-
label="
|
280 |
sources=["upload", "webcam"]
|
281 |
)
|
282 |
-
analyze_btn = gr.Button("
|
283 |
-
|
284 |
-
with gr.Accordion("📝 Guia de Uso", open=False):
|
285 |
-
gr.Markdown("""
|
286 |
-
### Como obter os melhores resultados:
|
287 |
-
1. Use fotos bem iluminadas
|
288 |
-
2. Fotografe de cima para baixo
|
289 |
-
3. Mantenha todos os alimentos visíveis
|
290 |
-
4. Evite sombras ou reflexos
|
291 |
-
|
292 |
-
### Por que usar o NutriAI?
|
293 |
-
- Análise nutricional profissional
|
294 |
-
- Recomendações baseadas em ciência
|
295 |
-
- Interface intuitiva e fácil de usar
|
296 |
-
""")
|
297 |
|
298 |
-
with gr.Column(
|
299 |
-
gr.Markdown("### Resultados da Análise")
|
300 |
output_text = gr.Markdown()
|
301 |
|
302 |
with gr.Row():
|
@@ -312,27 +160,6 @@ with gr.Blocks(theme=gr.themes.Soft(), css=css) as iface:
|
|
312 |
height=300
|
313 |
)
|
314 |
|
315 |
-
with gr.Row(elem_classes="testimonial"):
|
316 |
-
gr.Markdown("""
|
317 |
-
> "O NutriAI revolucionou minha forma de me alimentar. Agora consigo entender exatamente o que estou comendo e fazer escolhas mais saudáveis."
|
318 |
-
>
|
319 |
-
> *— Maria S., Nutricionista*
|
320 |
-
""")
|
321 |
-
|
322 |
-
gr.Markdown("""
|
323 |
-
### 🔒 Sua privacidade é importante
|
324 |
-
- Análise segura e privada
|
325 |
-
- Sem armazenamento de dados pessoais
|
326 |
-
- Tecnologia de ponta em segurança
|
327 |
-
|
328 |
-
### 📱 Disponível em qualquer dispositivo
|
329 |
-
Acesse pelo celular, tablet ou computador - em qualquer lugar, a qualquer momento!
|
330 |
-
|
331 |
-
### 🤝 Suporte ao cliente
|
332 |
-
Precisa de ajuda? Entre em contato com nossa equipe de suporte!
|
333 |
-
""")
|
334 |
-
|
335 |
-
# Eventos
|
336 |
analyze_btn.click(
|
337 |
fn=analyze_image,
|
338 |
inputs=[image_input],
|
|
|
1 |
import gradio as gr
|
2 |
import torch
|
3 |
+
from transformers import AutoModelForCausalLM, AutoProcessor
|
|
|
4 |
from PIL import Image
|
5 |
+
import pandas as pd
|
6 |
import numpy as np
|
7 |
|
8 |
+
# Carrega o modelo Emu3-Gen
|
9 |
+
model = AutoModelForCausalLM.from_pretrained("BAAI/Emu3-Gen", trust_remote_code=True)
|
10 |
+
processor = AutoProcessor.from_pretrained("BAAI/Emu3-Gen", trust_remote_code=True)
|
11 |
|
12 |
# Base de dados nutricional
|
13 |
NUTRITION_DB = {
|
|
|
15 |
"feijão": {"calorias": 77, "proteinas": 5.2, "carboidratos": 13.6, "gorduras": 0.5},
|
16 |
"carne": {"calorias": 250, "proteinas": 26, "carboidratos": 0, "gorduras": 17},
|
17 |
"batata frita": {"calorias": 312, "proteinas": 3.4, "carboidratos": 41, "gorduras": 15},
|
18 |
+
"salada": {"calorias": 15, "proteinas": 1.4, "carboidratos": 2.9, "gorduras": 0.2}
|
|
|
|
|
|
|
19 |
}
|
20 |
|
21 |
def process_image(image, progress=gr.Progress()):
|
22 |
+
"""Processa a imagem usando Emu3-Gen"""
|
23 |
try:
|
24 |
progress(0.3, desc="Processando imagem...")
|
25 |
|
|
|
28 |
image = Image.open(image)
|
29 |
elif isinstance(image, np.ndarray):
|
30 |
image = Image.fromarray(image)
|
31 |
+
|
32 |
+
# Prompt específico para análise de alimentos
|
33 |
+
prompt = "Describe in detail all the foods present in this image, including their preparation methods."
|
34 |
|
35 |
+
progress(0.6, desc="Analisando conteúdo...")
|
36 |
+
# Processa a imagem
|
37 |
inputs = processor(
|
38 |
+
images=image,
|
39 |
+
text=prompt,
|
40 |
return_tensors="pt"
|
41 |
+
).to(model.device)
|
42 |
|
|
|
43 |
# Gera a descrição
|
44 |
outputs = model.generate(
|
45 |
**inputs,
|
|
|
48 |
temperature=0.7,
|
49 |
top_p=0.9
|
50 |
)
|
51 |
+
|
52 |
description = processor.decode(outputs[0], skip_special_tokens=True)
|
53 |
|
54 |
progress(1.0, desc="Concluído!")
|
|
|
57 |
except Exception as e:
|
58 |
raise gr.Error(f"Erro no processamento: {str(e)}")
|
59 |
|
60 |
+
def analyze_nutrition(description):
|
61 |
+
"""Analisa nutrientes baseado na descrição"""
|
62 |
+
found_foods = []
|
63 |
+
|
64 |
+
# Identifica alimentos na descrição
|
65 |
+
for food in NUTRITION_DB.keys():
|
66 |
+
if food.lower() in description.lower():
|
67 |
+
found_foods.append(food)
|
68 |
+
|
69 |
+
# Calcula nutrientes
|
70 |
total_nutrients = {
|
71 |
"calorias": 0,
|
72 |
"proteinas": 0,
|
|
|
74 |
"gorduras": 0
|
75 |
}
|
76 |
|
77 |
+
for food in found_foods:
|
78 |
+
for nutrient, value in NUTRITION_DB[food].items():
|
79 |
+
total_nutrients[nutrient] += value
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
80 |
|
81 |
+
return total_nutrients, found_foods
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
82 |
|
83 |
def analyze_image(image):
|
84 |
"""Função principal de análise"""
|
|
|
87 |
description = process_image(image)
|
88 |
|
89 |
# Analisa nutrientes
|
90 |
+
total_nutrients, found_foods = analyze_nutrition(description)
|
|
|
|
|
|
|
91 |
|
92 |
# Prepara dados para visualização
|
93 |
table_data = [
|
|
|
108 |
})
|
109 |
|
110 |
# Monta o relatório
|
111 |
+
analysis = f"""### 🔍 Análise da Imagem:
|
112 |
{description}
|
113 |
|
114 |
+
### 🍽️ Alimentos Identificados:
|
115 |
{', '.join(found_foods)}
|
116 |
|
117 |
+
### 📊 Informação Nutricional:
|
118 |
+
• Calorias: {total_nutrients['calorias']:.1f} kcal
|
119 |
+
• Proteínas: {total_nutrients['proteinas']:.1f}g
|
120 |
+
• Carboidratos: {total_nutrients['carboidratos']:.1f}g
|
121 |
+
• Gorduras: {total_nutrients['gorduras']:.1f}g
|
122 |
|
123 |
+
### 💡 Recomendações:
|
124 |
+
{"⚠️ Alto valor calórico" if total_nutrients['calorias'] > 800 else "✅ Calorias adequadas"}
|
125 |
+
{"⚠️ Considere reduzir carboidratos" if total_nutrients['carboidratos'] > 60 else "✅ Carboidratos adequados"}
|
126 |
+
{"⚠️ Alto teor de gorduras" if total_nutrients['gorduras'] > 20 else "✅ Gorduras adequadas"}
|
127 |
"""
|
128 |
|
129 |
return analysis, table_data, plot_data
|
|
|
131 |
except Exception as e:
|
132 |
return str(e), None, None
|
133 |
|
134 |
+
# Interface Gradio
|
135 |
+
with gr.Blocks(theme=gr.themes.Soft()) as iface:
|
136 |
+
gr.Markdown("# 🍽️ NutriAI - Análise Nutricional com IA")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
137 |
|
138 |
with gr.Row():
|
139 |
with gr.Column():
|
|
|
140 |
image_input = gr.Image(
|
141 |
type="pil",
|
142 |
+
label="Foto do Prato",
|
143 |
sources=["upload", "webcam"]
|
144 |
)
|
145 |
+
analyze_btn = gr.Button("📊 Analisar", variant="primary")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
146 |
|
147 |
+
with gr.Column():
|
|
|
148 |
output_text = gr.Markdown()
|
149 |
|
150 |
with gr.Row():
|
|
|
160 |
height=300
|
161 |
)
|
162 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
163 |
analyze_btn.click(
|
164 |
fn=analyze_image,
|
165 |
inputs=[image_input],
|