GPU-accelerated pipeline for detecting, tracking, and classifying humans in dashcam footage...
GPU-accelerated pipeline for detecting, tracking, and classifying humans in dashcam footage. Processes MP4 videos to extract human crops with optional CLIP-based head covering classification, saving all outputs to a unified directory with comprehensive indexing.
Extract visual evidence of human presence from dashcam recordings for investigative analysis. Optimized for high throughput using NVDEC decoding, batched YOLOv8 detection, ByteTrack multi-object tracking, and optional CLIP classification.
Extract humans from Park_R videos on October 6, 2025
Scan Park_R\20251006 and 20251007, keep only frames with people,
save all outputs in one folder, add one full-frame per timestamp with boxes,
use my GPU at max, filter for head-covered individuals at 80% confidence
["G:\\My Drive\\PROJECTS\\INVESTIGATION\\DASHCAM\\Park_R\\20251006"]{
"status": "ok",
"summary": {
"videos_processed": 142,
"crops_saved": 4414,
"frames_saved": 728,
"gpu_util_avg": 0.85,
"processing_time_sec": 2847,
"errors": 0
},
"artifacts": {
"index_csv": "G:\\My Drive\\PROJECTS\\APPS\\Human_Detection\\parsed\\ALL_CROPS\\INDEX.csv",
"output_dir": "G:\\My Drive\\PROJECTS\\APPS\\Human_Detection\\parsed\\ALL_CROPS",
"log_file": "G:\\My Drive\\PROJECTS\\APPS\\Human_Detection\\parsed\\ALL_CROPS\\run_20251006_143022.log"
},
"performance": {
"nvdec_active": true,
"yolo_batch": 64,
"clip_batch": 384,
"avg_fps": 48.3,
"vram_peak_gb": 9.2
},
"notes": [
"NVDEC hardware decoding active",
"Batched YOLO=64, CLIP=384",
"GPU utilization: 85%"
]
}
{
"status": "error",
"error": "CUDA out of memory",
"suggestion": "Reduce batch sizes: yolo_batch=48, clip_batch=256",
"partial_results": {
"videos_processed": 67,
"crops_saved": 2103
}
}
parsed\ALL_CROPS\
βββ INDEX.csv # Global master index
βββ INDEX.20251006_pid1234.csv # Shard (pre-merge)
βββ run_20251006_143022.log # Execution log
β
# Crop files (per person detection)
βββ 20251006__20251006142644_070785B__t15234__f365__trk017__x1014y46w266h659__c85__v1.webp
βββ 20251006__20251006143844_070787B__t8420__f202__trk003__x234y567w180h420__c92__v1.webp
β
# Full-frame files (optional, one per timestamp)
βββ 20251006__20251006142644_070785B__t15234__FRAME__v1.webp
βββ 20251006__20251006143844_070787B__t8420__FRAME__v1.webp
Crop Format:
<date>__<video_stem>__t<ts_ms>__f<frame_idx>__trk<track_id>__x<x1>y<y1>w<w>h<h>__c<covered_0to100>__v<ver>.webp
Example:
20251006__20251006142644_070785B__t15234__f365__trk017__x1014y46w266h659__c85__v1.webp
Decoded:
- Date: 2025-10-06
- Video: 20251006142644_070785B.MP4
- Timestamp: 15234 ms
- Frame: 365
- Track: 17
- BBox: x=1014, y=46, w=266, h=659
- CLIP confidence: 85% (head covering)
- Version: v1
Full-Frame Format:
<date>__<video_stem>__t<ts_ms>__FRAME__v<ver>.webp
Example:
20251006__20251006142644_070785B__t15234__FRAME__v1.webp
dataset,date,video_rel,video_stem,frame_idx,ts_ms,track_id,x1,y1,w,h,person_conf,covered_conf,file_type,crop_file,sha1,bboxes_json,annotated,pipeline_ver,yolo_batch,clip_batch,nvdec,created_utc
# Example rows:
Park_R,20251006,20251006\20251006142644_070785B.MP4,20251006142644_070785B,365,15234,17,1014,46,266,659,0.92,0.85,crop,20251006__20251006142644_070785B__t15234__f365__trk017__x1014y46w266h659__c85__v1.webp,a3f2c8b9...,,,v1,64,384,1,2025-10-06T14:30:22Z
Park_R,20251006,20251006\20251006142644_070785B.MP4,20251006142644_070785B,365,15234,,,,,,,frame,20251006__20251006142644_070785B__t15234__FRAME__v1.webp,d4e1a2c7...,"[{""x1"":1014,""y1"":46,""w"":266,""h"":659,""conf"":0.92,""track"":17}]",1,v1,64,384,1,2025-10-06T14:30:22Z
Column Definitions:
[MP4 Videos]
β
βΌ
[NVDEC Decoder (GPU)]
RGB tensor β CUDA Stream A
β
βΌ
[YOLOv8s Detection]
Batched (64 frames)
FP16, conf=0.35
β
βΌ
[ByteTrack Tracking]
IoU=0.5, max_age=10
β
ββββββββββββββββββββββββΊ [Full-Frame Saver]
β (optional, downscaled, annotated)
βΌ
[ROI Align (GPU)]
Extract crops on GPU
β
βΌ
[CLIP Classification] βββββββ (optional)
Batched (384 crops)
FP16, threshold=0.80
β
βΌ
[Deduplication Filter]
SSIM β₯ 0.92
Rate cap: 12/min/track
β
βΌ
[Async I/O Thread Pool]
WebP encode (q=85)
Shard INDEX writes
β
βΌ
[Final Merge]
INDEX.csv
Dual CUDA Streams:
Dynamic Batching:
Memory Management:
Decoder Priority:
| Metric | Target | Notes |
|---|---|---|
| GPU Utilization | 80-90% | NVDEC + dual streams + large batches |
| Throughput | 3-4 videos/min | Parking videos (2 FPS sampling) |
| VRAM Usage | 6-10 GB | YOLO=64, CLIP=384 |
| Latency | <30s per video | Including decode, detect, track, classify |
If GPU util < 70%:
yolo_batch=80, clip_batch=448nvdec_active in response)max_workers=4If CUDA OOM:
clip_batch=256yolo_batch=48save_full_frame=falseIf disk I/O bottleneck:
save_full_frame=falsefull_frame_maxw=960, WebP q=75# Basic usage
python -m src.cli.run_multi_dates \
--root "G:\My Drive\PROJECTS\INVESTIGATION\DASHCAM\Park_R" \
--out parsed\ALL_CROPS \
--dates 20251006 20251007 \
--use-nvdec --conf 0.35 --iou 0.5
# Advanced usage with CLIP filtering
python -m src.cli.run_multi_dates \
--root "G:\My Drive\PROJECTS\INVESTIGATION\DASHCAM\Park_R" \
--out parsed\ALL_CROPS \
--dates 20251006 20251007 20251008 \
--use-nvdec \
--yolo-batch 64 \
--clip-batch 384 \
--clip-threshold 0.80 \
--conf 0.35 \
--iou 0.5 \
--save-full-frame \
--draw-boxes \
--parallel 3
User: "Extract all humans from Park_R videos on October 6"
Skill invokes:
{
"mode": "extract_humans",
"roots": ["G:\\My Drive\\PROJECTS\\INVESTIGATION\\DASHCAM\\Park_R\\20251006"],
"confidence": 0.35,
"single_output_dir": "parsed\\ALL_CROPS",
"nvdec": true
}
User: "Scan Park_R for October 6-8, filter for people with head coverings at 80% confidence, save annotated frames, max GPU usage"
Skill invokes:
{
"mode": "extract_humans",
"roots": [
"G:\\My Drive\\PROJECTS\\INVESTIGATION\\DASHCAM\\Park_R\\20251006",
"G:\\My Drive\\PROJECTS\\INVESTIGATION\\DASHCAM\\Park_R\\20251007",
"G:\\My Drive\\PROJECTS\\INVESTIGATION\\DASHCAM\\Park_R\\20251008"
],
"confidence": 0.35,
"iou": 0.50,
"yolo_batch": 64,
"clip_filter": {
"enabled": true,
"threshold": 0.80,
"batch": 384
},
"nvdec": true,
"save_full_frame": true,
"draw_boxes": true,
"single_output_dir": "parsed\\ALL_CROPS",
"parallel": {
"max_workers": 3
}
}
User: "Process Park_R October 6 with minimal GPU memory"
Skill invokes:
{
"mode": "extract_humans",
"roots": ["G:\\My Drive\\PROJECTS\\INVESTIGATION\\DASHCAM\\Park_R\\20251006"],
"confidence": 0.35,
"yolo_batch": 32,
"clip_filter": {
"enabled": false
},
"nvdec": false,
"save_full_frame": false,
"single_output_dir": "parsed\\ALL_CROPS"
}
# GPU availability
assert torch.cuda.is_available(), "CUDA required"
assert torch.cuda.device_count() > 0, "No GPU found"
# Model files
assert Path("models/yolov8s.pt").exists(), "YOLOv8 model missing"
# Output directory writable
output_dir = Path("parsed/ALL_CROPS")
output_dir.mkdir(parents=True, exist_ok=True)
assert os.access(output_dir, os.W_OK), "Output dir not writable"
# Check outputs exist
assert Path("parsed/ALL_CROPS/INDEX.csv").exists()
assert len(list(Path("parsed/ALL_CROPS").glob("*.webp"))) > 0
# Validate INDEX.csv
df = pd.read_csv("parsed/ALL_CROPS/INDEX.csv")
assert df['crop_file'].notna().all()
assert df['person_conf'].between(0, 1).all()
# Sample roundtrip
sample = df.sample(1).iloc[0]
assert Path(f"parsed/ALL_CROPS/{sample['crop_file']}").exists()
# GPU utilization check
assert gpu_util_avg > 0.70, f"Low GPU util: {gpu_util_avg}"
cd "G:\My Drive\PROJECTS\APPS\Human_Detection"
pip install -r requirements.txt
1. CUDA Out of Memory
Error: CUDA out of memory. Tried to allocate 2.50 GiB
Solution: Reduce batch sizes
yolo_batch: 64 β 48 β 32
clip_batch: 384 β 256 β 128
2. NVDEC Not Available
Warning: NVDEC unavailable, falling back to CPU decode
Solution: Check NVIDIA driver version (β₯525.60)
GPU must support Video Codec SDK
Verify with: nvidia-smi --query-gpu=name --format=csv
3. Low GPU Utilization
Warning: GPU util only 45%
Solutions:
1. Increase batch sizes (if VRAM allows)
2. Enable NVDEC: nvdec=true
3. Increase parallel workers: max_workers=4
4. Check CPU bottleneck (use more DataLoader workers)
4. Slow Processing
Performance: 0.8 videos/min (expected 3-4)
Diagnostics:
1. Check disk I/O (use SSD)
2. Verify NVDEC active (5-10x faster than CPU)
3. Profile with: python -m torch.utils.bottleneck script.py
v1.0 (Current)
For issues or questions:
parsed/ALL_CROPS/run_*.log for error detailsnvidia-smipython -c "import torch; print(torch.cuda.is_available())"