import streamlit as st import torch import cv2 import numpy as np from ultralytics import YOLO from PIL import Image import easyocr import requests def load_model(): # Load the pre-trained YOLOv8 model for object detection model = YOLO("yolov8n.pt") # You can use a custom-trained model for food detection return model def detect_ingredients(image, model): results = model(image) detected_items = set() for result in results: for box in result.boxes: cls = result.names[int(box.cls[0])] detected_items.add(cls) return list(detected_items) def extract_text(image): # Use EasyOCR to extract text from the image reader = easyocr.Reader(['en']) # Specify language results = reader.readtext(np.array(image)) # Convert PIL image to NumPy extracted_text = [text[1] for text in results] # Extract detected text return extracted_text MEALDB_API_URL = "https://www.themealdb.com/api/json/v1/1" def fetch_ingredients(): """Fetches a list of available ingredients from TheMealDB API.""" url = f"{MEALDB_API_URL}/list.php?i=list" response = requests.get(url) if response.status_code == 200: data = response.json() return [item["strIngredient"].lower() for item in data["meals"]] return [] def filter_valid_ingredients(detected_ingredients): """Filters detected ingredients against TheMealDB ingredient list.""" valid_ingredients = fetch_ingredients() return [ing for ing in detected_ingredients if ing.lower() in valid_ingredients] def get_recipes(ingredients): """Fetch recipes from TheMealDB based on detected ingredients.""" recipe_list = set() for ingredient in ingredients: url = f"{MEALDB_API_URL}/filter.php?i={ingredient}" response = requests.get(url) if response.status_code == 200: data = response.json() if data["meals"]: for meal in data["meals"]: recipe_list.add(meal["strMeal"]) return list(recipe_list) if recipe_list else ["No matching recipes found."] def main(): st.title("VQA Recipe Generator") st.write("Upload an image of ingredients, and we'll suggest recipes you can make!") with st.expander("How It Works"): st.write(""" 1. **Upload an Image**: Upload a photo of ingredients you have. 2. **Ingredient Detection**: The app uses a YOLOv8 model to detect visible ingredients. 3. **Text Extraction**: Any text in the image (e.g., labels) is extracted using EasyOCR. 4. **Ingredient Validation**: The detected ingredients are cross-checked with TheMealDB database. 5. **Recipe Suggestions**: The app fetches recipes that match the available ingredients. P.S This is a work in progress so it can't cater all ingredients and can't really detect if ingredients don't have labels. """) model = load_model() uploaded_file = st.file_uploader("Upload an image", type=["jpg", "png", "jpeg"]) if uploaded_file: image = Image.open(uploaded_file) st.image(image, caption="Uploaded Image", use_column_width=True) # Convert image for processing img_array = np.array(image) img_array = cv2.cvtColor(img_array, cv2.COLOR_RGB2BGR) with st.spinner("Detecting ingredients..."): detected_ingredients = detect_ingredients(img_array, model) extracted_text = extract_text(image) # Merge OCR text with detected objects detected_ingredients.extend(extracted_text) # Filter only valid ingredients from TheMealDB valid_ingredients = filter_valid_ingredients(detected_ingredients) st.subheader("Detected Ingredients:") st.write(", ".join(valid_ingredients)) recipes = get_recipes(valid_ingredients) st.subheader("Suggested Recipes:") for recipe in recipes: st.write(f"- {recipe}") if __name__ == "__main__": main()