DHEIVER commited on
Commit
dcf8576
·
verified ·
1 Parent(s): 4037260

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +154 -172
app.py CHANGED
@@ -1,198 +1,180 @@
1
  import gradio as gr
2
- from transformers import Blip2Processor, Blip2ForConditionalGeneration
3
- import torch
4
  from PIL import Image
5
- import pandas as pd
 
6
 
7
- # Carregar o modelo BLIP2
8
- model_name = "Salesforce/blip2-opt-2.7b"
9
- processor = Blip2Processor.from_pretrained(model_name)
10
- model = Blip2ForConditionalGeneration.from_pretrained(model_name, torch_dtype=torch.float16, device_map="auto")
11
-
12
- # Base de dados nutricional
13
- NUTRITIONAL_DB = {
14
- "arroz": {
15
- "calorias": 130,
16
- "proteinas": 2.7,
17
- "carboidratos": 28,
18
- "gorduras": 0.3,
19
- "fibras": 0.4,
20
- "vitamina_b1": 0.02,
21
- "vitamina_b3": 0.4,
22
- "ferro": 0.2,
23
- },
24
- "feijão": {
25
- "calorias": 77,
26
- "proteinas": 5.2,
27
- "carboidratos": 13.6,
28
- "gorduras": 0.5,
29
- "fibras": 5.4,
30
- "ferro": 1.5,
31
- "potássio": 255,
32
- "magnésio": 42,
33
- },
34
- "frango": {
35
- "calorias": 165,
36
- "proteinas": 31,
37
- "carboidratos": 0,
38
- "gorduras": 3.6,
39
- "vitamina_b6": 0.5,
40
- "niacina": 13.7,
41
- "fósforo": 200,
42
- },
43
- "salada": {
44
- "calorias": 15,
45
- "proteinas": 1.4,
46
- "carboidratos": 2.9,
47
- "gorduras": 0.2,
48
- "fibras": 1.3,
49
- "vitamina_a": 370,
50
- "vitamina_k": 126,
51
- "folato": 38,
52
- }
53
- }
54
-
55
- def get_food_description(image):
56
- """
57
- Usa o modelo BLIP2 para analisar a imagem e descrever os alimentos
58
- """
59
- prompt = "Descreva detalhadamente todos os alimentos visíveis nesta imagem. Liste cada item separadamente."
60
-
61
- # Processar imagem
62
- inputs = processor(image, text=prompt, return_tensors="pt").to(model.device)
63
-
64
- # Gerar descrição
65
- outputs = model.generate(
66
- **inputs,
67
- max_new_tokens=100,
68
- do_sample=False,
69
- num_beams=5,
70
- temperature=1.0,
71
- top_p=0.9,
72
- )
73
-
74
- # Decodificar e retornar descrição
75
- description = processor.decode(outputs[0], skip_special_tokens=True)
76
- return description
77
-
78
- def parse_food_description(description):
79
- """
80
- Processa a descrição do modelo para identificar alimentos
81
- """
82
- foods = []
83
- description = description.lower()
84
-
85
- for food in NUTRITIONAL_DB.keys():
86
- if food in description:
87
- # Quantidade padrão em gramas
88
- qty = 100
89
- foods.append((food, qty))
90
-
91
- return foods
92
-
93
- def analyze_food(image):
94
  """
95
- Analisa a imagem do alimento e retorna relatório nutricional detalhado
96
  """
97
  try:
98
- # Obter descrição dos alimentos
99
- food_description = get_food_description(image)
100
-
101
- # Processar descrição para identificar alimentos
102
- identified_foods = parse_food_description(food_description)
103
-
104
- if not identified_foods:
105
- return "Nenhum alimento foi identificado com confiança suficiente na imagem. Por favor, tente outra foto."
106
 
107
- # Gerar relatório nutricional
108
- report = "🍽️ RELATÓRIO NUTRICIONAL DETALHADO\n\n"
109
- report += "📝 Alimentos Identificados:\n"
110
- report += f"\nDescrição do modelo:\n{food_description}\n\n"
111
 
