Project Info
Inspiration
Coming from India, I've seen far too many times that crowds are not managed well, and that overcrowding is almost always handled poorly. The Kumbh Mela, one of the largest human gatherings on Earth, sees people lose their lives to crowd crushes nearly every time it is held. I've lost some close relatives to such incidents. And it isn't just India: Itaewon in Seoul, the Love Parade in Germany, and Astroworld in the US, a lot of concerts, political gatherings, strikes/rallies, etc are all recent reminders that crowd crushes keep happening, in every place, at events that were planned months in advance. A "crowd crush" is a physics problem before it is a human one. A lot of scientists have provided evidence that an average human crowd behaves similar to how a fluid flows. I felt like this concept could be used to model human crowd and use that information to do better crowd management in events regardless of their scale. TL;DR CrowdPhysics turns any existing camera into a crowd-crush early-warning system preventing potential accidents in crowding. It also lets you simulate a venue's crowd flow, through the same perception pipeline, before the event ever happens and plan crowd management efficiently.
What it does
CrowdPhysics is a two-mode platform for crowd safety. Monitor mode turns any existing camera feed — a CCTV stream, a phone, or a public webcam — into a crush-risk early-warning system. It reads the crowd purely as fluid dynamics: it extracts the optical flow, feeds it to a learned world model, and forecasts what the crowd will do next. When the model becomes "surprised" — when the real crowd starts behaving in a way it has never seen during calm footage — the system raises a warning before the crush forms. Claude then explains, in plain language, what is happening, decides the crush-risk percentage, and recommends what to do. Simulate mode is the pre-event planning tool. Upload a photo or video of a venue, and agents reconstruct the space in 3D, simulate a crowd flowing through it, and surface the danger zones — peak-pressure sectors, bottlenecks, Fruin level-of-service, and time-to-crush — before a single person arrives. It then suggests how to arrange entrances, flow, and staff to make the layout safe. Architecture Two modes share one perception core — optical flow → a learned world model → an anomaly signal — and one explainer (Claude). Monitor pipeline — frame to warning. Every consecutive frame pair becomes an optical-flow field, compressed to a 256-dim feature vector, encoded by the world model into a 64-dim latent z, and rolled forward. The gap between what the model predicted and what actually happened is the danger signal, which the RL agent and Claude turn into a calibrated risk and a recommended intervention. At the end of that pipeline sits a multi-agent decision framework: no single model decides alone. The anomaly status, the world-model's imagined futures, the statistical trend, the RL agent's recommended intervention, and a counterfactual "prove the fix works" are all fused — and Claude reasons over the whole picture to produce one calibrated verdict, a plain-language briefing, and a recommended action. Plan pipeline — photo to safe layout. Upload a photo or video; Claude vision reconstructs the venue in 3D, the crowd simulator fills it, and we surface danger zones, Fruin level-of-service, and an arrangement plan before anyone arrives. The Sim → RAFT bridge. The simulator is a pressure-grid fluid model with no individual people — so there is nothing for optical flow to track. We close that gap by seeding massless particles at the entry ports, advecting them through the simulated velocity field, and rendering them as a video. Running that synthetic crowd through the same RAFT extractor used on live cameras yields the optical flow an operator should expect at each door — so a layout is validated against the perception system itself, before the event. How I built it Challenges I ran into Anomaly detection with no disaster data. Real crowd-crush footage is scarce and ethically fraught, so we could not train a supervised classifier. We had to invert the problem: train only on normal physics and treat the world model's prediction error as the danger signal. Putting the stochasticity in the right place. Our first world model was a "half-VAE" — the encoder was deterministic but the KL term acted on the transition, so the latent space was never shaped toward a prior and our ||z|| danger score was meaningless. Rebuilding it as a proper posterior-vs-prior RSSM was the fix that made the anomaly signal principled. Proving the model actually learned physics. It's easy to claim a self-supervised model "understands" a crowd. We had to prove it by linearly probing the latent space. Connecting simulation to perception. The simulator outputs fields, not people, so optical flow had nothing to track. Building the particle-advection renderer — auto-scaling velocity to visible pixel motion and measuring magnitude-weighted flow at each door — was what finally let the same RAFT pipeline validate a layout before the event. Real-time end to end. Chaining RAFT → world model → anomaly scoring → RL → Claude while keeping the feed responsive took a lot of profiling and a lazy-loaded, calibration-aware inference layer, plus running Claude's risk assessment on a non-blocking background thread. Accomplishments that I'm proud of The world model genuinely discovered crowd physics on its own. By linearly probing the unlabeled latent space, we recovered interpretable physical concepts with high fidelity: Boundary stress — compression at walls and barriers, the literal mechanism of a crush — was recovered at R² = 0.99, even though we never told the model what a wall is. And the latent dimensions we couldn't explain still separated pre-anomaly frames from calm ones by 0.91σ, meaning the model encodes early-warning signal we don't yet have names for. This is a standard mechanistic interpretability based proof that the world model learned physics principles intrinsically. I'm also proud that: The whole thing is genuinely two products in one — pre-event simulation and live monitoring — and it runs on cameras that already exist, requiring no new hardware. Other experiments World model v1 → v2. We started with a deterministic CNN-encoder + LSTM transition and migrated to a stochastic RSSM after the latent probe showed the danger score wasn't grounded. Self-supervised RAFT fine-tuning. We fine-tuned RAFT on unlabeled crowd video to sharpen flow on dense, low-contrast scenes (raft_crowd.pt). "Prove the fix works" counterfactuals. Using the RL effect model, we roll the crowd forward two ways — do nothing vs. apply the recommended intervention — so the projected impact of acting now is visible as the gap between two risk curves. Minutes-ahead forecasting. Beyond the immediate surprise signal, we extrapolate the risk trend to project crush risk minutes into the future.
What we learned
Self-supervised "surprise" is a remarkably powerful safety signal — you can detect danger you never trained on, as long as you've learned what "normal" looks like. Where you put stochasticity in a latent model matters enormously; the RSSM formulation wasn't just cleaner, it was the difference between a meaningful danger score and noise. Linear probing is an underrated way to verify that a model learned something real, and it turned a black box into our most compelling demo. Model-based RL (Dyna / Dreamer-style) lets you train a useful intervention policy entirely in imagination — no real catastrophes required. Validating a simulator through the same perception model you deploy is a powerful sanity check — it catches layouts that look fine on a heatmap but read as a bottleneck to the optical-flow pipeline.
What's next
for CrowdPhysics Multi-camera fusion — stitch several feeds into one venue-wide pressure field for full situational coverage. Calibrated, deployable alerts — push warnings to staff radios, SMS, and agent networks with venue-specific instructions. Richer venue reconstruction — go from a single photo to a true 3D layout for higher-fidelity Plan-mode simulations. Edge deployment — run the pipeline on-site for privacy and zero-latency monitoring at large events. Naming the unknown — investigate the unexplained latent dimensions that already predict danger, and turn them into new, named safety metrics.
CrowdPhysics
Live crowd-crush early warning + pre-event crowd-flow simulation — on cameras that already exist.
A crush is a physics problem before it is a human one. By the time a camera operator sees people falling, it is already too late. CrowdPhysics reads a crowd as pure fluid dynamics, learns what "normal" looks like, and warns before the crush forms — and lets you simulate a venue's crowd flow before the event, through the same perception pipeline.
What it does
CrowdPhysics is one platform with two modes:
-
Monitor mode (live). Turns any CCTV stream, phone, or public webcam into a crush-risk early-warning system. It extracts optical flow, feeds it to a self-supervised world model, and forecasts what the crowd will do next. When the model becomes surprised — the crowd behaves in a way it never saw during calm footage — it raises a warning. Claude then explains what's happening, decides a calibrated crush-risk %, and recommends an action.
-
Simulate mode (pre-event). Upload a photo or video of a venue; agents reconstruct it in 3D, fill it with a simulated crowd, and surface danger zones, Fruin level-of-service, and a safe arrangement plan. The Sim → RAFT bridge then renders the simulation as a synthetic-crowd video and runs it through the same optical-flow extractor used live — previewing the inflow/outflow each entrance and exit should show on the day.
The signature of the product is the visualization: instead of a red dot on a surveillance feed, the crowd is rendered as a CFD-style pressure field. The people disappear, and only the physics remains.
It learned crowd physics on its own — a linear probe of the unlabeled latent space recovers crowd velocity (R² 0.83), turbulence (0.78), backward pressure (0.84), and boundary stress — the literal mechanism of a crush — at R² 0.94, without ever being told what a wall is.
Architecture
Two modes share one perception core — optical flow → a learned world model → an anomaly signal — and one explainer (Claude).
Monitor pipeline — frame to warning
Every frame pair becomes an optical-flow field → a 256-d feature vector → a 64-d latent z → an autoregressive rollout. The gap between predicted and actual is the danger signal.

