Metadata-Version: 2.4
Name: crowdwards
Version: 0.1.0
Summary: CrowdWARDS — link per-frame head detections into crowd trajectories (early release of a crowd-risk toolkit).
Author-email: Martin-Isbjoern Trappe <martin.trappe@quantumlah.org>
License-Expression: LicenseRef-Proprietary
Project-URL: Homepage, https://pypi.org/project/crowdwards/
Keywords: crowd,pedestrian,tracking,trajectories,head detection
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: Topic :: Scientific/Engineering
Classifier: Programming Language :: Python :: 3
Classifier: Operating System :: OS Independent
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: numpy>=1.21
Requires-Dist: scipy>=1.7

# CrowdWARDS

Early release of the CrowdWARDS crowd-risk toolkit. This version contains one
stand-alone piece: a **head-detection linker**. It turns per-frame head positions
(from any head or person detector, with no identities) into per-person trajectories.
The full toolkit is in development and will be published here later.

## Install

Install into a virtual environment (on Ubuntu/Debian a system-wide `pip install`
is blocked):

```bash
python3 -m venv ~/cw && source ~/cw/bin/activate
pip install crowdwards
```

Needs Python 3.9+, numpy and scipy (installed automatically).

## Try it without data

```bash
crowdwards demo
```

This simulates people walking, hides who is who, links the detections back into
tracks and reports how many links were correct.

## Link your own detections

Input: a CSV (or `.csv.gz`) with a header row and one line per detected head:

```
frame,time_s,x_px,y_px
0,0.000,1140.0,934.7
0,0.000,2436.1,899.4
2,0.067,1141.2,936.0
...
```

Recognised column names: frame (`frame`, `frame_id`, `frame_idx`, `f`), time
(`t`, `time`, `time_s`, `timestamp` — optional, otherwise frame × `--dt`), x
(`x`, `x_px`, `x_m`, `u`), y (`y`, `y_px`, `y_m`, `v`), and optionally a confidence
(`score`, `conf`, `confidence`). Other columns are ignored.

```bash
crowdwards link detections.csv -o tracks.dat          # CrowdWARDS tracks format
crowdwards link detections.csv -o tracks.csv          # long CSV: track_id,t,x,y
crowdwards link detections.csv --t-start 0 --t-end 12 # only part of the recording
crowdwards link --help                                # all options
```

Main options:

- `--max-dist` — the furthest a person can move between two consecutive frames,
  in the same units as the positions (pixels or metres). Default: half the typical
  spacing between neighbouring heads, estimated from the data.
- `--max-gap` — how many missed frames a track may bridge (default 2).
- `--min-length` — drop tracks seen in fewer frames (default 3).
- `--min-score` — drop detections below this confidence (only if the file has a
  `score`, `conf` or `confidence` column).

**Tip:** many head detectors deliberately over-detect. If your tracks come out very
short, drop the uncertain detections and allow longer gaps, e.g.
`--min-score 0.3 --max-gap 5`.

Output `tracks.dat` has one line per person: `t1 x1 y1 t2 x2 y2 …`.

## Use from Python

```python
import crowdwards

frames = crowdwards.read_detections("detections.csv")  # [(t, xy array), ...]
tracks = crowdwards.link(frames, max_gap=2)            # list of Track(t, xy)
crowdwards.write_tracks_dat("tracks.dat", tracks)

for tr in tracks[:3]:
    print(len(tr), tr.duration, tr.xy[0])
```

You can also build `frames` yourself: a list of `(time, positions)` pairs, where
`positions` is an `(N, 2)` array for that frame.

## How it works

Each open track predicts where its person is now (last position plus a smoothed
velocity). Detections close to a prediction are candidates, and a one-to-one
assignment (the Hungarian algorithm) picks the best matches so that no two tracks
claim the same head. Unmatched detections start new tracks; a track that goes
unseen for more than `--max-gap` frames is closed; very short tracks are dropped.

It is a simple, general linker: in very dense or heavily occluded crowds, expect
tracks to break into shorter pieces.