112
- total_nutrients = {
113
- "calorias": 0,
114
- "proteinas": 0,
115
- "carboidratos": 0,
116
- "gorduras": 0,
117
- "fibras": 0,
118
- }
119
 
120
- vitamins_minerals = {}
 
 
 
 
 
 
121
 
122
- for food, quantity in identified_foods:
123
- multiplier = quantity / 100 # Ajusta para a quantidade real
124
- report += f"\n• {food.capitalize()} ({quantity}g)\n"
 
125
 
126
- if food in NUTRITIONAL_DB:
127
- for nutrient, value in NUTRITIONAL_DB[food].items():
128
- adjusted_value = value * multiplier
129
-
130
- # Adiciona aos totais principais
131
- if nutrient in total_nutrients:
132
- total_nutrients[nutrient] += adjusted_value
133
- # Coleta vitaminas e minerais
134
- elif nutrient not in ['calorias', 'proteinas', 'carboidratos', 'gorduras', 'fibras']:
135
- if nutrient not in vitamins_minerals:
136
- vitamins_minerals[nutrient] = 0
137
- vitamins_minerals[nutrient] += adjusted_value
138
-
139
- # Adiciona seção de macronutrientes
140
- report += "\n📊 MACRONUTRIENTES:\n"
141
- report += f"• Calorias: {total_nutrients['calorias']:.1f} kcal\n"
142
- report += f"• Proteínas: {total_nutrients['proteinas']:.1f}g\n"
143
- report += f"• Carboidratos: {total_nutrients['carboidratos']:.1f}g\n"
144
- report += f"• Gorduras: {total_nutrients['gorduras']:.1f}g\n"
145
- report += f"• Fibras: {total_nutrients['fibras']:.1f}g\n"
146
 
147
- # Adiciona seção de micronutrientes
148
- if vitamins_minerals:
149
- report += "\n🧬 VITAMINAS E MINERAIS:\n"
150
- for nutrient, value in vitamins_minerals.items():
151
- report += f"• {nutrient.replace('_', ' ').capitalize()}: {value:.1f}mg\n"
 
 
152
 
153
- # Adiciona recomendações personalizadas
154
- report += "\n💡 RECOMENDAÇÕES:\n"
155
 
156
- if total_nutrients['calorias'] > 800:
157
- report += "• Alto valor calórico - considere reduzir as porções\n"
158
- if total_nutrients['proteinas'] < 15:
159
- report += "• Baixo teor de proteínas - considere adicionar fontes proteicas\n"
160
- if total_nutrients['fibras'] < 6:
161
- report += "• Baixo teor de fibras - adicione mais vegetais e grãos integrais\n"
 
 
 
162
 
163
- # Análise de proporções
164
- protein_cal = (total_nutrients['proteinas'] * 4)
165
- carb_cal = (total_nutrients['carboidratos'] * 4)
166
- fat_cal = (total_nutrients['gorduras'] * 9)
167
- total_cal = protein_cal + carb_cal + fat_cal
 
 
 
 
 
 
168
 
169
- if total_cal > 0:
170
- protein_pct = (protein_cal / total_cal) * 100
171
- carb_pct = (carb_cal / total_cal) * 100
172
- fat_pct = (fat_cal / total_cal) * 100
 
 
 
 
173
 
174
- report += f"\n📈 DISTRIBUIÇÃO CALÓRICA:\n"
175
- report += f"• Proteínas: {protein_pct:.1f}%\n"
176
- report += f"• Carboidratos: {carb_pct:.1f}%\n"
177
- report += f"• Gorduras: {fat_pct:.1f}%\n"
178
 
179
- return report
 
 
 
 
 
 
 
 
 
 
 
 
 
 
180
 
181
  except Exception as e:
