Brand-O-Meter is a web application that analyzes retail shelf images to calculate the percentage of shelf space (counter share) occupied by each FMCG brand. It uses a TensorFlow object detection model trained to recognize 6 biscuit brands (Oreo, Hide & Seek, Bourbon, Dark Fantasy, Jim Jam, Chocopie), detects their bounding boxes in uploaded shelf photos, and computes each brand's area coverage and shelf position (left/middle/right, top/middle/bottom).
Built for a hackathon, it solves a real FMCG industry problem: brands pay retail chains a premium for shelf visibility, but have no automated way to verify if stores are complying with contract terms.
- Object Detection on Shelf Images — TensorFlow SavedModel (26MB) detects bounding boxes for 6 biscuit brands with confidence thresholds, using the TF Object Detection API
- Counter Share Calculation — Computes each brand's percentage of total shelf area from detected bounding boxes:
(sum of bbox areas / total image area) × 100 - Shelf Position Mapping — Divides the image into a 3×3 grid and maps each brand's average centroid to a position label (e.g., "Left-Top", "Middle-Bottom")
- Bulk Image Upload — Upload multiple shelf images via a drag-and-drop Dropzone.js interface for batch analysis
- Results Dashboard — Displays each uploaded image as a card with per-brand area percentage and position data
- User Authentication — Django auth with signup (including product/brand name), login, and session management via a sliding sign-in/sign-up form
- TensorFlow Object Detection Pipeline — Uses
tf.saved_model.load()to load a pre-trained model, runs inference per image viamodel.signatures['serving_default'], extracts detection boxes/classes/scores, and filters by a 0.5 confidence threshold - Area Computation from Bounding Boxes — Denormalizes YOLO-style normalized coordinates to pixel values using image dimensions, then sums
|width × height|per brand class to get total area occupied - Position Grid Algorithm — Computes the centroid of all bounding boxes per brand, divides the image into thirds horizontally and vertically, and maps the centroid to one of 9 grid positions using directional labels
- Label Map —
labelmap.pbtxtmaps 6 class IDs to brand names, consumed by TF'slabel_map_utilfor human-readable output - Azure Production Config —
azure.pyoverrides settings for PostgreSQL (Azure Database), Azure Blob Storage for static files, and SSL enforcement
| Layer | Technology |
|---|---|
| Backend | Django 2.2 |
| ML Model | TensorFlow Object Detection API (SavedModel format, 26MB) |
| Database | SQLite (dev), PostgreSQL (Azure prod) |
| Frontend | Bootstrap, Dropzone.js (drag-and-drop upload), animated CSS cards |
| Auth | Django built-in auth + custom Profile model |
| Static Storage | Azure Blob Storage (production) |
| Visualization | TF visualization_utils for bounding box overlay on images |
┌──────────────────────────────────────────────────────┐
│ Django Web Application │
│ │
│ /login/ → Sign in / Sign up (sliding form) │
│ /bulk → Dropzone.js image upload │
│ /redirection → Run inference + show results │
└──────────────────┬───────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────┐
│ TensorFlow Object Detection │
│ │
│ 1. Load saved_model.pb (26MB) │
│ 2. For each uploaded image: │
│ a. Convert to tensor │
│ b. Run inference → boxes, classes, scores │
│ c. Filter by confidence > 0.5 │
│ d. Map class IDs → brand names (labelmap.pbtxt) │
│ e. Draw bounding boxes on image │
└──────────────────┬───────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────┐
│ Counter Share Analysis │
│ │
│ • Area %: sum(bbox areas) / image area × 100 │
│ • Position: centroid → 3×3 grid → label │
│ │
│ Output per image: │
│ { │
│ "oreo": { area: 15.1%, position: "Middle-Top" }, │
│ "bourbon": { area: 5.8%, position: "Middle-Bottom"}│
│ } │
└──────────────────────────────────────────────────────┘
Detected Brands (6 classes):
| ID | Brand |
|---|---|
| 1 | Oreo |
| 2 | Hide & Seek |
| 3 | Bourbon |
| 4 | Dark Fantasy |
| 5 | Jim Jam |
| 6 | Chocopie |
- Python 3.6+
- TensorFlow 1.x or 2.x with Object Detection API
cd Website
# Create virtual environment
python -m venv venv
source venv/bin/activate
# Install dependencies
pip install -r requirements.txt
# Run migrations
python manage.py migrate
# Start the server
python manage.py runserverThe app will be available at http://localhost:8000.
- Navigate to
/login/and create an account (enter your brand name during signup) - Go to
/bulkto upload shelf images via drag-and-drop - Click analyze — the system runs object detection on each image
- View results: each image displayed as a card showing per-brand area percentage and shelf position
- Applied Computer Vision — Using TensorFlow Object Detection API for a real business use case (retail shelf analysis), not just academic classification
- End-to-End ML Integration — Loading a SavedModel into a Django web app, running inference on user-uploaded images, and presenting structured results
- Domain-Specific Feature Engineering — Converting raw bounding box coordinates into business metrics (area percentage, shelf position grid)
- Full-Stack Development — Django backend with auth, file uploads, template rendering, and Azure deployment configuration
- Hardcoded Windows Paths — Image paths in
views.pyuse absolute Windows paths (C:\\Users\\windows\\...); these should useos.pathor Django'sMEDIA_ROOTfor portability - Inference Code Commented Out — The TensorFlow inference pipeline in
views.pyis commented out, with hardcoded mock results returned instead. The model and label map are present but the inference integration needs to be reconnected - 6 Brand Classes Only — The model is trained on 6 specific biscuit brands; extending to more brands/categories would require retraining
- No Real-Time Video Support — Only static image analysis; adding video frame extraction would enable live shelf monitoring
- No Confidence Score Display — Detection confidence scores are used for filtering but not shown to the user in the results view
- No Comparative Analytics — Results are per-image; adding time-series tracking would let brands monitor shelf share trends across store visits