Real-time CCTV surveillance system for Indian railway stations that detects persons, bags, tracks ownership, and flags abandoned luggage using YOLO26 + BoT-SORT.
┌─────────────┐ ┌──────────────┐ ┌─────────────────────┐ ┌──────────────────────┐
│ YOLO26m │───>│ BoT-SORT │───>│ OwnershipEvent │───>│ AbandonmentRisk │
│ Detection │ │ Tracking │ │ Engine │ │ Engine │
└─────────────┘ └──────────────┘ └─────────────────────┘ └──────────────────────┘
│ │ │ │
│ │ │ │
│ ┌──────┴──────┐ ┌──────┴──────┐ ┌───────┴───────┐
│ │ BagRegistry │ │ Ownership │ │ AnomalyFusion│
│ │ + ReID │ │ FSM Logic │ │ Engine │
└───────────┴─────────────┘ └─────────────┘ └───────────────┘
| Module | Description |
|---|---|
run_ownership_tracking.py |
Main pipeline — runs YOLO26m → BoT-SORT → ownership → abandonment |
detection/detect.py |
YOLO detection wrapper |
detection/bag_registry.py |
Appearance-based bag ReID with embedding similarity |
detection/bag_reid_extractor.py |
Feature extraction for bag re-identification |
detection/ownership_event_engine.py |
FSM-based person↔bag ownership tracking |
detection/ownership_manager.py |
Legacy IoU + co-movement ownership logic |
detection/abandonment_risk_engine.py |
Multi-factor abandonment risk scoring |
detection/anomaly_fusion_engine.py |
Fuses anomaly signals from multiple engines |
detection/association.py |
Hungarian algorithm person-bag association |
infer_anomaly.py |
Standalone anomaly inference script |
botsort.yaml |
BoT-SORT tracker configuration |
Tools for building a fine-tuning dataset from raw CCTV footage:
| Script | Purpose |
|---|---|
extract_frames_hd.py |
Extract full-resolution frames (1280×720) from MP4 videos |
sample_frames.py |
Fixed-interval sampling with optional perceptual dedup |
sample_motion.py |
Motion-aware sampling using histogram difference (best for static CCTV) |
validate_dataset.py |
Pre-training dataset validator (format, balance, duplicates, tiny boxes) |
# 1. Extract HD frames from video
python extract_frames_hd.py --src . --out frames_hd --interval 2
# 2. Motion-aware sampling (picks diverse frames)
python sample_motion.py --src frames_hd --out dataset --target 3000
# 3. Auto-label with COCO model
yolo predict model=yolo26m.pt source=dataset/images/train imgsz=1280 conf=0.15 save_txt=True classes="[0,24,26,28]"
# 4. Review labels in LabelImg
labelImg dataset/images/train dataset/classes.txt dataset/labels/train
# 5. Validate before training
python validate_dataset.py --data dataset
# 6. Fine-tune
yolo train model=yolo26m.pt data=dataset/dataset.yaml epochs=30 imgsz=1280 batch=4 amp=True| ID | Class | Use Case |
|---|---|---|
| 0 | person | Track owners, detect crowds |
| 1 | backpack | Most common bag type in railways |
| 2 | handbag | Smaller personal bags |
| 3 | suitcase | Large luggage on shelves |
- Model: YOLO26m (detection, not classification)
- Tracker: BoT-SORT (
botsort.yaml) - Resolution: 1280px inference
- Confidence: 0.25 (tracking) / 0.15 (auto-labeling)
- ReID: Handled by BagRegistry (BoT-SORT ReID disabled)
- GPU: NVIDIA RTX 4060 (8GB VRAM)
- Training:
batch=4,imgsz=1280,amp=True - Inference: ~50ms/frame at 1280px
| Camera | Location | Characteristics |
|---|---|---|
| ADMIN Block | Chemical Corridor, C-119 | Indoor, fluorescent lighting |
| Admin Block 2 | Near B301 | Indoor, corridor |
| CSED | Department entrance | Low contrast, haze |
| Library 2 | Baggage Area | Shelf-packed luggage, dark-on-dark |
| Main Gate | Entry/Exit | Outdoor, high traffic |
| Parking | Learning Block | Outdoor, varying light |
| Road | Hostel-H Chownk | Outdoor, 3200×1800 resolution |
pip install -r requirements.txtKey dependencies: ultralytics, opencv-python, torch, numpy, scipy, imagehash, pillow, tqdm
Private repository — all rights reserved.