182
- return f"Erro na análise: {str(e)}\nPor favor, tente novamente com outra imagem."
183
 
184
  # Interface Gradio
185
- iface = gr.Interface(
186
- fn=analyze_food,
187
- inputs=gr.Image(type="pil", label="Upload da Imagem do Prato"),
188
- outputs=gr.Textbox(label="Relatório Nutricional", lines=20),
189
- title="🍽️ Análise Nutricional com IA",
190
- description="""
191
  Faça upload de uma foto do seu prato para receber uma análise nutricional detalhada.
192
- O sistema identificará os alimentos e fornecerá informações nutricionais completas.
193
- """,
194
- theme=gr.themes.Soft()
195
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
196
 
 
197
  if __name__ == "__main__":
198
  iface.launch(share=True)
 
1
  import gradio as gr
2
+ import json
 
3
  from PIL import Image
4
+ import requests
5
+ from io import BytesIO
6
 
7
+ def process_image(image, api_key=None):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  """
9
+ Processa a imagem usando a API de análise nutricional
10
  """
11
  try:
12
+ # Prepara a imagem
13
+ if isinstance(image, str):
14
+ img = Image.open(image)
15
+ else:
16
+ img = Image.fromarray(image)
 
 
 
17
 
18
+ # Converte para formato adequado
19
+ buffered = BytesIO()
20
+ img.save(buffered, format="JPEG")
21
+ img_bytes = buffered.getvalue()
22
 
23
+ # Headers da requisição
24
+ headers = {}
25
+ if api_key:
26
+ headers['Authorization'] = f'Bearer {api_key}'
 
 
 
27
 
28
+ # Faz a requisição para a API
29
+ files = {'image': ('image.jpg', img_bytes, 'image/jpeg')}
30
+ response = requests.post(
31
+ 'http://localhost:7860/api/predict', # Ajuste a URL conforme necessário
32
+ files=files,
33
+ headers=headers
34
+ )
35
 
36
+ if response.status_code == 200:
37
+ return response.json()
38
+ else:
39
+ return f"Erro na API: {response.status_code}"
40
 
41
+ except Exception as e:
42
+ return f"Erro no processamento: {str(e)}"
43
+
44
+ def analyze_nutrition(image, api_key=""):
45
+ """
46
+ Função principal que processa a imagem e retorna os resultados formatados
47
+ """
48
+ try:
49
+ # Processa a imagem
50
+ result = process_image(image, api_key)
 
 
 
 
 
 
 
 
 
 
51
 
52
+ if isinstance(result, str): # Se for mensagem de erro
53
+ return (
54
+ result, # Texto do erro
55
+ None, # Gráfico de macronutrientes
56
+ None, # Tabela nutricional
57
+ None # Recomendações
58
+ )
59
 
60
+ # Extrai informações do resultado
61
+ nutrients = result.get('nutrients', {})
62
 
63
+ # Prepara dados para o gráfico
64
+ macro_data = {
65
+ 'labels': ['Proteínas', 'Carboidratos', 'Gorduras'],
66
+ 'values': [
67
+ nutrients.get('proteinas', 0),
68
+ nutrients.get('carboidratos', 0),
69
+ nutrients.get('gorduras', 0)
70
+ ]
71
+ }
72
 
73
+ # Prepara tabela nutricional
74
+ nutri_table = {
75
+ 'Nutriente': ['Calorias', 'Proteínas', 'Carboidratos', 'Gorduras', 'Fibras'],
76
+ 'Quantidade': [
77
+ f"{nutrients.get('calorias', 0):.1f} kcal",
78
+ f"{nutrients.get('proteinas', 0):.1f}g",
79
+ f"{nutrients.get('carboidratos', 0):.1f}g",
80
+ f"{nutrients.get('gorduras', 0):.1f}g",
81
+ f"{nutrients.get('fibras', 0):.1f}g"
82
+ ]
83
+ }
84
 
85
+ # Prepara recomendações
86
+ recommendations = []
87
+ if nutrients.get('calorias', 0) > 800:
88
+ recommendations.append("⚠️ Alto valor calórico - considere reduzir as porções")
89
+ if nutrients.get('proteinas', 0) < 15:
90
+ recommendations.append("⚠️ Baixo teor de proteínas - considere adicionar fontes proteicas")
91
+ if nutrients.get('fibras', 0) < 6:
92
+ recommendations.append("⚠️ Baixo teor de fibras - adicione mais vegetais")
93
 
94
+ recommendations = "\n".join(recommendations) if recommendations else "✅ Valores nutricionais dentro das recomendações!"
 
 
 
95
 
96
+ # Retorna todos os componentes
97
+ return (
98
+ json.dumps(result, indent=2), # Resultado completo em JSON
99
+ gr.BarPlot(
100
+ macro_data['values'],
101
+ macro_data['labels'],
102
+ title="Distribuição de Macronutrientes",
103
+ y="Gramas"
104
+ ), # Gráfico
105
+ gr.Dataframe(
106
+ headers=['Nutriente', 'Quantidade'],
107
+ data=list(zip(nutri_table['Nutriente'], nutri_table['Quantidade']))
108
+ ), # Tabela
109
+ recommendations # Texto de recomendações
110
+ )
111
 
112
  except Exception as e:
113
+ return str(e), None, None, None
114
 
115
  # Interface Gradio
116
+ with gr.Blocks(theme=gr.themes.Soft()) as iface:
117
+ gr.Markdown("""
118
+ # 🍽️ Análise Nutricional com IA
 
 
 
119
  Faça upload de uma foto do seu prato para receber uma análise nutricional detalhada.
120
+ """)
121
+
122
+ with gr.Row():
123
+ with gr.Column():
124
+ # Inputs
125
+ image_input = gr.Image(
126
+ type="pil",
127
+ label="Foto do Prato",
128
+ sources=['upload', 'webcam']
129
+ )
130
+ api_key = gr.Textbox(
131
+ label="API Key (opcional)",
132
+ placeholder="Digite sua API key aqui...",
133
+ type="password"
134
+ )
135
+ analyze_btn = gr.Button("📊 Analisar", variant="primary")
136
+
137
+ with gr.Column():
138
+ # Outputs
139
+ with gr.Tab("Resumo"):
140
+ recommendations = gr.Textbox(
141
+ label="Recomendações",
142
+ lines=3
143
+ )
144
+ nutri_table = gr.Dataframe(
145
+ label="Tabela Nutricional",
146
+ headers=['Nutriente', 'Quantidade']
147
+ )
148
+ macro_plot = gr.Plot(
149
+ label="Macronutrientes"
150
+ )
151
+
152
+ with gr.Tab("Detalhes"):
153
+ json_output = gr.JSON(
154
+ label="Resultado Detalhado"
155
+ )
156
+
157
+ # Eventos
158
+ analyze_btn.click(
159
+ fn=analyze_nutrition,
160
+ inputs=[image_input, api_key],
161
+ outputs=[json_output, macro_plot, nutri_table, recommendations]
162
+ )
163
+
164
+ gr.Markdown("""
165
+ ### 📝 Instruções
166
+ 1. Faça upload de uma foto do seu prato ou tire uma foto com a webcam
167
+ 2. Se tiver uma API key, insira-a (opcional)
168
+ 3. Clique em "Analisar"
169
+ 4. Veja os resultados nas abas "Resumo" e "Detalhes"
170
+
171
+ ### 🎯 Dicas para melhores resultados
172
+ - Use fotos bem iluminadas
173
+ - Fotografe de cima para baixo
174
+ - Certifique-se que todos os alimentos estão visíveis
175
+ - Evite sombras ou reflexos fortes
176
+ """)
177
 
178
+ # Inicia a interface
179
  if __name__ == "__main__":
180
  iface.launch(share=True)