██████╗ ██████╗ ██████╗ ██╗ ██╗██████╗
██╔════╝██╔══██╗██╔═══██╗██║ ██║██╔══██╗
██║ ██████╔╝██║ ██║██║ █╗ ██║██║ ██║
██║ ██╔══██╗██║ ██║██║███╗██║██║ ██║
╚██████╗██║ ██║╚██████╔╝╚███╔███╔╝██████╔╝
╚═════╝╚═╝ ╚═╝ ╚═════╝ ╚══╝╚══╝ ╚═════╝
███╗ ███╗ ██████╗ ███╗ ██╗██╗████████╗ ██████╗ ██████╗
████╗ ████║██╔═══██╗████╗ ██║██║╚══██╔══╝██╔═══██╗██╔══██╗
██╔████╔██║██║ ██║██╔██╗ ██║██║ ██║ ██║ ██║██████╔╝
██║╚██╔╝██║██║ ██║██║╚██╗██║██║ ██║ ██║ ██║██╔══██╗
██║ ╚═╝ ██║╚██████╔╝██║ ╚████║██║ ██║ ╚██████╔╝██║ ██║
╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝
Real-time crowd density estimation for campus canteens and libraries
Built from scratch using classical Computer Vision — no deep learning required
Campus Crowd Monitor is a privacy-first, real-time crowd density estimation system designed for campus environments — canteens, libraries, study halls, and corridors. It processes video from a fixed overhead or entry-facing camera and delivers live occupancy intelligence using only classical Computer Vision.
No neural network. No cloud. No faces stored. Just elegant signal processing, from pixel to insight.
| Capability | Method |
|---|---|
| 👤 Person Detection | HOG descriptor + SVM classifier |
| 🗺️ Zone Segmentation | Pixel-mapped zones with colour-coded overlays |
| 🌡️ Density Heatmap | Gaussian Kernel Density Estimation |
| 🚦 Occupancy Alerts | Per-zone threshold triggers (Free / Moderate / Crowded) |
| 🔬 CV Debug View | Live edges, corners, histograms, pyramids in dashboard |
This project was built to demonstrate techniques across a full Computer Vision curriculum.
┌─────────────────────────────────────────────────────────────────────────┐
│ UNIT 1 — Digital Image Formation │
│ ├─ Resize & colour conversion (BGR → Grayscale → LAB) │
│ ├─ Gaussian blur (5×5 kernel, σ = 1.0) │
│ └─ CLAHE histogram equalisation (contrast enhancement) │
├─────────────────────────────────────────────────────────────────────────┤
│ UNIT 3 — Feature Extraction │
│ ├─ Edge detection : Canny · LOG · DOG │
│ ├─ Corner detection : Harris │
│ ├─ Line detection : Hough transform │
│ ├─ Descriptors : HOG · SIFT keypoints │
│ └─ Scale-space : Gaussian image pyramids │
├─────────────────────────────────────────────────────────────────────────┤
│ UNIT 3 — Image Segmentation │
│ ├─ Region growing │
│ ├─ GrabCut (graph-cut) │
│ ├─ Watershed algorithm │
│ └─ Mean-shift segmentation │
├─────────────────────────────────────────────────────────────────────────┤
│ UNIT 4 — Pattern Analysis │
│ ├─ HOG + SVM person classifier │
│ ├─ Non-Maximum Suppression (NMS) │
│ ├─ Background subtraction (MOG2) │
│ └─ Temporal density averaging │
└─────────────────────────────────────────────────────────────────────────┘
crowd-detection/
│
├── 📁 data/
│ ├── sample_videos/ ← Place your .mp4 / .avi footage here
│ └── annotations/
│ └── counts.csv ← Manual frame counts for evaluation
│
├── 📁 src/
│ ├── preprocessing.py ← Unit 1 · Gaussian blur, CLAHE, MOG2, pyramids
│ ├── feature_extraction.py ← Unit 3 · Canny, Harris, Hough, HOG, SIFT
│ ├── detector.py ← Unit 3/4 · HOG+SVM detection, NMS, zone counting
│ ├── segmentation.py ← Unit 3 · Region growing, GrabCut, Watershed, zones
│ ├── density_map.py ← Unit 1/3 · Gaussian KDE heatmap, alert thresholds
│ └── dashboard.py ← Streamlit interactive web dashboard
│
├── 📁 models/
│ └── hog_svm.pkl ← Auto-loaded from OpenCV; swap for custom model
│
├── 📁 notebooks/
│ └── exploration.ipynb ← Step-by-step visualisation of every CV stage
│
├── 📁 report/
│ └── project_report.pdf
│
├── requirements.txt
└── README.md
git clone https://github.com/YOUR_USERNAME/campus-crowd-monitor.git
cd campus-crowd-monitor
pip install -r requirements.txtDrop a .mp4 or .avi file into data/sample_videos/.
Record 5–10 minutes of canteen or library footage from a phone mounted overhead.
(Always get permission from your institution before recording.)
No footage? The dashboard also works directly with your webcam — see step 4.
jupyter notebook notebooks/exploration.ipynbThe notebook walks through every preprocessing and feature-extraction stage with inline visualisations. Run it first — it generates all the figures you'll need for your report and builds intuition for the pipeline before you touch the live system.
streamlit run src/dashboard.pyOpen the URL printed in your terminal — usually http://localhost:8501.
In the dashboard you can:
- Upload a video or click "Start webcam" for live inference
- Toggle heatmap, bounding boxes, zone overlay, and edge debug view from the sidebar
- Adjust occupancy thresholds and detection sensitivity with live sliders
Every video frame travels through this processing chain:
Camera frame
│
▼ ─────────────────────────────────────────────────────
│ STAGE 1 · PREPROCESSING
│
├─ resize_frame() → 640 × 480, BGR → Grayscale
├─ gaussian_blur() → 5×5 kernel, σ = 1.0 (noise removal)
└─ apply_clahe_color() → CLAHE on LAB L-channel (contrast boost)
│
▼ ─────────────────────────────────────────────────────
│ STAGE 2 · DETECTION & SEGMENTATION
│
├─ BackgroundSubtractor.apply() → Foreground mask (MOG2)
└─ HOGPersonDetector.detect() → Bounding boxes + NMS
│
▼ ─────────────────────────────────────────────────────
│ STAGE 3 · DENSITY & OVERLAY
│
├─ make_density_map() → Gaussian KDE heatmap
└─ draw_zone_overlay() → Per-zone occupancy labels & colours
│
▼
Dashboard frame ✓
Zones are defined in src/segmentation.py as pixel-coordinate rectangles mapped to your camera's field of view:
# src/segmentation.py
DEFAULT_ZONES = {
"Zone A (tables 1–4)": ( 0, 0, 320, 240),
"Zone B (tables 5–8)": (320, 0, 640, 240),
"Zone C (corridor)": ( 0, 240, 640, 480),
}Format:
(x_min, y_min, x_max, y_max)in pixels, relative to the 640×480 frame.
1. Screenshot your camera's empty view
2. Open in any image editor (Paint, Preview, GIMP …)
3. Note pixel coordinates at zone corners
4. Update DEFAULT_ZONES with those coordinates
| Status | Colour | Default condition | Dashboard control |
|---|---|---|---|
| 🟢 Free | Green | < 5 people | Sidebar slider |
| 🟡 Moderate | Amber | 5 – 14 people | Sidebar slider |
| 🔴 Crowded | Red | ≥ 15 people | Sidebar slider |
Thresholds can also be hard-coded directly in src/density_map.py if you want them locked for deployment.
To measure detection accuracy against ground truth:
Step 1 → Pick 20–30 representative frames from your video
Step 2 → Manually count the people in each frame
Step 3 → Write results to data/annotations/counts.csv
Format: frame_id, manual_count
Step 4 → Run the final cell in exploration.ipynb
→ computes Mean Absolute Error (MAE) automatically
Metric: Mean Absolute Error between predicted and manual counts.
A MAE of 1–3 people per zone is typical for controlled indoor environments.
This system is designed to be privacy-safe by construction:
- Detection uses head/shoulder silhouettes only (HOG blobs) — no facial geometry is analysed
- No images or crops are stored to disk at any point
- All computation is local — no data ever leaves the device
- Only aggregate zone counts and density values are logged
| Library | Version | Role |
|---|---|---|
| OpenCV | ≥ 4.8 | All CV algorithms — detection, blur, edges, segmentation |
| NumPy | ≥ 1.24 | Array maths, kernel operations |
| Streamlit | ≥ 1.30 | Interactive web dashboard |
| Matplotlib | ≥ 3.8 | Notebook visualisations |
| PyTorch | ≥ 2.1 | Optional deep learning backbone (plug-in replacement for HOG+SVM) |
pip install -r requirements.txt# requirements.txt
opencv-contrib-python>=4.8
numpy>=1.24
streamlit>=1.30
matplotlib>=3.8
torch>=2.1 # optional — comment out if not needed
scikit-learn>=1.3 # for SVM training utilities
jupyter>=1.0
🔁 Swap in a deep learning detector
Replace HOGPersonDetector in detector.py with a YOLOv8 or Faster R-CNN call. The rest of the pipeline (zone counting, heatmap, dashboard) is detector-agnostic.
# detector.py — drop-in replacement sketch
from ultralytics import YOLO
model = YOLO("yolov8n.pt")
def detect(frame):
results = model(frame)
boxes = results[0].boxes.xyxy.cpu().numpy()
return boxes📊 Export data for analytics
Add a CSV writer to density_map.py to log timestamped zone counts. Pipe this into a Grafana dashboard or a simple pandas analysis for usage trend reports.
📡 Deploy on a Raspberry Pi
Disable PyTorch, reduce frame resolution to 320×240, and lower the detection window stride. The HOG+SVM pipeline runs comfortably at 10–15 FPS on a Pi 4.
MIT License — free to use, modify, and adapt for academic and personal projects.
Please retain attribution when submitting as coursework.
Built with classical Computer Vision · Privacy-first · No cloud required