Spaces:
Build error
Build error
import gradio as gr | |
import numpy as np | |
import os | |
from dotenv import load_dotenv | |
import pandas as pd | |
from transformers import Blip2Processor, Blip2ForConditionalGeneration | |
import torch | |
# Carrega variáveis de ambiente | |
load_dotenv() | |
API_KEY = os.getenv('NUTRITION_API_KEY', '') | |
# Carrega o modelo BLIP2 | |
model_name = "Salesforce/blip2-opt-2.7b" | |
processor = Blip2Processor.from_pretrained(model_name) | |
model = Blip2ForConditionalGeneration.from_pretrained(model_name, torch_dtype=torch.float16, device_map="auto") | |
def identify_foods(image): | |
"""Identifica alimentos na imagem usando BLIP2""" | |
prompt = "Liste todos os alimentos visíveis nesta imagem de refeição." | |
inputs = processor(image, text=prompt, return_tensors="pt").to(model.device) | |
outputs = model.generate( | |
**inputs, | |
max_new_tokens=100, | |
do_sample=False, | |
num_beams=5, | |
temperature=1.0, | |
top_p=0.9, | |
) | |
return processor.decode(outputs[0], skip_special_tokens=True) | |
def analyze_nutrition(image): | |
"""Análise nutricional da imagem""" | |
try: | |
# Identifica alimentos | |
identified_foods = identify_foods(image) | |
# Simula análise nutricional | |
nutrients = { | |
"calorias": 450, | |
"proteinas": 25, | |
"carboidratos": 55, | |
"gorduras": 15, | |
"fibras": 8 | |
} | |
# Dados do gráfico | |
plot_data = pd.DataFrame({ | |
'Nutriente': ['Proteínas', 'Carboidratos', 'Gorduras'], | |
'Quantidade': [nutrients['proteinas'], nutrients['carboidratos'], nutrients['gorduras']] | |
}) | |
# Tabela nutricional | |
table_data = [ | |
["Calorias", f"{nutrients['calorias']:.1f} kcal"], | |
["Proteínas", f"{nutrients['proteinas']:.1f}g"], | |
["Carboidratos", f"{nutrients['carboidratos']:.1f}g"], | |
["Gorduras", f"{nutrients['gorduras']:.1f}g"], | |
["Fibras", f"{nutrients['fibras']:.1f}g"] | |
] | |
# Análise e recomendações | |
analysis = [] | |
if nutrients['calorias'] > 800: | |
analysis.append("⚠️ Alto valor calórico") | |
if nutrients['proteinas'] < 15: | |
analysis.append("⚠️ Baixo teor de proteínas") | |
if nutrients['fibras'] < 6: | |
analysis.append("⚠️ Baixo teor de fibras") | |
analysis_text = "\n".join(analysis) if analysis else "✅ Valores nutricionais adequados" | |
# Recomendações personalizadas | |
recommendations = [] | |
if "Alto valor calórico" in analysis_text: | |
recommendations.append("• Considere reduzir as porções") | |
if "Baixo teor de proteínas" in analysis_text: | |
recommendations.append("• Adicione mais fontes de proteína como frango, peixe ou leguminosas") | |
if "Baixo teor de fibras" in analysis_text: | |
recommendations.append("• Inclua mais vegetais e grãos integrais") | |
recommendations_text = "\n".join(recommendations) if recommendations else "• Continue mantendo uma alimentação equilibrada!" | |
return ( | |
identified_foods, | |
table_data, | |
plot_data, | |
analysis_text, | |
recommendations_text, | |
"success" # Status para UI | |
) | |
except Exception as e: | |
return ( | |
None, None, None, None, | |
f"Erro na análise: {str(e)}", | |
"error" # Status para UI | |
) | |
# Interface Gradio | |
with gr.Blocks(theme=gr.themes.Soft()) as iface: | |
# Cabeçalho | |
with gr.Row(variant="compact"): | |
gr.Markdown(""" | |
# 🍽️ Análise Nutricional com IA | |
""") | |
# Container Principal | |
with gr.Row(): | |
# Coluna da Esquerda - Input | |
with gr.Column(scale=2): | |
gr.Markdown("### 📸 Foto do Prato") | |
image_input = gr.Image( | |
type="pil", | |
sources=["upload", "webcam"], | |
height=400, | |
label="" | |
) | |
with gr.Row(): | |
analyze_btn = gr.Button("🔍 Analisar Prato", variant="primary", size="lg") | |
clear_btn = gr.Button("🔄 Limpar", size="lg") | |
with gr.Accordion("📝 Dicas para Melhores Resultados", open=False): | |
gr.Markdown(""" | |
- Use fotos bem iluminadas | |
- Fotografe de cima para baixo | |
- Certifique-se que todos os alimentos estão visíveis | |
- Evite sombras ou reflexos fortes | |
""") | |
# Coluna da Direita - Resultados | |
with gr.Column(scale=3): | |
# Status | |
status = gr.Markdown(visible=False) | |
with gr.Tabs(): | |
# Tab de Identificação | |
with gr.Tab("🔍 Alimentos Identificados"): | |
foods_detected = gr.Markdown( | |
label="", | |
value="Faça o upload de uma imagem e clique em Analisar" | |
) | |
# Tab de Nutrientes | |
with gr.Tab("📊 Informação Nutricional"): | |
with gr.Row(): | |
nutri_table = gr.Dataframe( | |
headers=["Nutriente", "Quantidade"], | |
label="", | |
wrap=True | |
) | |
with gr.Row(): | |
macro_plot = gr.BarPlot( | |
label="", | |
title="Distribuição de Macronutrientes (g)", | |
x="Nutriente", | |
y="Quantidade", | |
height=300, | |
tooltip=["Nutriente", "Quantidade"] | |
) | |
# Tab de Análise | |
with gr.Tab("💡 Análise e Recomendações"): | |
with gr.Box(): | |
gr.Markdown("#### 📋 Análise") | |
analysis_output = gr.Markdown() | |
with gr.Box(): | |
gr.Markdown("#### ✨ Recomendações") | |
recommendations_output = gr.Markdown() | |
# Event handlers | |
def clear_outputs(): | |
return { | |
foods_detected: "Faça o upload de uma imagem e clique em Analisar", | |
nutri_table: None, | |
macro_plot: None, | |
analysis_output: None, | |
recommendations_output: None, | |
status: gr.Markdown(visible=False) | |
} | |
analyze_btn.click( | |
fn=analyze_nutrition, | |
inputs=[image_input], | |
outputs=[ | |
foods_detected, | |
nutri_table, | |
macro_plot, | |
analysis_output, | |
recommendations_output, | |
status | |
] | |
) | |
clear_btn.click( | |
fn=clear_outputs, | |
outputs=[ | |
foods_detected, | |
nutri_table, | |
macro_plot, | |
analysis_output, | |
recommendations_output, | |
status | |
] | |
) | |
# Inicia a interface | |
if __name__ == "__main__": | |
if not API_KEY: | |
print("⚠️ Atenção: API Key não encontrada!") | |
print("Configure a variável de ambiente NUTRITION_API_KEY no arquivo .env") | |
iface.launch(share=False) |