At the end of the pipeline, a multi-agent decision framework fuses every signal — no single model decides alone.

Simulate pipeline — photo to safe layout

Sim → RAFT bridge — validate a layout through the same eyes that will watch it

Tools used
| Layer | Stack |
|---|---|
| Perception | PyTorch · RAFT (torchvision, optionally fine-tuned raft_crowd.pt) with a Farneback fallback |
| World model | Latent dynamics — CNN/MLP encoder + stochastic LSTM transition, 256 → 64-d latent (RSSM v2 explored, v1 shipped) |
| Decision (RL) | Dyna-style model-based RL with Conservative Q-Learning (CQL), trained in imagination |
| Agent / LLM | Claude (Sonnet) via Anthropic — vision reconstruction, behavior planning, safety reports, agent-decided live risk |
| Live capture | Browserbase (cloud headless browser) · yt-dlp · OpenCV |
| Simulation | Pressure-grid CFD crowd model — time-varying arrivals, density-dependent speed, Fruin LOS |
| Observability | Arize AX (OpenTelemetry tracing + LLM-as-judge evals) |
| Alerts | Fetch.ai heartbeat agent · Slack / Discord / webhook / Twilio SMS |
| App | FastAPI (backend) · Next.js + React Three Fiber / Three.js · Recharts · Tailwind |
Dataset
The world model and the RAFT fine-tuning are trained on a small set of publicly available YouTube clips of crowds walking and moving — stadium crowds, pedestrian flows, and crowd-dynamics demonstrations. The clips live in data/videos/ and are loaded directly by the training scripts (scripts/train.py, scripts/finetune_raft.py).
Two things to note:
- No labels, no disaster footage. Training is entirely self-supervised on normal crowd motion — the model only ever learns what calm looks like, and danger is inferred as deviation ("surprise") from that. Real crush footage is scarce and ethically fraught, so none is used.
- Intentionally small (hackathon scope). A handful of clips is enough to demonstrate the pipeline and recover physics via the latent probe, but it's also why held-out generalization is modest — broader, more varied footage is the obvious next step.
To use your own data, drop .mp4 / .avi / .mov files into data/videos/ and re-run the training scripts below.
Model results
All numbers are reproducible from the scripts in scripts/ and the JSON artifacts in results/.
Latent probe — did the world model learn physics?
We freeze the shipped world model (v1), encode crowd video into the 64-d latent, and fit a probe from the latent to each measured physics quantity. High R² means the concept is linearly recoverable from the latent the model built on its own.
| Concept | R² (linear, in-sample) | R² (held-out, group k-fold) |
|---|---|---|
| Crowd velocity | 0.83 | 0.54 |
| Turbulence | 0.78 | 0.33 |
| Backward pressure | 0.84 | 0.56 |
| Boundary stress (the literal mechanism of a crush) | 0.94 | 0.26 |
Plus the unexplained latent dimensions still separate pre-anomaly frames from calm ones by 1.56σ — early-warning signal the model encodes that we don't yet have names for. The in-sample numbers show the concept is represented; the held-out numbers are honest about how much generalizes from this small dataset. (Source: results/probe_results.json, scripts/probe_latent.py.)
Model selection — v1 vs RSSM v2
We built a Dreamer/RSSM-style v2 and compared it to v1 on a combined probe + surprise-separation score. v1 won and shipped.
| Model | Mean linear-probe R² | Surprise separation | Combined score |
|---|---|---|---|
| v1 (shipped) | 0.85 | 1.56σ | 1.63 |
| RSSM v2 | 0.87 | 1.25σ | 1.49 |
(Source: results/probe_compare_results.json, scripts/probe_compare.py.)
Training curves (selected models)
World model (v1, shipped) — self-supervised loss (reconstruction + KL + transition) converging to ≈ 0.045 under cosine LR decay:

