FoodVision / cal.py
nightey3s's picture
Update cal.py
6953fda verified
# cal.py
import torch
from ultralytics import YOLO
import cv2
import numpy as np
import matplotlib.pyplot as plt
import streamlit as st
# Configuration class
class Config:
CLASSES = ['asparagus', 'avocados', 'broccoli', 'cabbage', #4
'celery', 'cucumber', 'green_apples', 'green_beans', #4
'green_capsicum', 'green_grapes', 'kiwifruit', #3
'lettuce', 'limes', 'peas', 'spinach', #4
'Banana', 'Cauliflower', 'Date', 'Garlic', #4
'Ginger', 'Mushroom', 'Onion', 'Parsnip', #4
'Peach', 'Pear', 'Potato', 'Turnip', #4
'Beetroot', 'Blackberry', 'Blueberry', 'Cherry', #4
'Eggplant', 'Plum', 'Purple asparagus', 'Purple grapes', #4
'Radish', 'Raspberry', 'Red Apple', 'Red Grape', #4
'Red cabbage', 'Red capsicum', 'Strawberry', 'Tomato', #4
'Watermelon', 'apricot', 'carrot', 'corn', #4
'grapefruit', 'lemon', 'mango', 'nectarine', #4
'orange', 'pineapple', 'pumpkin', 'sweet_potato'] #4
CALORIES_DICT = {
# Green foods (existing)
'asparagus': 20,
'avocados': 160,
'broccoli': 55,
'cabbage': 25,
'celery': 16,
'cucumber': 16,
'green_apples': 52,
'green_beans': 31,
'green_capsicum': 20,
'green_grapes': 69,
'kiwifruit': 61,
'lettuce': 15,
'limes': 30,
'peas': 81,
'spinach': 23,
# White/Beige foods
'Banana': 89,
'Cauliflower': 25,
'Date': 282,
'Garlic': 149,
'Ginger': 80,
'Mushroom': 22,
'Onion': 40,
'Parsnip': 75,
'Peach': 39,
'Pear': 57,
'Potato': 77,
'Turnip': 28,
# Purple/Red foods
'Beetroot': 43,
'Blackberry': 43,
'Blueberry': 57,
'Cherry': 50,
'Eggplant': 25,
'Plum': 46,
'Purple asparagus': 20,
'Purple grapes': 69,
'Radish': 16,
'Raspberry': 52,
'Red Apple': 52,
'Red Grape': 69,
'Red cabbage': 31,
'Red capsicum': 31,
'Strawberry': 32,
'Tomato': 18,
'Watermelon': 30,
# Orange/Yellow foods
'apricot': 48,
'carrot': 41,
'corn': 86,
'grapefruit': 42,
'lemon': 29,
'mango': 60,
'nectarine': 44,
'orange': 47,
'pineapple': 50,
'pumpkin': 26,
'sweet_potato': 86
}
# Load the model
@st.cache_resource
def load_model():
model = YOLO('./best.pt')
return model
# Function to make predictions on a single image
def predict_image(image_path, model, conf_threshold=0.03):
# Perform inference on the image
results = model.predict(
source=image_path,
imgsz=640,
conf=conf_threshold
)
# Load the image for visualization
image = cv2.imread(image_path)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
# To store detailed information about detections
detection_details = []
# Iterate over detections
for result in results[0].boxes.data:
# Extract bounding box coordinates, confidence score, and class ID
x1, y1, x2, y2, confidence, class_id = result.cpu().numpy()
# Draw the bounding box with top confidence score
cv2.rectangle(image, (int(x1), int(y1)), (int(x2), int(y2)), color=(0, 255, 0), thickness=2)
label = f"{Config.CLASSES[int(class_id)]}: {confidence:.2f}"
cv2.putText(image, label, (int(x1), int(y1) - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), thickness=1)
# Save details for printing below
detection_details.append({
"class": Config.CLASSES[int(class_id)],
"top_confidence": confidence,
"bbox": (x1, y1, x2, y2)
})
return image, detection_details
# Function to calculate detected items and their calories
def calculate_calories(detection_details):
"""
Calculate calories for detected items, keeping only the highest confidence detection for each unique food item.
Args:
detection_details: List of dictionaries containing detection information
Each dict has keys: "class" (food name), "top_confidence" (detection confidence), "bbox"
Returns:
List of tuples: (food_item, calories, confidence) for unique items with highest confidence
"""
# Dictionary to keep track of highest confidence detection for each food item
unique_items = {}
# Process each detection
for det in detection_details:
item = det["class"]
confidence = det["top_confidence"]
# Only update if this is the first instance or has higher confidence
if item not in unique_items or confidence > unique_items[item]["confidence"]:
unique_items[item] = {
"calories": Config.CALORIES_DICT[item],
"confidence": confidence
}
# Convert to list of tuples format
detected_items = [
(item, data["calories"], data["confidence"])
for item, data in unique_items.items()
]
# Sort by confidence (optional)
detected_items.sort(key=lambda x: x[2], reverse=True)
return detected_items