SnapFood / app.py
AADalhat's picture
Update app.py
256a688 verified
import gradio as gr
import tensorflow as tf
import numpy as np
from PIL import Image
import json
from datetime import datetime
import tempfile
import os
from gtts import gTTS
from fpdf import FPDF
from health_logic import generate_advice
from tensorflow.keras.applications.efficientnet import preprocess_input as efficientnet_preprocess
# Load model
model = tf.keras.models.load_model("food_vision_model.keras")
# Ensure class names are in the correct order used during training
class_names = [
"akara", "banga_soup", "egusi_soup", "jollof_rice", "moi_moi",
"nkwobi", "okpa", "suya", "tuwo", "yam_porridge"
]
# Load food metadata
with open("food_info.json", "r") as f:
food_info = json.load(f)
# Language map for TTS
LANG_CODE = {
"English": "en",
"Hausa": "en", # gTTS doesn't support Hausa properly
"Yoruba": "en",
"Igbo": "en"
}
# Risk level helper
def get_risk_level(score):
if score <= 30:
return "🟒 Low Risk"
elif score <= 70:
return "🟑 Medium Risk"
else:
return "πŸ”΄ High Risk"
# PDF class with Unicode support
class UnicodePDF(FPDF):
def header(self):
self.set_font("DejaVu", "B", 16)
self.cell(0, 10, "HoodHealth Pro+ Report", ln=True)
def footer(self):
self.set_y(-15)
self.set_font("DejaVu", "I", 8)
self.cell(0, 10, f"Generated: {datetime.now().strftime('%Y-%m-%d %H:%M')}", align="C")
def generate_pdf(info, advice, risk_score, risk_level, flags, conditions, lang, display_name, image_path):
pdf = UnicodePDF()
pdf.add_font("DejaVu", "", "DejaVuSans.ttf", uni=True)
pdf.add_font("DejaVu", "B", "DejaVuSans.ttf", uni=True)
pdf.add_font("DejaVu", "I", "DejaVuSans.ttf", uni=True)
pdf.add_page()
pdf.set_font("DejaVu", "", 12)
pdf.image(image_path, x=10, y=40, w=60)
pdf.set_xy(75, 40)
pdf.multi_cell(0, 10, f"Food: {display_name}\nEthnicity: {info['ethnicity']}\nIngredients: {info['ingredients']}")
pdf.ln(35)
pdf.multi_cell(0, 10, f"Calories: {info['calories']} kcal\nCarbs: {info['carbs']}g\nProtein: {info['protein']}g\nFat: {info['fat']}g")
pdf.ln(5)
pdf.multi_cell(0, 10, f"Diet Type: {info['diet_type']}\nSubstitute: {info.get('substitute', 'None')}")
pdf.ln(10)
pdf.set_font("DejaVu", "B", 14)
pdf.cell(0, 10, "Health Analysis", ln=True)
pdf.set_font("DejaVu", "", 12)
pdf.multi_cell(0, 10, f"Conditions: {', '.join(conditions)}\nRisk Score: {risk_score}% ({risk_level})\nRisk Factors: {', '.join(flags) if flags else 'None'}\nAdvice: {advice}")
pdf.ln(5)
pdf.set_font("DejaVu", "I", 10)
pdf.multi_cell(0, 10, "*Note: This advice is not a medical diagnosis.*")
path = os.path.join(tempfile.gettempdir(), "report.pdf")
pdf.output(path)
return path
def classify_food(image):
try:
# Convert to grayscale since model expects 1 channel
image = image.convert("L").resize((225, 225)) # "L" = grayscale
img = tf.keras.preprocessing.image.img_to_array(image)
# Ensure shape is (225, 225, 1)
if img.shape[-1] != 1:
img = np.expand_dims(img, axis=-1)
# Preprocess for EfficientNet
img = efficientnet_preprocess(img)
img = np.expand_dims(img, axis=0)
# Predict
preds = model.predict(img)
pred_class = np.argmax(preds[0])
confidence = float(np.max(preds[0]))
food_name = class_names[pred_class]
food_details = food_info[food_name]
result = f"🍽️ Food: {food_name}\n"
result += f"🌍 Ethnicity: {food_details['Ethnicity']}\n"
result += f"πŸ₯¦ Ingredients: {', '.join(food_details['Ingredients'])}\n"
result += f"πŸ”₯ Nutrients: {food_details['Nutrients']}\n"
result += f"❀️ Health Advice: {food_details['Health_Advice']}\n"
result += f"🌱 Diet Type: {food_details['Diet_Type']}\n"
result += f"πŸ“Š Confidence: {confidence:.2f}"
return result
except Exception as e:
return f"Error during classification: {str(e)}"
# Gradio interface
interface = gr.Interface(
fn=classify_food,
inputs=[
gr.Image(type="pil", label="Upload Food Image"),
gr.CheckboxGroup(label="Select Health Conditions", choices=[
"Normal", "Diabetic", "Hypertensive", "Weight Loss", "Malnourished", "Pregnant/Nursing", "Cholesterol Watch"]),
gr.Dropdown(label="Language for TTS", choices=["English", "Hausa", "Yoruba", "Igbo"], value="English")
],
outputs=[
gr.Textbox(label="Prediction and Advice"),
gr.Audio(label="Hear Advice"),
gr.Textbox(label="Language Info"),
gr.File(label="Download PDF Report")
],
title="🍲 HoodHealth Pro+",
description="Upload a food image and get nutrition details, health risk, personalized advice, audio guidance, and a downloadable PDF report."
)
if __name__ == "__main__":
interface.launch()