Spaces:
Sleeping
Sleeping
File size: 7,130 Bytes
dd9402a |
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 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
import streamlit as st
import os
import json
import cv2
import pandas as pd
from ultralytics import YOLO
from PIL import Image
# Configure Streamlit pages
st.set_page_config(
page_title="NutriDetect: AI-powered Food Detection and Nutritional Insights",
page_icon="π΄",
# Set layout to wide for better visualization
)
# Sidebar navigation
st.sidebar.title("Navigation")
page = st.sidebar.radio("Go to", ["Home", "Description", "Try Models"])
# Load nutritional data from the JSON file
def load_nutritional_data(json_path):
with open(json_path, 'r') as file:
data = json.load(file)
for food in data["food"]:
food["preprocessed_name"] = food["name"].lower().replace(",", "").strip()
return data
# Load models
@st.cache_resource
def load_models():
yolov8_model = YOLO("./model/Yolov8m.pt")
yolov11_model = YOLO("./model/Yolo11m.pt")
return yolov8_model, yolov11_model
# Global variables for models and nutritional data
models = load_models()
nutritional_json_path = "db.json"
nutritional_data = load_nutritional_data(nutritional_json_path)
# Home Page
if page == "Home":
st.title("π΄ NutriDetect: Food Detection and Nutritional Insights")
st.markdown("**Welcome to the NutriDetect App!** Leverage cutting-edge AI to identify food items and provide nutritional details.")
st.image("back_image.png", use_container_width=True, caption="AI-powered Food Detection")
st.subheader("π Key Features")
st.markdown("""
- **Accurate Food Detection**: Identify food items in images.
- **Nutritional Insights**: Get calorie, protein, fat, and other details for detected food.
""")
# Description Page
elif page == "Description":
st.title("π About the NutriDetect App")
st.markdown("""
The NutriDetect App uses YOLO-based models for accurate food detection and provides:
- Bounding boxes for detected food items.
- Detailed nutritional insights for the detected items.
""")
# Try Models Page
elif page == "Try Models":
st.title("π― Try the Models")
uploaded_file = st.file_uploader("Upload an image (jpg, jpeg, png)", type=["jpg", "jpeg", "png"])
if uploaded_file:
st.subheader("Step 2: Choose Model")
model_option = st.selectbox("Select Model", ["YOLOv8m", "YOLO11m"])
if st.button("π Detect"):
with st.spinner("Processing..."):
# Save the uploaded file temporarily
temp_file_path = "temp_image.jpg"
with open(temp_file_path, "wb") as f:
f.write(uploaded_file.getbuffer())
# Perform detection
model = models[0] if model_option == "YOLOv8m" else models[1]
results = model(temp_file_path)
# Process detected items
detected_items = []
for box in results[0].boxes.data.cpu().numpy():
label = int(box[5]) # Get the class label
class_name = model.names[label]
nutrition_info = next(
(food["nutrients"] for food in nutritional_data["food"] if food["preprocessed_name"] == class_name.lower().replace(",", "").strip()),
None
)
if nutrition_info:
detected_items.append(
{
"Food": class_name,
"Calories": round(nutrition_info.get("calories", 0), 2),
"Protein": round(nutrition_info.get("protein", 0), 2),
"Fat": round(nutrition_info.get("fat", 0), 2),
"Carbs": round(nutrition_info.get("carbs", 0), 2),
"Fiber": round(nutrition_info.get("fiber", 0), 2),
}
)
# Handle case with no detected items
if not detected_items:
st.warning("No food items detected, sorry!")
else:
# Convert detected items to DataFrame
df = pd.DataFrame(detected_items)
# Calculate totals
totals = {
"Calories": round(df["Calories"].sum(), 2),
"Protein": round(df["Protein"].sum(), 2),
"Fat": round(df["Fat"].sum(), 2),
"Carbs": round(df["Carbs"].sum(), 2),
"Fiber": round(df["Fiber"].sum(), 2),
}
# Display annotated image
annotated_image = cv2.cvtColor(results[0].plot(), cv2.COLOR_BGR2RGB)
st.image(annotated_image, caption=f"{model_option} Results", use_container_width=True)
# Two-column layout for detected items and totals
left_col, right_col = st.columns([2, 1])
# Left column: Individual food items
with left_col:
st.header("Detected Food Items")
for _, row in df.iterrows():
st.subheader(row["Food"])
st.write(f"Calories: {row['Calories']} Cal")
st.write(f"Protein: {row['Protein']} g")
st.write(f"Fat: {row['Fat']} g")
st.write(f"Carbs: {row['Carbs']} g")
st.write(f"Fiber: {row['Fiber']} g")
st.write("---")
# Right column: Total nutritional summary
# Right column: Total nutritional summary
# Right column: Total nutritional summary
with right_col:
st.header("Total Nutritional Summary")
st.metric("Total Calories", f"{totals['Calories']} Cal")
st.metric("Total Protein", f"{totals['Protein']} g")
st.metric("Total Fat", f"{totals['Fat']} g")
st.metric("Total Carbs", f"{totals['Carbs']} g")
st.metric("Total Fiber", f"{totals['Fiber']} g")
# Check for unhealthy items and provide recommendations
detected_foods = df["Food"].str.lower().tolist() # Convert to lowercase for matching
unhealthy_items = [item for item in detected_foods if item in ["pizza", "hamburger", "french fries"]]
if unhealthy_items:
st.warning(
f"Detected unhealthy food items: {', '.join(unhealthy_items)}. "
"Consider replacing them with fruits and green salad for better health. π₯π"
)
else:
st.success("Balanced meals lead to a healthier life! π")
|