Spaces:
Sleeping
Sleeping
import streamlit as st | |
import cv2 | |
from ultralytics import YOLO | |
from paddleocr import PaddleOCR | |
from tensorflow.keras.models import load_model | |
from tensorflow.keras.preprocessing.image import img_to_array | |
import numpy as np | |
import re | |
from datetime import datetime | |
import pandas as pd | |
# Load YOLO models | |
brand_model = YOLO('b.pt') # Replace 'b.pt' with the correct path to your YOLO model for brands | |
ocr = PaddleOCR(lang='en') # Initialize PaddleOCR | |
fruit_model = load_model('DenseNet20_model.h5') # Replace with the correct path to your fruit freshness model | |
object_model = YOLO('yolov5s.pt') # Add object detection model | |
# Class names for freshness detection | |
class_names = { | |
0: 'Banana_Bad', 1: 'Banana_Good', 2: 'Fresh', 3: 'FreshCarrot', 4: 'FreshCucumber', | |
5: 'FreshMango', 6: 'FreshTomato', 7: 'Guava_Bad', 8: 'Guava_Good', 9: 'Lime_Bad', | |
10: 'Lime_Good', 11: 'Rotten', 12: 'RottenCarrot', 13: 'RottenCucumber', | |
14: 'RottenMango', 15: 'RottenTomato', 16: 'freshBread', 17: 'rottenBread' | |
} | |
# Custom CSS for styling | |
st.markdown(""" | |
<style> | |
.main { | |
background-color: #f0f2f6; | |
padding: 20px; | |
border-radius: 10px; | |
} | |
.stButton>button { | |
background-color: #4CAF50; | |
color: white; | |
border-radius: 8px; | |
padding: 10px 24px; | |
font-size: 16px; | |
margin: 10px 0; | |
} | |
.stButton>button:hover { | |
background-color: #45a049; | |
} | |
.stSidebar { | |
background-color: #2c3e50; | |
color: white; | |
} | |
.stSidebar .stSelectbox { | |
color: black; | |
} | |
h1, h2, h3, h4, h5, h6 { | |
color: #2c3e50; | |
} | |
</style> | |
""", unsafe_allow_html=True) | |
# Helper function: Extract expiry dates | |
def extract_expiry_dates(text): | |
patterns = [ | |
r'(\d{1,2}[\/\-]\d{1,2}[\/\-]\d{4})', # 20/07/2024 or 20-07-2024 | |
r'(\d{1,2}[\/\-]\d{1,2}[\/\-]\d{2})', # 20/07/24 or 20-07-24 | |
r'(\d{1,2}\s*[A-Za-z]{3,}\s*\d{4})', # 20 MAY 2024 | |
r'([A-Za-z]{3,}\s*\d{1,2}[,\s]*\d{4})', # July 20, 2024 | |
r'(\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2})', # 2024/07/20 or 2024-07-20 | |
r'([A-Za-z]{3}[\-]\d{1,2}[\-]\d{4})', | |
r'(?:exp(?:iry)?\.?\s*date\s*[:\-]?\s*.*?(\d{2}[\/\-]\d{2}[\/\-][0O]\d{2}))', # Expiry Date: 20/07/2O24 | |
r'(?:exp(?:iry)?\.?\s*date\s*[:\-]?\s*.*?(\d{2}[\/\-]\d{2}[\/\-]\d{4}))', # Expiry Date: 20/07/2024 | |
r'(?:exp(?:iry)?\.?\s*date\s*[:\-]?\s*.*?(\d{2}[\/\-]\d{2}[\/\-][0O]\d{2}))', # Expiry Date: 20/07/2O24 | |
r'(?:exp(?:iry)?\.?\s*date\s*[:\-]?\s*.?(\d{2}\s[A-Za-z]{3,}\s*[0O]\d{2}))', # Expiry Date: 20 MAY 2O24 | |
r'(?:exp(?:iry)?\.?\s*date\s*[:\-]?\s*.?(\d{2}\s[A-Za-z]{3,}\s*\d{4}))', # Expiry Date: 20 MAY 2024 | |
r'(?:exp(?:iry)?\.?\s*date\s*[:\-]?\s*.?(\d{2}\s[A-Za-z]{3,}\s*[0O]\d{2}))', # Expiry Date: 20 MAY 2O24 | |
r'(?:exp(?:iry)?\.?\s*date\s*[:\-]?\s*.*?(\d{4}[\/\-]\d{2}[\/\-][0O]\d{2}))', # Expiry Date: 2024/07/2O24 | |
r'(?:exp(?:iry)?\.?\s*date\s*[:\-]?\s*.*?(\d{4}[\/\-]\d{2}[\/\-]\d{2}))', # Expiry Date: 2024/07/20 | |
r'(?:best\s*before\s*[:\-]?\s*.*?(\d{4}))', # Best Before: 2025 | |
r'(?:best\s*before\s*[:\-]?\s*.*?(\d{2}[\/\-]\d{2}[\/\-][0O]\d{2}))', # Best Before: 20/07/2O24 | |
r'(?:best\s*before\s*[:\-]?\s*.*?(\d{2}[\/\-]\d{2}[\/\-]\d{4}))', # Best Before: 20/07/2024 | |
r'(?:best\s*before\s*[:\-]?\s*.*?(\d{2}[\/\-]\d{2}[\/\-][0O]\d{2}))', # Best Before: 20/07/2O24 | |
r'(?:best\s*before\s*[:\-]?\s*.?(\d{2}\s[A-Za-z]{3,}\s*[0O]\d{2}))', # Best Before: 20 MAY 2O24 | |
r'(?:best\s*before\s*[:\-]?\s*.?(\d{2}\s[A-Za-z]{3,}\s*\d{4}))', # Best Before: 20 MAY 2024 | |
r'(?:best\s*before\s*[:\-]?\s*.?(\d{2}\s[A-Za-z]{3,}\s*[0O]\d{2}))', # Best Before: 20 MAY 2O24 | |
r'(?:best\s*before\s*[:\-]?\s*.*?(\d{4}[\/\-]\d{2}[\/\-][0O]\d{2}))', # Best Before: 2024/07/2O24 | |
r'(?:best\s*before\s*[:\-]?\s*.*?(\d{4}[\/\-]\d{2}[\/\-]\d{2}))', # Best Before: 2024/07/20 | |
r'(?:best\s*before\s*[:\-]?\s*.*?(\d{1,2}\d{2}\d{2}))', | |
r'(?:best\s*before\s*[:\-]?\s*(\d{6}))', | |
r'(?:consume\s*before\s*[:\-]?\s*.*?(\d{1,2}[A-Za-z]{3,}[0O]\d{2}))', # Consume Before: 3ODEC2O24 | |
r'(?:consume\s*before\s*[:\-]?\s*.*?(\d{1,2}[A-Za-z]{3,}\d{2}))', # Consume Before: 30DEC23 | |
r'(?:consume\s*before\s*[:\-]?\s*.*?(\d{2}[\/\-]\d{2}[\/\-][0O]\d{2}))', # Consume Before: 20/07/2O24 | |
r'(?:consume\s*before\s*[:\-]?\s*.*?(\d{2}[\/\-]\d{2}[\/\-]\d{4}))', # Consume Before: 20/07/2024 | |
r'(?:consume\s*before\s*[:\-]?\s*.*?(\d{2}[\/\-]\d{2}[\/\-][0O]\d{2}))', # Consume Before: 20/07/2O24 | |
r'(?:consume\s*before\s*[:\-]?\s*.?(\d{2}\s[A-Za-z]{3,}\s*[0O]\d{2}))', # Consume Before: 20 MAY 2O24 | |
r'(?:consume\s*before\s*[:\-]?\s*.?(\d{2}\s[A-Za-z]{3,}\s*\d{4}))', # Consume Before: 20 MAY 2024 | |
r'(?:consume\s*before\s*[:\-]?\s*.?(\d{2}\s[A-Za-z]{3,}\s*[0O]\d{2}))', # Consume Before: 20 MAY 2O24 | |
r'(?:consume\s*before\s*[:\-]?\s*.*?(\d{4}[\/\-]\d{2}[\/\-][0O]\d{2}))', # Consume Before: 2024/07/2O24 | |
r'(?:consume\s*before\s*[:\-]?\s*.*?(\d{4}[\/\-]\d{2}[\/\-]\d{2}))', # Consume Before: 2024/07/20 | |
r'(?:exp\s*[:\-]?\s*.*?(\d{2}[\/\-]\d{2}[\/\-][0O]\d{2}))', # Exp: 20/07/2O24 | |
r'(?:exp\s*[:\-]?\s*.*?(\d{2}[\/\-]\d{2}[\/\-]\d{4}))', # Exp: 20/07/2024 | |
r'(?:exp\s*[:\-]?\s*.*?(\d{2}[\/\-]\d{2}[\/\-][0O]\d{2}))', # Exp: 20/07/2O24 | |
r'(?:exp\s*[:\-]?\s*.?(\d{2}\s[A-Za-z]{3,}\s*[0O]\d{2}))', # Exp: 20 MAY 2O24 | |
r'(?:exp\s*[:\-]?\s*.?(\d{2}\s[A-Za-z]{3,}\s*\d{4}))', # Exp: 20 MAY 2024 | |
r'(?:exp\s*[:\-]?\s*.?(\d{2}\s[A-Za-z]{3,}\s*[0O]\d{2}))', # Exp: 20 MAY 2O24 | |
r'(?:exp\s*[:\-]?\s*.*?(\d{4}[\/\-]\d{2}[\/\-][0O]\d{2}))', # Exp: 2024/07/2O24 | |
r'(?:exp\s*[:\-]?\s*.*?(\d{4}[\/\-]\d{2}[\/\-]\d{2}))', # Exp: 2024/07/20 | |
r'Exp\.Date\s+(\d{2}[A-Z]{3}\d{4})', | |
r'(?:exp\s*\.?\s*date\s*[:\-]?\s*.?(\d{2}\s[A-Za-z]{3,}\s*[0O]\d{2}))', # Exp. Date: 16 MAR 2O30 (with typo) | |
r'(?:exp\s*\.?\s*date\s*[:\-]?\s*.*?(\d{2}[\/\-]\d{2}[\/\-][0O]\d{2}))', # Exp. Date: 15/12/2O30 (with typo) | |
r'(?:exp\s*\.?\s*date\s*[:\-]?\s*.?(\d{2}\s[A-Za-z]{3,}\s*[0O]\d{2}))', # Exp. Date: 15 MAR 2O30 (with typo) | |
r'(?:exp\s*\.?\s*date\s*[:\-]?\s*.?(\d{2}\s[A-Za-z]{3,}\s*[0O]\d{2}))', # Exp. Date cdsyubfuyef 15 MAR 2O30 (with typo) | |
r'(\d{2}[\/\-]\d{2}[\/\-]\d{4})', # 20/07/2024 | |
r'(\d{2}[\/\-]\d{2}[\/\-]\d{2})', # 20/07/24 | |
r'(\d{2}\s*[A-Za-z]{3,}\s*\d{4})', # 20 MAY 2024 | |
r'(\d{2}\s*[A-Za-z]{3,}\s*\d{2})', # 20 MAY 24 | |
r'(\d{4}[\/\-]\d{2}[\/\-]\d{2})', # 2024/07/20 | |
r'(\d{4}[\/\-]\d{2}[\/\-]\d{2})', # 2024-07-20 | |
r'(\d{4}[A-Za-z]{3,}\d{2})', # 2024MAY20 | |
r'(\d{2}[A-Za-z]{3,}\d{4})', # 20MAY2024 | |
r'(?:exp\.?\s*date\s*[:\-]?\s*(\d{2}\s*[A-Za-z]{3,}\s*(\d{4}|\d{2})))', | |
r'(?:exp\.?\s*date\s*[:\-]?\s*(\d{2}\s*\d{2}\s*\d{4}))', # Exp. Date: 20 05 2025 | |
r'(\d{4}[A-Za-z]{3}\d{2})', # 2025MAY11 | |
r'(?:best\s*before\s*[:\-]?\s*(\d+)\s*(days?|months?|years?))', # Best Before: 6 months | |
r'(?:best\s*before\s*[:\-]?\s*(three)\s*(months?))', | |
r'(\b(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\b\s*\d{4})', | |
r'\bUSE BY\s+(\d{1,2}[A-Za-z]{3}\d{4})\b', | |
r'Exp\.Date\s*(\d{2}[A-Z]{3}\d{4})', | |
r'EXP:\d{4}/\d{2}/\d{4}/\d{1}/[A-Z]', # JAN-15-2024 | |
r'USE BY[:\-]?\s*(\d{1,2}[\/\-]\d{1,2}[\/\-]\d{4})', # Use by date | |
r'BEST BEFORE[:\-]?\s*(\d{1,2}[\/\-]\d{1,2}[\/\-]\d{4})', # Best before date | |
r'EXPIRY DATE[:\-]?\s*(\d{1,2}[\/\-]\d{1,2}[\/\-]\d{4})', # Expiry Date | |
r'EXPIRY[:\-]?\s*(\d{1,2}[\/\-]\d{1,2}[\/\-]\d{4})', # Expiry | |
r'EXP[:\-]?\s*(\d{1,2}[\/\-]\d{1,2}[\/\-]\d{4})', # Exp | |
r'VALID UNTIL[:\-]?\s*(\d{1,2}[\/\-]\d{1,2}[\/\-]\d{4})', # Valid Until | |
r'CONSUME BY[:\-]?\s*(\d{1,2}[\/\-]\d{1,2}[\/\-]\d{4})', # Consume By | |
r'EXPIRES ON[:\-]?\s*(\d{1,2}[\/\-]\d{1,2}[\/\-]\d{4})', # Expires On | |
# DDMMMYYYY format | |
r'(\d{1,2}[A-Za-z]{3}\d{4})', # DDMMMYYYY format | |
# Short year formats | |
r'(\d{1,2}[\/\-]\d{1,2}[\/\-]\d{2})', # Short year date format (DD/MM/YY) | |
r'(\d{1,2}[\/\-]\d{1,2}[\/\-]\d{4})', # General date format (DD/MM/YYYY) | |
# Year-month-day formats | |
r'(\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2})', # Year-month-day format (YYYY/MM/DD) | |
# Month/Year formats | |
r'(\d{1,2}[\/\-]\d{1,2})', # MM/DD format | |
r'(\d{1,2}[\/\-]\d{2})', # MM/YY format | |
# Month name formats | |
r'(\d{1,2}\s*[A-Za-z]{3,}\s*\d{4})', # Month name with day and year | |
r'(\d{1,2}\s*[A-Za-z]{3,}\s*\d{2})', # Month name with day and short year | |
# Year with month name | |
r'(\d{4}[A-Za-z]{3,}\d{1,2})', # Year with month name | |
r'(\d{1,2}[A-Za-z]{3,}\d{4})', # Day with month name and full year | |
# Additional formats | |
r'(\d{1,2}[\/\-]\d{1,2}[\/\-]\d{2})', # MM/DD/YY format | |
r'(\d{1,2}[\/\-]\d{1,2}[\/\-]\d{4})', # MM/DD/YYYY format | |
r'(\d{1,2}[\/\-]\d{1,2})', # MM/DD format | |
r'(\d{1,2}[\/\-]\d{2})', # MM/YY format | |
# Best before phrases | |
r'Best before (\d+) months', # Best before in months | |
r'Expiration Date[:\-]?\s*(\d{1,2}[\/\-]\d{1,2}[\/\-]\d{4})', # Expiration Date | |
r'Expires[:\-]?\s*(\d{1,2}[\/\-]\d{1,2}[\/\-]\d{4})', # Expires | |
# Additional variations | |
r'(\d{1,2}\s*[A-Za-z]{3,}\s*\d{4})', # Month name with day and year | |
r'(\d{1,2}\s*[A-Za-z]{3,}\s*\d{2})', # Month name with day and short year | |
# More variations | |
r'(\d{1,2}[\/\-]\d{1,2}[\/\-]\d{4})', # MM/DD/YYYY format | |
r'(\d{1,2}[\/\-]\d{1,2})', # MM/DD format | |
r'(\d{1,2}[\/\-]\d{2})', # MM/YY format | |
# Additional expiry phrases | |
r'(\d{1,2}[\/\-]\d{1,2}[\/\-]\d{4})', # Expiry in various formats | |
r'(\d{1,2}[\/\-]\d{1,2}[\/\-]\d{2})', # Expiry in short year formats | |
r'(\d{1,2}[\/\-]\d{1,2})', # Expiry in MM/DD format | |
r'(\d{1,2}[\/\-]\d{2})', # Expiry in MM/YY format | |
# Additional phrases | |
r'(\d{1,2}\s*[A-Za-z]{3,}\s*\d{4})', # Month name with day and year | |
r'(\d{1,2}\s*[A-Za-z]{3,}\s*\d{2})', # Month name with day and short year | |
r'(\d{4}[A-Za-z]{3,}\d{1,2})', # Year with month name | |
r'(\d{1,2}[A-Za-z]{3,}\d{4})', # Day with month name and full year | |
# Additional expiry phrases | |
r'(\d{1,2}[\/\-]\d{1,2}[\/\-]\d{4})', # Expiry in various formats | |
r'(\d{1,2}[\/\-]\d{1,2}[\/\-]\d{2})', # Expiry in short year formats | |
r'(\d{1,2}[\/\-]\d{1,2})', # Expiry in MM/DD format | |
r'(\d{1,2}[\/\-]\d{2})', # Expiry in MM/YY format | |
] | |
dates = [] | |
for pattern in patterns: | |
matches = re.findall(pattern, text) | |
dates.extend(matches) | |
unique_dates = sorted(dates, key=lambda x: len(x), reverse=True) | |
return [unique_dates[0]] if unique_dates else [] # Return the most likely date | |
# Helper function: Preprocess image for fruit freshness | |
def preprocess_image(image): | |
img = cv2.resize(image, (128, 128)) | |
img_array = img_to_array(img) | |
img_array = np.expand_dims(img_array, axis=0) | |
img_array = img_array / 255.0 | |
return img_array | |
# Helper function: Calculate days to expiry | |
def calculate_days_to_expiry(expiry_dates): | |
results = [] | |
today = datetime.now() | |
for date_str in expiry_dates: | |
try: | |
if '/' in date_str or '-' in date_str: | |
if len(date_str.split('/')[-1]) == 2 or len(date_str.split('-')[-1]) == 2: | |
date_obj = datetime.strptime(date_str, '%d/%m/%y') if '/' in date_str else datetime.strptime(date_str, '%d-%m-%y') | |
else: | |
date_obj = datetime.strptime(date_str, '%d/%m/%Y') if '/' in date_str else datetime.strptime(date_str, '%d-%m-%Y') | |
else: | |
date_obj = datetime.strptime(date_str, '%d %B %Y') | |
delta = (date_obj - today).days | |
if delta >= 0: | |
results.append(f"{date_str}: {delta} days to expire") | |
else: | |
results.append(f"{date_str}: Expired") | |
except ValueError: | |
results.append(f"{date_str}: Invalid date format") | |
return results | |
# Initialize session state | |
if 'uploaded_file' not in st.session_state: | |
st.session_state['uploaded_file'] = None | |
# Streamlit App | |
st.title("Flipkart Grid") | |
# Sidebar options | |
app_mode = st.sidebar.selectbox( | |
"Choose the mode", | |
["Home", "Brand & Text Detection", "Fruit Freshness Detection", "Object Detection"], | |
on_change=lambda: st.session_state.update({'uploaded_file': None}) # Reset uploaded file on mode change | |
) | |
if app_mode == "Home": | |
st.markdown(""" | |
## Welcome to the Detection App | |
Use the sidebar to choose between: | |
- *Brand & Text Detection*: Detect brands, extract text, and identify expiry dates from uploaded images. | |
- *Fruit Freshness Detection*: Detect and classify the freshness of fruits from uploaded images. | |
- *Object Detection*: Detect objects in uploaded images. | |
""") | |
else: | |
st.header(app_mode) | |
uploaded_file = st.file_uploader("Upload an image", type=["jpg", "jpeg", "png"], key=app_mode) | |
if uploaded_file is not None: | |
st.session_state['uploaded_file'] = uploaded_file | |
if st.session_state['uploaded_file'] is not None: | |
file_bytes = np.asarray(bytearray(st.session_state['uploaded_file'].read()), dtype=np.uint8) | |
image = cv2.imdecode(file_bytes, cv2.IMREAD_COLOR) | |
if app_mode == "Brand & Text Detection": | |
# Brand detection | |
results = brand_model.predict(source=image, stream=False) | |
detected_image = results[0].plot() | |
# OCR for text extraction | |
_, img_buffer = cv2.imencode('.jpg', image) | |
ocr_result = ocr.ocr(img_buffer.tobytes()) | |
if ocr_result and isinstance(ocr_result[0], list) and len(ocr_result[0]) > 0: | |
extracted_text = ' '.join([line[1][0] for line in ocr_result[0]]) | |
expiry_dates = extract_expiry_dates(extracted_text) | |
expiry_info = calculate_days_to_expiry(expiry_dates) | |
else: | |
extracted_text = "No text detected" | |
expiry_dates = [] | |
expiry_info = [] | |
# Count objects | |
object_counts = {} | |
for box in results[0].boxes.data.cpu().numpy(): | |
label = results[0].names[int(box[5])] | |
object_counts[label] = object_counts.get(label, 0) + 1 | |
# Display results | |
st.image(cv2.cvtColor(detected_image, cv2.COLOR_BGR2RGB), caption="Detected Image") | |
st.markdown(f"*Extracted Text:* {extracted_text}") | |
st.markdown(f"*Expiry Dates:*") | |
if expiry_info: | |
for info in expiry_info: | |
st.markdown(f"- {info}") | |
else: | |
st.markdown("None") | |
st.markdown("*Object Counts:*") | |
for label, count in object_counts.items(): | |
st.markdown(f"- {label}: {count}") | |
elif app_mode == "Fruit Freshness Detection": | |
# Preprocess and predict | |
img_array = preprocess_image(image) | |
predictions = fruit_model.predict(img_array) | |
predicted_class = np.argmax(predictions, axis=1)[0] | |
label = class_names[predicted_class] | |
confidence = predictions[0][predicted_class] * 100 | |
# Display results | |
st.image(cv2.cvtColor(image, cv2.COLOR_BGR2RGB), caption="Uploaded Image") | |
st.markdown(f"*Label:* {label}") | |
st.markdown(f"*Confidence:* {confidence:.2f}%") | |
elif app_mode == "Object Detection": | |
# Object Detection | |
results = object_model.predict(source=image, stream=False) | |
detected_objects = [] | |
for result in results: | |
boxes = result.boxes.data.cpu().numpy() | |
for box in boxes: | |
class_id = int(box[5]) | |
confidence = box[4] # Assuming the confidence score is at index 4 | |
detected_objects.append((result.names[class_id], confidence)) | |
# Draw bounding box and label on the image | |
x1, y1, x2, y2 = map(int, box[:4]) | |
label = f"{result.names[class_id]} {confidence * 100:.2f}%" | |
cv2.rectangle(image, (x1, y1), (x2, y2), (255, 0, 0), 2) | |
cv2.putText(image, label, (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 2) | |
# Convert the image back to RGB for display in Streamlit | |
image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) | |
st.image(image_rgb, caption='Detected Objects', use_container_width=True) | |
# Count occurrences and average confidence of each object | |
object_data = {} | |
for obj, confidence in detected_objects: | |
if obj in object_data: | |
object_data[obj]['count'] += 1 | |
object_data[obj]['total_confidence'] += confidence | |
else: | |
object_data[obj] = {'count': 1, 'total_confidence': confidence} | |
# Prepare data for display | |
object_display_data = [ | |
{'Object': obj, 'Count': data['count'], 'Average Confidence': data['total_confidence'] / data['count']} | |
for obj, data in object_data.items() | |
] | |
# Display detected objects in a table with column names | |
st.write("Detected Objects and Counts:") | |
st.table(pd.DataFrame(object_display_data)) |