Intervention RL (Dyna + Conservative Q-Learning) — trained entirely in the world model's imagination. Over 15k imagined episodes the 50-episode average reward climbs to ≈ 62 (best ≈ 68) as the TD/CQL loss decays and ε anneals:

(Curves written live by metrics_logger.py; sources in logs/.)
Getting started
Prerequisites
- Python 3.10+ and Node.js 18+
- An Anthropic API key (required for the Claude-powered features)
1. Backend (FastAPI · port 8000)
# from the repo root
python3 -m venv .venv && source .venv/bin/activate
pip install -r backend/requirements.txt
# add your keys (see "Environment" below)
echo 'ANTHROPIC_API_KEY=sk-ant-...' > .env
# run the API (loads the world model + RL policy at startup)
python3 backend/main.py
The API serves on http://localhost:8000.
2. Frontend (Next.js · port 3000)
cd frontend
npm install
npm run dev
Open http://localhost:3000. The UI talks to the backend at http://localhost:8000 by default (override with NEXT_PUBLIC_API_URL).
Environment
Create a .env in the repo root (auto-loaded by the backend). Only ANTHROPIC_API_KEY is required:
ANTHROPIC_API_KEY=sk-ant-... # required — Claude reasoning & vision
# optional — live webcam/stream capture via Browserbase
BROWSERBASE_API_KEY=...
BROWSERBASE_PROJECT_ID=...
# optional — tracing + evals
ARIZE_API_KEY=...
ARIZE_SPACE_ID=...
# optional — outbound alerts
SLACK_WEBHOOK_URL=...
# DISCORD_WEBHOOK_URL / ALERT_WEBHOOK_URL / TWILIO_* + ALERT_SMS_TO also supported
Tip: for a fast local demo with no GPU, force the classical flow backend:
CROWDPHYSICS_FLOW_BACKEND=farneback python3 backend/main.py
Using it
- Monitor — open the Monitor tab and paste a live stream / webcam / YouTube URL. Analysis auto-starts and loops; watch the live feed, the synchronized pressure field, the crush-risk forecast, and the agent's reasoning. Danger regions are marked directly on the frame.
- Plan — open the Plan tab, upload a photo or video of a space, and answer a few questions (purpose, crowd size, density). Agents reconstruct the venue in 3D, simulate the crowd, rank layout scenarios, and run the Expected Entry/Exit Flow check (Sim → RAFT). Refine the scene in plain language ("add an exit on the north wall").
Repository layout
backend/ FastAPI app (main.py), API endpoints, streaming
frontend/ Next.js + Three.js UI
flow_extractor.py RAFT / Farneback optical flow + pressure-field render
world_model.py World model v1 — CNN/MLP encoder + LSTM transition
anomaly_detector.py surprise σ scoring + status
dyna_trainer.py model-based RL (Dyna + CQL)
simulation_engine.py pressure-grid crowd simulator + Sim→RAFT frames
claude_interpreter.py Claude agents (vision, planning, risk, reports)
agents/ Browserbase / YouTube capture, Fetch.ai heartbeat
scripts/ training, fine-tuning, and latent-probe scripts
models/ trained checkpoints loaded at startup
devpost/ architecture diagrams + demo deck
Training (optional)
The repo ships with trained checkpoints in models/. To retrain:
python3 scripts/train.py # world model + RL policy
python3 scripts/finetune_raft.py # self-supervised RAFT on crowd video
python3 scripts/probe_latent.py # verify the latent learned physics (R²)
Diagrams & deck
Architecture diagrams are reproducible matplotlib sources in devpost/ (architecture.py, decision_framework.py, bridge_architecture.py). The demo deck lives at devpost/CrowdPhysics_Demo.pptx (regenerate with python3 devpost/make_deck.py).
Analysis
View
Metric
- 51
Figures cover GitHub contributors during the hackathon window. A co-authored commit counts in full for each author, so per-member totals add up to more than the whole-team figures.
Technology
- AnthropicIn code
- CSSIn code
- FastAPIIn code
- Next.jsIn code
- PythonIn code
- PyTorchIn code
- ReactIn code
- Tailwind CSSIn code
- TypeScriptIn code
9 of 9 appear in the indexed code.
AI coding agents
- CursorConfig
Detected from committed agent config files and commit authorship. Absence of a signal is not proof an agent was unused.
Codebase size
Source size
1.0 MB
Source files
96
Counts recognized source files only; vendored directories, binaries and lockfiles are excluded, so this is smaller than the repository on disk.
Repository
dhyutin/CrowdPhysics
128 files · 5.8 MB · @ 9d168b4
Structure
Interface
16 files · 13%Screens, components and styles rendered to the user.
Application logic
26 files · 20%Domain rules, services and shared utilities.
+1 more
Supporting
Layers are inferred from where files sit in the tree, not from reading the code. A project that names its directories unconventionally will read oddly here — open the file browser to check anything the diagram implies.
Languages
- Python43%
- Markdown35%
- TypeScript22%
- CSS1%
Share of indexed source by file size. Binary and vendored files are excluded.
Dependencies
frontend/package.json
npm · 18- @react-three/drei
- @react-three/fiber
- @types/three
- next
- react
- react-dom
- react-markdown
- recharts
- three
- +9 more
backend/requirements.txt
pypi · 14- anthropic
- arize-otel
- fastapi
- numpy
- opencv-python-headless
- openinference-instrumentation-anthropic
- Pillow
- playwright
- python-multipart
- requests
- torch
- torchvision
- uvicorn[standard]
- yt-dlp
agents/requirements.txt
pypi · 6- numpy
- opencv-python-headless
- playwright
- requests
- uagents
- yt-dlp
Declared in the repository’s manifests at the indexed commit. A declared package is not proof it is used, and runtime dependencies are listed first.
This project’s features have not been analysed yet.
Export this project's context (description, README, evidence, key source files) to chat with an AI agent elsewhere.