The universal annotation converter
Project description
Panlabel
The universal annotation converter
If you've ever written a one-off Python script to wrangle COCO annotations into YOLO format (or vice versa), panlabel is here to save you the trouble. It's a fast, single-binary CLI that converts between common object detection annotation formats — with built-in validation, clear lossiness warnings, and no Python dependencies to manage.
Panlabel is also available as a Rust library if you want to integrate format conversion into your own tools.
Note: Panlabel is in active development (v0.5.x). The CLI and library APIs may change between versions, so pin to a specific version if you're using it in production.
Installation
pip / uv (any platform)
pip install panlabel
# or
uv pip install panlabel
This installs a pre-built binary — no Rust toolchain needed.
Homebrew (macOS / Linux)
brew install strickvl/tap/panlabel
Shell script (macOS / Linux)
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/strickvl/panlabel/releases/latest/download/panlabel-installer.sh | sh
PowerShell (Windows)
powershell -ExecutionPolicy Bypass -c "irm https://github.com/strickvl/panlabel/releases/latest/download/panlabel-installer.ps1 | iex"
Cargo (from source)
cargo install panlabel
# Enable full HF support (remote Hub import + metadata.parquet)
cargo install panlabel --features hf
Pre-built binaries
Download from the latest GitHub Release. Builds are available for macOS (Intel + Apple Silicon), Linux (x86_64 + ARM64), and Windows.
Docker
docker pull strickvl/panlabel
# Convert a COCO file in your current directory to YOLO
docker run --rm -v "$PWD":/data strickvl/panlabel convert -f coco -t yolo -i /data/annotations.json -o /data/yolo_out --allow-lossy
Multi-arch images (amd64 + arm64) are published for each release.
As a Rust library
cargo add panlabel
Quick start
# Convert COCO annotations to YOLO (auto-detects the input format)
panlabel convert --from auto --to yolo -i annotations.json -o ./yolo_out --allow-lossy
# Convert a YOLO dataset to COCO JSON
panlabel convert -f yolo -t coco -i ./my_dataset -o coco_output.json
# Convert a Pascal VOC dataset to COCO JSON
panlabel convert -f voc -t coco -i ./voc_dataset -o coco_output.json
# Convert Label Studio JSON to COCO JSON
panlabel convert -f label-studio -t coco -i export.json -o coco_output.json
# Convert CVAT XML to COCO JSON
panlabel convert -f cvat -t coco -i annotations.xml -o coco_output.json
# Convert a LabelMe directory to COCO JSON
panlabel convert -f labelme -t coco -i ./labelme_dataset -o coco_output.json
# Convert Apple CreateML JSON to COCO JSON
panlabel convert -f create-ml -t coco -i createml_annotations.json -o coco_output.json
# Convert a KITTI dataset to COCO JSON
panlabel convert -f kitti -t coco -i ./kitti_dataset -o coco_output.json
# Convert VIA JSON to COCO JSON
panlabel convert -f via -t coco -i via_annotations.json -o coco_output.json
# Convert RetinaNet CSV to COCO JSON
panlabel convert -f retinanet -t coco -i annotations.csv -o coco_output.json
# Convert local HF ImageFolder metadata to COCO JSON
panlabel convert -f hf -t coco -i ./hf_dataset -o coco_output.json
# Convert remote HF dataset repo to COCO JSON (requires --features hf when building from source)
panlabel convert -f hf -t coco --hf-repo rishitdagli/cppe-5 --split train -o coco_output.json
# Convert a zip-style HF dataset repo split to IR JSON (auto-detects extracted payload format)
panlabel convert -f hf -t ir-json --hf-repo keremberke/football-object-detection --split train -o football.ir.json
# Check a dataset for problems before training
panlabel validate --format coco annotations.json
# Get machine-readable validation output
panlabel validate --format coco annotations.json --output-format json
# Get a quick overview of what's in a dataset
panlabel stats --format coco annotations.json
# Compare two datasets
panlabel diff --format-a auto --format-b auto old.json new.json
# Sample a smaller subset for quick experiments
panlabel sample -i annotations.json -o sample.ir.json --from auto --to ir-json -n 100 --seed 42
# Preview a conversion without writing output files
panlabel convert --from auto --to ir-json -i annotations.json -o preview.ir.json --dry-run
# Preview a deterministic sample without writing output files
panlabel sample -i annotations.json -o sample.ir.json --from auto --to ir-json -n 100 --seed 42 --dry-run
# Ask for a machine-readable conversion/sample report
panlabel sample -i annotations.json -o sample.ir.json --from auto --to ir-json -n 100 --seed 42 --output-format json
# Discover supported formats as JSON
panlabel list-formats --output json
What can panlabel do?
| Command | What it does |
|---|---|
convert |
Convert between annotation formats, with clear warnings about what (if anything) gets lost |
validate |
Check your dataset for common problems — duplicate IDs, missing references, invalid bounding boxes |
stats |
Show rich dataset statistics in text, JSON, or HTML |
diff |
Compare two datasets semantically (summary or detailed output) |
sample |
Create subset datasets (random or stratified), with optional category filtering and JSON reports |
list-formats |
Show which formats are supported and their read/write/lossiness capabilities, including JSON discovery output |
Supported formats
| Format | Extension / Layout | Description | Lossiness |
|---|---|---|---|
ir-json |
.json |
Panlabel's own intermediate representation | Lossless |
coco |
.json |
COCO object detection format | Conditional |
cvat |
.xml / annotations.xml export |
CVAT for images XML annotation export | Lossy |
label-studio |
.json |
Label Studio task export JSON (rectanglelabels) |
Lossy |
tfod |
.csv |
TensorFlow Object Detection | Lossy |
yolo |
images/ + labels/ directory |
YOLO .txt labels (flat or split-aware, optional confidence) |
Lossy |
voc |
Annotations/ + JPEGImages/ directory |
Pascal VOC XML | Lossy |
hf |
metadata.jsonl / metadata.parquet directory |
Hugging Face ImageFolder metadata | Lossy |
labelme |
.json file or annotations/ directory |
LabelMe per-image JSON annotations | Lossy |
create-ml |
.json |
Apple CreateML annotation format | Lossy |
kitti |
label_2/ + image_2/ directory |
KITTI object detection labels | Lossy |
via |
.json |
VGG Image Annotator (VIA) JSON | Lossy |
retinanet |
.csv |
keras-retinanet CSV format | Lossy |
Run panlabel list-formats for the full details, or panlabel list-formats --output json for machine-readable format discovery.
list-formats shows canonical names (for example label-studio), while commands also accept aliases (for example ls, label-studio-json). Across commands, --output-format is the consistent way to request JSON reports; convert and sample also keep --report as an alias. JSON is pretty-printed on a terminal and compact when piped or captured, which makes it friendlier for scripts and agents. stats also adapts its text renderer: rich/Unicode on a terminal, plain text layout when piped.
More convert examples
# COCO to IR JSON (lossless — no data lost)
panlabel convert -f coco -t ir-json -i input.json -o output.json
# IR JSON to TFOD (lossy — requires explicit opt-in)
panlabel convert -f ir-json -t tfod -i input.json -o output.csv --allow-lossy
# Auto-detect input format from file extension/content or directory layout
panlabel convert --from auto -t coco -i input.csv -o output.json
# Request a machine-readable conversion report
panlabel convert --from auto -t coco -i input.csv -o output.json --output-format json
# Preview a conversion without touching the output path
panlabel convert --from auto -t coco -i input.csv -o output.json --dry-run
Dry runs still do the real thinking work — format detection, validation, sampling/conversion analysis, and lossiness checks — but they skip the final filesystem write. That means they are good for “what would happen?” checks, but they do not prove that the output path is writable.
Getting help
panlabel --help # See all commands
panlabel convert --help # Help for a specific command
panlabel -V # Show version
Documentation
Want to go deeper? The full docs are readable right here on GitHub:
- Documentation home — start here
- CLI reference — every flag and option
- Format reference — how each format works
- Tasks and use cases — what's supported today
- Conversion and lossiness — understanding what gets lost
- Contributing — we'd love your help
- Roadmap — what's coming next
Contributing
Contributions are welcome! Whether it's a bug report, a new format adapter, or a documentation fix — we appreciate the help. For major changes, please open an issue first so we can discuss the approach.
See the contributing guide for details on the codebase structure and how to make changes.
License
MIT — see LICENSE for details.
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 Distributions
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 panlabel-0.6.0.tar.gz.
File metadata
- Download URL: panlabel-0.6.0.tar.gz
- Upload date:
- Size: 314.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.10.10 {"installer":{"name":"uv","version":"0.10.10","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d2ee51cdf0b0c1e79703a8e78e26f30b6c8154b127efabeaad54db43f22c1a8e
|
|
| MD5 |
a048837c761c350e8b3a07890ed9eb0e
|
|
| BLAKE2b-256 |
c5d3c60c4b11d5df6348094719c281ee222e5997a25818b20d8ce0b4e559ee1b
|
File details
Details for the file panlabel-0.6.0-py3-none-win_amd64.whl.
File metadata
- Download URL: panlabel-0.6.0-py3-none-win_amd64.whl
- Upload date:
- Size: 1.4 MB
- Tags: Python 3, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.10.10 {"installer":{"name":"uv","version":"0.10.10","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cb28ca58fdb8afff37c5c75ed5b869b44a734826e1df43e32ea8928822ca13d9
|
|
| MD5 |
e39c24d5fe4ca38db7985fedc525ae01
|
|
| BLAKE2b-256 |
fec95b88f650b668a0b39119650e36d60668d3f182dbbb05a7c85e10d2732667
|
File details
Details for the file panlabel-0.6.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: panlabel-0.6.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 1.5 MB
- Tags: Python 3, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.10.10 {"installer":{"name":"uv","version":"0.10.10","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
85a6e0184ed0a73aac97578589a24327952d0c493207711d90ae9cf48a17017d
|
|
| MD5 |
5a5f83cd57d0dfbc831a46e8e6a51598
|
|
| BLAKE2b-256 |
40973f9784d5c34808e62ed5bb999f68ee8236ee89fd88e7d7e6acefa47fbb12
|
File details
Details for the file panlabel-0.6.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: panlabel-0.6.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 1.3 MB
- Tags: Python 3, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.10.10 {"installer":{"name":"uv","version":"0.10.10","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
efa8b5e852d4cb50166445b1dc0b35fd7010826da41f87424575607c5d4a88e0
|
|
| MD5 |
657e3837c18a36993ccece7e599925bc
|
|
| BLAKE2b-256 |
84cb3ba5b43e2b0533d469c7844c703a689f126f73e2244926e983c1113f41b8
|
File details
Details for the file panlabel-0.6.0-py3-none-macosx_11_0_arm64.whl.
File metadata
- Download URL: panlabel-0.6.0-py3-none-macosx_11_0_arm64.whl
- Upload date:
- Size: 1.3 MB
- Tags: Python 3, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.10.10 {"installer":{"name":"uv","version":"0.10.10","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
68d6979392095a29f2d000717b3c981a9bbb356f5f9bb3cd7daa76d89071d5bf
|
|
| MD5 |
41b115032a7df98e8cb9d08ab0eabc53
|
|
| BLAKE2b-256 |
e51ef5b24a773bb67c36984b32464abfc268879589597713f55183e06f3d8109
|
File details
Details for the file panlabel-0.6.0-py3-none-macosx_10_12_x86_64.whl.
File metadata
- Download URL: panlabel-0.6.0-py3-none-macosx_10_12_x86_64.whl
- Upload date:
- Size: 1.4 MB
- Tags: Python 3, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.10.10 {"installer":{"name":"uv","version":"0.10.10","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
55dec7fba8b2bc88690a3e5dadc8c177c98f2a064d14e0f1e053aa4eaad748bd
|
|
| MD5 |
901a8b69bf329b90c5f8526bd27b6482
|
|
| BLAKE2b-256 |
7f4ec7f0231ddff7779d1cb8c6b63cdf41652b7049f0733bb14037e51285fae8
|