File size: 4,968 Bytes
804a5fa
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
256a688
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
804a5fa
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
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()