Physical-AI data processing on Daft, starting with hand tracking.
Project description
daft-physical-ai
Physical-AI data processing on Daft, starting with hand tracking. The methods run as Daft UDFs, so they slot into any Daft pipeline and execute lazily, batched, and distributed.
API
The package operates on a Daft image column and returns a hand-pose column. A
LeRobot dataset is a natural source: Daft's native reader
daft.datasets.lerobot (added in Daft #7090)
decodes each camera into an image column with load_video_frames.
import daft
from daft.datasets import lerobot
from daft_physical_ai.hands import track_hands
# one row per frame; the camera key is decoded into an image column.
# egodex-test is a tiny EgoDex sample (3 episodes / 632 frames) in LeRobot v3 format.
df = lerobot.read("pepijn223/egodex-test", load_video_frames="observation.image")
# pick a method (each returns the same schema):
# mediapipe -> CPU, 2D only, permissive license, no weights to supply
# wilor -> GPU, 3D MANO keypoints (MANO weights user-supplied)
df = df.with_column("hands", track_hands(df["observation.image"], method="mediapipe"))
df.write_parquet("annotated/")
Install the method you need as an extra: pip install daft-physical-ai[mediapipe]
(CPU, 2D), pip install daft-physical-ai[wilor] (GPU, 3D), or
pip install daft-physical-ai[all] for both. WiLoR additionally needs a CUDA
torch build and chumpy from git
(pip install 'chumpy @ git+https://github.com/mattloper/chumpy', omitted from the
extra because PyPI metadata can't carry direct references), plus a user-supplied
MANO_RIGHT.pkl (research-gated).
Note: the LeRobot reader with batched video decode (Daft #7184) is not yet in a stable Daft release (latest is v0.7.17). Until it is, this repo resolves
daftfrom the nightly index -uv synchandles it via thedaft-nightlyindex inpyproject.toml.
Output schema
One unified output schema regardless of method: each frame yields a list of 0-2 detected hands. A single hand value (MediaPipe):
{
"handedness": "right", # "left", "right", or "unknown"
"confidence": 0.979,
"kp2d": [[1412.1, 1111.1], # 21 image-space [x, y] keypoints
[1357.9, 1075.9],
...],
"kp3d": None, # 21 [x, y, z] keypoints, or null for 2D-only methods
}
The Daft type is list[struct{ handedness: string, confidence: float32, kp2d: list[list[float32]], kp3d: list[list[float32]] }], defined as HANDS_DTYPE in
daft_physical_ai/hands/schema.py.
Example
A complete walkthrough - read a dataset, run track_hands (MediaPipe), draw the
keypoints, and score against EgoDex ground truth:
Available in three equivalent forms:
- examples/demo.md - read it start to finish; code and outputs inline.
- examples/demo.ipynb - runnable notebook (outputs included).
- examples/demo.py - plain script.
Generate your own (other methods, a Modal GPU runtime, with/without eval) with the
daft-physical-ai hands command - run it with no flags for an interactive
walkthrough, or pass flags:
# No flags - interactive walkthrough that asks a few questions
daft-physical-ai hands
# --no-input skips all prompts; flags supply the answers, the rest use defaults
daft-physical-ai hands --method mediapipe --output-dir my-demo --no-input
daft-physical-ai hands --method wilor --runtime modal --mano-path ./MANO_RIGHT.pkl --no-input
Hand tracking is the first capability; each new one will be its own subcommand
(daft-physical-ai <command> lists what's available).
The bare daft-physical-ai command works once the package is installed. Until
it's published to PyPI, run it from a clone instead:
uv sync # installs the daft-physical-ai console script
uv run daft-physical-ai # generate a demo (prefix the commands above with `uv run`)
To run a generated demo you also need its inference stack (uv sync already
brings the nightly Daft with the LeRobot reader). Install the extras into the
venv, then run from the activated venv - not uv run, which re-syncs the env
and would drop them:
source .venv/bin/activate
uv pip install -U av mediapipe scipy opencv-python matplotlib jupyterlab
jupyter lab hand-tracking-demo/demo.ipynb
Once the LeRobot reader lands in a stable Daft release (> v0.7.17), the nightly
pin in pyproject.toml goes away and this collapses to
pip install daft-physical-ai.
Development
uv sync # set up env + install deps
uv run pre-commit install # install lint/format hooks
uv run pytest tests/ -v # run the test suite
Versioning
Versions are derived from git tags via hatch-vcs. Tag releases as v0.1.0,
v0.2.0, etc.
Publishing
Publishing a GitHub release triggers .github/workflows/publish-package.yml,
which builds a wheel and sdist with uv build and uploads both to PyPI via
trusted publishing. Configure the
trusted publisher on PyPI for this repository before the first release.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file daft_physical_ai-0.1.0.tar.gz.
File metadata
- Download URL: daft_physical_ai-0.1.0.tar.gz
- Upload date:
- Size: 959.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f995d69ae81c1809535ec3d1121cc5e2049e9a98e7e9171869273a830b33c1b8
|
|
| MD5 |
40afcf148392d252a8afb7ae57844363
|
|
| BLAKE2b-256 |
6a1ab685828d45332583b8cc7814578454c5d808b57f80842eb419b05ecda6bd
|
Provenance
The following attestation bundles were made for daft_physical_ai-0.1.0.tar.gz:
Publisher:
publish-package.yml on Eventual-Inc/daft-physical-ai
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
daft_physical_ai-0.1.0.tar.gz -
Subject digest:
f995d69ae81c1809535ec3d1121cc5e2049e9a98e7e9171869273a830b33c1b8 - Sigstore transparency entry: 2121292805
- Sigstore integration time:
-
Permalink:
Eventual-Inc/daft-physical-ai@8b232aa1ef56c8a8aa22ba896c038175ca97d152 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/Eventual-Inc
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-package.yml@8b232aa1ef56c8a8aa22ba896c038175ca97d152 -
Trigger Event:
push
-
Statement type:
File details
Details for the file daft_physical_ai-0.1.0-py3-none-any.whl.
File metadata
- Download URL: daft_physical_ai-0.1.0-py3-none-any.whl
- Upload date:
- Size: 28.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
42fe1fd15488d1fb56deb1029281959b39e46761a4b3479c9f7fe116dcbcc402
|
|
| MD5 |
bcd722098e5fbd6b0410527c7faf1a70
|
|
| BLAKE2b-256 |
4b2327acc38913d733d844c461f84235f608a31c4d3ec50cef2e599d3d24ad38
|
Provenance
The following attestation bundles were made for daft_physical_ai-0.1.0-py3-none-any.whl:
Publisher:
publish-package.yml on Eventual-Inc/daft-physical-ai
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
daft_physical_ai-0.1.0-py3-none-any.whl -
Subject digest:
42fe1fd15488d1fb56deb1029281959b39e46761a4b3479c9f7fe116dcbcc402 - Sigstore transparency entry: 2121293003
- Sigstore integration time:
-
Permalink:
Eventual-Inc/daft-physical-ai@8b232aa1ef56c8a8aa22ba896c038175ca97d152 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/Eventual-Inc
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-package.yml@8b232aa1ef56c8a8aa22ba896c038175ca97d152 -
Trigger Event:
push
-
Statement type: