diff --git a/app.py b/app.py index 287e541..18f3f7d 100644 --- a/app.py +++ b/app.py @@ -2,6 +2,7 @@ import cv2 import os import numpy as np +import pandas as pd import matplotlib.pyplot as plt import seaborn as sns from collections import defaultdict @@ -16,6 +17,9 @@ cap = cv2.VideoCapture(video_path) net = cv2.dnn.readNetFromCaffe(prototxt_path, model_path) +# Load the store data +store_data = pd.read_csv('store.csv') + def detect_people(frame): h, w = frame.shape[:2] blob = cv2.dnn.blobFromImage(cv2.resize(frame, (300, 300)), 0.007843, (300, 300), 127.5) @@ -58,45 +62,129 @@ def calculate_footfall(frame, people): return footfall def plot_heatmap(footfall): - plt.figure(figsize=(10, 4)) - sns.heatmap(footfall, cmap='hot', annot=True) + plt.figure(figsize=(8, 6)) + sns.heatmap(footfall, cmap='YlOrRd', annot=True, fmt='.0f', cbar_kws={'label': 'Foot Traffic'}) plt.title('Customer Footfall Heatmap') - plt.xlabel('Grid X') - plt.ylabel('Grid Y') + plt.xlabel('Store Width') + plt.ylabel('Store Length') return plt.gcf() def generate_report(footfall): deadspots = [] threshold = np.percentile(footfall, 25) # Define a threshold for low footfall areas + grid_size = footfall.shape + items_per_grid = len(store_data) // (grid_size[0] * grid_size[1]) + + report_data = [] + for i in range(footfall.shape[0]): for j in range(footfall.shape[1]): if footfall[i, j] <= threshold: deadspots.append((i, j)) - - report = f"Total Grids: {footfall.size}\n" - report += f"Deadspots Identified: {len(deadspots)}\n\n" - report += "Deadspots Locations (Grid Y, Grid X):\n" - for (y, x) in deadspots: - report += f"- Grid Y: {y + 1}, Grid X: {x + 1}\n" - - return report + start_index = (i * grid_size[1] + j) * items_per_grid + end_index = start_index + items_per_grid + items = store_data.iloc[start_index:end_index] + for _, item in items.iterrows(): + report_data.append({ + "Grid Location": f"Y: {i+1}, X: {j+1}", + "Product": item['Product'], + "Brand": item['Brand'], + "Weekly Sales": f"${item['Weekly Sales']}" + }) + + report_df = pd.DataFrame(report_data) + + summary = f"Total Grids: {footfall.size}\n" + summary += f"Deadspots Identified: {len(deadspots)}" + + return summary, report_df + +def get_best_selling_products_with_brands(category): + category_data = store_data[store_data['Category'] == category] + best_selling = category_data.groupby(['Product', 'Brand'])['Weekly Sales'].sum().sort_values(ascending=False).head(5) + return best_selling + +def plot_best_selling_products_with_brands(data): + plt.figure(figsize=(12, 6)) + ax = data.plot(kind='bar', color='skyblue', edgecolor='navy') + plt.title('Top 5 Best-Selling Products with Brands', fontsize=16) + plt.xlabel('Product (Brand)', fontsize=12) + plt.ylabel('Total Weekly Sales ($)', fontsize=12) + plt.xticks(rotation=45, ha='right') + + # Modify x-axis labels to show Product (Brand) + labels = [f"{product} ({brand})" for product, brand in data.index] + ax.set_xticklabels(labels) + + # Add value labels on top of each bar + for i, v in enumerate(data): + ax.text(i, v, f'${v:,.0f}', ha='center', va='bottom') + + plt.tight_layout() + return plt.gcf() def run_app(): - st.title("Store Deadspot Detection") - - # Layout with two columns - col1, col2 = st.columns(2) - - with col1: - st.subheader("Video Feed") - frame_placeholder = st.empty() - st.subheader("Customer Footfall Heatmap") - heatmap_placeholder = st.empty() - - with col2: + st.set_page_config(layout="wide", page_title="Store Analysis Dashboard") + + # Apply custom CSS for layout and styling + st.markdown(""" + + """, unsafe_allow_html=True) + + st.markdown('