Spaces:
Build error
Build error
import gradio as gr | |
import torch | |
from transformers import AutoModelForCausalLM, AutoTokenizer, AutoProcessor | |
import pandas as pd | |
import numpy as np | |
from PIL import Image | |
def load_model(): | |
"""Inicializa o modelo DeepSeek Multimodal""" | |
device = "cuda" if torch.cuda.is_available() else "cpu" | |
model_name = "deepseek-ai/deepseek-vl-7b-base" | |
processor = AutoProcessor.from_pretrained(model_name) | |
model = AutoModelForCausalLM.from_pretrained( | |
model_name, | |
torch_dtype=torch.float16 if device == "cuda" else torch.float32, | |
device_map="auto", | |
trust_remote_code=True | |
) | |
tokenizer = AutoTokenizer.from_pretrained(model_name) | |
return model, processor, tokenizer, device | |
# Base de dados nutricional | |
NUTRITION_DB = { | |
"arroz": {"calorias": 130, "proteinas": 2.7, "carboidratos": 28, "gorduras": 0.3}, | |
"feijão": {"calorias": 77, "proteinas": 5.2, "carboidratos": 13.6, "gorduras": 0.5}, | |
"frango": {"calorias": 165, "proteinas": 31, "carboidratos": 0, "gorduras": 3.6}, | |
"salada": {"calorias": 15, "proteinas": 1.4, "carboidratos": 2.9, "gorduras": 0.2}, | |
"batata": {"calorias": 93, "proteinas": 2.5, "carboidratos": 21, "gorduras": 0.1}, | |
"carne": {"calorias": 250, "proteinas": 26, "carboidratos": 0, "gorduras": 17}, | |
"peixe": {"calorias": 206, "proteinas": 22, "carboidratos": 0, "gorduras": 12}, | |
"macarrão": {"calorias": 158, "proteinas": 5.8, "carboidratos": 31, "gorduras": 1.2}, | |
"ovo": {"calorias": 155, "proteinas": 13, "carboidratos": 1.1, "gorduras": 11}, | |
} | |
def process_image(image, progress=gr.Progress()): | |
"""Processa a imagem usando DeepSeek Multimodal""" | |
try: | |
progress(0.3, desc="Inicializando modelo...") | |
model, processor, tokenizer, device = load_model() | |
progress(0.5, desc="Processando imagem...") | |
# Prepara a imagem | |
if isinstance(image, np.ndarray): | |
image = Image.fromarray(image) | |
# Prompt específico para identificação de alimentos | |
prompt = "Analise esta imagem e liste todos os alimentos visíveis. Para cada alimento, informe o tipo e estado (ex: cozido, cru, grelhado)." | |
# Processa a imagem | |
inputs = processor(images=image, text=prompt, return_tensors="pt").to(device) | |
progress(0.7, desc="Gerando descrição...") | |
# Gera a descrição | |
with torch.no_grad(): | |
outputs = model.generate( | |
**inputs, | |
max_new_tokens=150, | |
do_sample=True, | |
temperature=0.7, | |
top_p=0.9, | |
) | |
# Decodifica a saída | |
description = processor.decode(outputs[0], skip_special_tokens=True) | |
progress(1.0, desc="Concluído!") | |
return description.strip() | |
except Exception as e: | |
raise gr.Error(f"Erro no processamento da imagem: {str(e)}") | |
def analyze_foods(description): | |
"""Analisa a descrição e retorna informações nutricionais""" | |
try: | |
# Identifica alimentos da base de dados na descrição | |
found_foods = [] | |
for food in NUTRITION_DB.keys(): | |
if food in description.lower(): | |
found_foods.append(food) | |
if not found_foods: | |
return "Nenhum alimento conhecido identificado.", None, None | |
# Calcula nutrientes | |
total_nutrients = { | |
"calorias": 0, | |
"proteinas": 0, | |
"carboidratos": 0, | |
"gorduras": 0 | |
} | |
for food in found_foods: | |
for nutrient, value in NUTRITION_DB[food].items(): | |
total_nutrients[nutrient] += value | |
# Prepara dados para visualização | |
table_data = [ | |
["Calorias", f"{total_nutrients['calorias']:.1f} kcal"], | |
["Proteínas", f"{total_nutrients['proteinas']:.1f}g"], | |
["Carboidratos", f"{total_nutrients['carboidratos']:.1f}g"], | |
["Gorduras", f"{total_nutrients['gorduras']:.1f}g"] | |
] | |
# Dados para o gráfico | |
plot_data = pd.DataFrame({ | |
'Nutriente': ['Proteínas', 'Carboidratos', 'Gorduras'], | |
'Quantidade': [ | |
total_nutrients['proteinas'], | |
total_nutrients['carboidratos'], | |
total_nutrients['gorduras'] | |
] | |
}) | |
analysis = f"""### 🍽️ Descrição do Modelo: | |
{description} | |
### 🔍 Alimentos Identificados: | |
• {', '.join(found_foods)} | |
### 📊 Análise Nutricional: | |
• Calorias Totais: {total_nutrients['calorias']:.1f} kcal | |
• Proteínas: {total_nutrients['proteinas']:.1f}g | |
• Carboidratos: {total_nutrients['carboidratos']:.1f}g | |
• Gorduras: {total_nutrients['gorduras']:.1f}g | |
### 💡 Avaliação: | |
{"✅ Refeição balanceada!" if total_nutrients['proteinas'] > 15 else "⚠️ Considere adicionar mais proteínas"} | |
{"✅ Carboidratos adequados" if total_nutrients['carboidratos'] < 60 else "⚠️ Alto teor de carboidratos"} | |
{"✅ Gorduras em nível adequado" if total_nutrients['gorduras'] < 20 else "⚠️ Alto teor de gorduras"} | |
""" | |
return analysis, table_data, plot_data | |
except Exception as e: | |
raise gr.Error(f"Erro na análise: {str(e)}") | |
def analyze_image(image): | |
"""Função principal que coordena o processo de análise""" | |
try: | |
# Processa a imagem | |
description = process_image(image) | |
# Analisa os alimentos | |
analysis, table_data, plot_data = analyze_foods(description) | |
return analysis, table_data, plot_data | |
except Exception as e: | |
return str(e), None, None | |
# Interface Gradio | |
with gr.Blocks(theme=gr.themes.Soft()) as iface: | |
gr.Markdown(""" | |
# 🍽️ Análise Nutricional com DeepSeek | |
Faça upload de uma foto do seu prato para análise nutricional detalhada. | |
""") | |
with gr.Row(): | |
# Coluna de Input | |
with gr.Column(): | |
image_input = gr.Image( | |
type="pil", | |
label="Foto do Prato", | |
sources=["upload", "webcam"] | |
) | |
analyze_btn = gr.Button("📊 Analisar", variant="primary", size="lg") | |
with gr.Accordion("📝 Dicas", 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 de Output | |
with gr.Column(): | |
# Análise textual | |
output_text = gr.Markdown() | |
with gr.Row(): | |
# Tabela nutricional | |
output_table = gr.Dataframe( | |
headers=["Nutriente", "Quantidade"], | |
label="Informação Nutricional", | |
wrap=True | |
) | |
# Gráfico | |
output_plot = gr.BarPlot( | |
x="Nutriente", | |
y="Quantidade", | |
title="Macronutrientes (g)", | |
height=300, | |
tooltip=["Nutriente", "Quantidade"] | |
) | |
# Eventos | |
analyze_btn.click( | |
fn=analyze_image, | |
inputs=[image_input], | |
outputs=[output_text, output_table, output_plot] | |
) | |
if __name__ == "__main__": | |
print(f"Usando dispositivo: {'CUDA' if torch.cuda.is_available() else 'CPU'}") | |
iface.launch() |