Skip to content

Latest commit

ย 

History

151 Commits

Folders and files

NameName
Last commit message
Last commit date
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

tode

A fast, open-source annotation tool for video frames and images โ€” bounding boxes, polygon segmentation, and image classification โ€” powered by RT-DETR auto-annotation and a built-in web server for multi-user workflows. Ships as a PySide6 desktop app with a one-click installer.


Contents


Features

Desktop app (PySide6)

  • Auto-annotate with RT-DETR (HuggingFace transformers + supervision) โ€” one frame or all at once
  • Three annotation types: bounding box, polygon segmentation, image classification
  • Click-and-drag box drawing with full resize / move handles
  • Polygon draw mode โ€” click to place vertices, double-click to close, Escape to cancel
  • Play/pause video with variable speed (0.5ร— / 1ร— / 2ร— / 4ร—) and Space bar toggle
  • Adjustable frame step โ€” load every Nth frame for fast navigation on long videos
  • Manual class names + confidence threshold slider
  • Live log viewer, class-filter, per-frame undo (clear), label persistence across sessions

Export formats

  • YOLO (images/ + labels/ + data.yaml)
  • COCO JSON
  • Pascal VOC XML
  • CSV
  • JSON

Web server (FastAPI)

  • REST API for projects, frame upload, per-frame annotations, ZIP export
  • Dark-theme SPA at http://localhost:8000 โ€” works in any browser
  • Canvas annotation (bbox / polygon / classification), frame strip, keyboard navigation

Performance

  • Frames saved as JPEG (not PNG) โ€” 5โ€“10ร— faster writes, 10ร— smaller files
  • Image folder loading skips unnecessary decoding โ€” near-instant for large folders
  • Label scan does one os.listdir() at startup instead of per-frame file stats
  • Background frame extraction โ€” UI is responsive immediately after opening a video

Quick Start

# 1. Clone
git clone https://github.com/tedo001/tode.git
cd tode

# 2. Virtual environment (Python 3.11 or 3.12)
python3.12 -m venv .venv
source .venv/bin/activate          # Windows: .venv\Scripts\activate

# 3. Install desktop dependencies
pip install -r requirements.txt

# 4. Launch the desktop app
python main.py

# 5. (Optional) Install and launch the web server
pip install -r requirements-server.txt
python run_server.py               # โ†’ http://localhost:8000

Prefer a one-click install? tode also ships as a WEKA-style installer (tode-setup.exe on Windows, a tarball on Linux) that bundles Python and all dependencies โ€” no manual setup. See packaging/README.md.


Desktop App

Opening a Source

Toolbar button Action
๐Ÿ“‚ Open Tabbed dialog โ€” Video / Image / Image Folder
๐ŸŽฌ Video Direct video file picker
๐Ÿ–ผ Image Single image or image folder

Click the canvas when no source is loaded to open the file picker directly.

Supported video formats: MP4, AVI, MOV, MKV, WEBM, FLV, WMV

Supported image formats: JPG, PNG, BMP, TIFF, WEBP

Frame Step โ€” the Open dialog includes a "Video frame step" spinbox (1โ€“30). At step=5 a 30 fps video loads 6ร— fewer frames; at step=1 (default) every frame is indexed. Frames not yet extracted from the background thread are decoded on-demand.


Annotation Types

Select the annotation type from the mode bar above the canvas.

Bounding Box (W key โ†’ Draw mode)

  1. Click and drag on the canvas to draw a box
  2. Click inside a drawn box to select it โ€” 8 resize handles appear
  3. Drag a handle to resize; drag the body to move
  4. Click an empty area or press V / Esc to deselect

Polygon Segmentation (โฌ  Polygon button)

  1. Click to place each vertex
  2. Double-click to close the polygon and commit it
  3. Escape cancels the polygon in progress
  4. Saved in YOLO-seg format (.seg.txt sidecar)

Image Classification (๐Ÿท Cls button)

  • Assigns a single class label to the whole frame (no spatial extent)
  • Saved as a .cls.txt sidecar

Keyboard Shortcuts

Key Action
A / โ† Previous frame
D / โ†’ Next frame
Home Jump to first frame
End Jump to last frame
W Switch to Draw Box mode
V / Esc Switch to View mode / cancel polygon
Space Toggle play / pause
Y Run RT-DETR on the current frame
Ctrl+S Save annotations
Ctrl+E Export dataset
Ctrl+O Open source dialog
Delete Clear all annotations on the current frame

Playback Controls

The navigation bar has five buttons:

โฎ   โ—€   โ–ถ/โธ   โ–ถ   โญ
  • โ–ถ (purple) โ€” click or press Space to start auto-advance
  • โธ (pink) โ€” shown while playing; click or press Space to pause
  • Speed row below: 0.5ร— 1ร— 2ร— 4ร—
  • Any navigation button (โฎ โ—€ โ–ถ โญ) stops playback automatically

RT-DETR Models

The control panel has an RT-DETR model dropdown (HuggingFace ids).

Model Backbone Speed Accuracy
PekingU/rtdetr_r18vd ResNet-18 Fastest Good
PekingU/rtdetr_r34vd ResNet-34 Fast Better
PekingU/rtdetr_r50vd ResNet-50 Medium High (default)
PekingU/rtdetr_r101vd ResNet-101 Slow Best
PekingU/rtdetr_v2_r18vd / _r50vd RT-DETRv2 โ€” improved

Weights are auto-downloaded from the HuggingFace Hub on first use and cached โ€” no local weight files to manage. Set a different default with the TODE_RTDETR_MODEL environment variable.


Exporting

Click ๐Ÿ“ค Export and choose a format and output folder.

Format Output
YOLO images/ + labels/ + data.yaml โ€” ready for yolo train
COCO annotations.json (images, annotations, categories)
Pascal VOC One XML per image
CSV One row per bounding box
JSON Custom JSON with all annotation types

Only annotated frames are exported. Frame files are renumbered sequentially (img_1, img_2, โ€ฆ) so images and labels always match 1-to-1.

The YOLO/COCO export uses the standard dataset layout, so the result feeds straight into any detection trainer (RT-DETR fine-tuning via transformers, or any framework that reads YOLO data.yaml / COCO annotations.json).


Web Server

The web server is a standalone FastAPI app that does not modify main.py or any desktop code. Run it alongside or instead of the desktop app.

Starting the Server

pip install -r requirements-server.txt
python run_server.py

Open http://localhost:8000 in a browser.

Environment variables:

Variable Default Description
TODE_HOST 0.0.0.0 Bind address
TODE_PORT 8000 Port
TODE_RELOAD false Uvicorn auto-reload (dev mode)

REST API

Method Endpoint Description
GET /health Health check
GET /api/projects List all projects
POST /api/projects Create a project
GET /api/projects/{id} Get project metadata
DELETE /api/projects/{id} Delete a project
PATCH /api/projects/{id}/classes Update class list
POST /api/projects/{id}/upload Upload frame images
GET /api/projects/{id}/export?fmt=yolo Download annotations as ZIP
GET /api/projects/{id}/frames List frames
GET /api/projects/{id}/frames/{idx}/image Get frame image
GET /api/projects/{id}/frames/{idx}/annotations Get frame annotations
POST /api/projects/{id}/frames/{idx}/annotations Save frame annotations

All annotation endpoints accept and return JSON with boxes, polygons, and classifications arrays.


Performance

Scenario Before After
Write one 1080p frame ~40 ms (PNG) ~6 ms (JPEG)
1000-frame background extraction ~40 s disk I/O ~6 s
Load 1000-image folder Decodes all 1000 images Zero decodes โ€” path copy only
Startup label scan (1000 frames) ~3000 stat() calls 1 listdir() call
10-min 30fps video at step=5 18 000 frames 3 600 frames

Frames are cached as JPEG on first access. Subsequent navigation reads the JPEG from disk (~5 ms per frame). Old projects with .png frames are supported automatically via a fallback path.


Output Structure

output/
โ”œโ”€โ”€ frames/
โ”‚   โ””โ”€โ”€ <source_name>/
โ”‚       โ”œโ”€โ”€ frame_000000.jpg        โ† JPEG cache (new projects)
โ”‚       โ””โ”€โ”€ frame_000005.jpg
โ”œโ”€โ”€ labels/
โ”‚   โ””โ”€โ”€ <source_name>/
โ”‚       โ”œโ”€โ”€ frame_000000.txt        โ† YOLO bbox  (class cx cy w h)
โ”‚       โ”œโ”€โ”€ frame_000000.seg.txt    โ† YOLO-seg polygons
โ”‚       โ”œโ”€โ”€ frame_000000.cls.txt    โ† image-level classification
โ”‚       โ””โ”€โ”€ classes.json            โ† class id โ†’ name mapping
โ””โ”€โ”€ server_projects/                โ† web server projects
    โ””โ”€โ”€ <project_id>/
        โ”œโ”€โ”€ meta.json
        โ”œโ”€โ”€ frames/
        โ””โ”€โ”€ labels/

Label format:

File Format
.txt <class_id> <cx> <cy> <w> <h> (normalised, YOLO)
.seg.txt <class_id> <x1> <y1> <x2> <y2> โ€ฆ <xN> <yN> (normalised, YOLO-seg)
.cls.txt <class_id> <confidence>

Project Structure

tode/
โ”œโ”€โ”€ main.py                         # desktop app entry point
โ”œโ”€โ”€ run_server.py                   # web server entry point
โ”œโ”€โ”€ requirements.txt                # desktop dependencies
โ”œโ”€โ”€ requirements-server.txt         # web server dependencies
โ”œโ”€โ”€ requirements-test.txt           # test dependencies
โ”‚
โ”œโ”€โ”€ src/
โ”‚   โ”œโ”€โ”€ core/
โ”‚   โ”‚   โ”œโ”€โ”€ annotation_manager.py   # orchestrates the full pipeline
โ”‚   โ”‚   โ”œโ”€โ”€ video_loader.py         # OpenCV video I/O
โ”‚   โ”‚   โ”œโ”€โ”€ frame_extractor.py      # sequential JPEG frame extraction
โ”‚   โ”‚   โ”œโ”€โ”€ image_loader.py         # single image / folder loader
โ”‚   โ”‚   โ”œโ”€โ”€ image_frame_extractor.py
โ”‚   โ”‚   โ”œโ”€โ”€ auto_annotator.py       # RT-DETR detector facade (thread-safe)
โ”‚   โ”‚   โ”œโ”€โ”€ exporter.py             # multi-format dataset export
โ”‚   โ”‚   โ”œโ”€โ”€ base_detector.py
โ”‚   โ”‚   โ”œโ”€โ”€ analytics/              # stats, report generator
โ”‚   โ”‚   โ”œโ”€โ”€ detectors/              # RT-DETR (transformers + supervision) backend
โ”‚   โ”‚   โ”œโ”€โ”€ exporters/              # YOLO / COCO / Pascal VOC / CSV / JSON
โ”‚   โ”‚   โ”œโ”€โ”€ importers/              # YOLO / COCO / CSV / JSON importers
โ”‚   โ”‚   โ””โ”€โ”€ pipeline/               # QueueManager, BatchProcessor, Scheduler
โ”‚   โ”‚
โ”‚   โ”œโ”€โ”€ models/
โ”‚   โ”‚   โ”œโ”€โ”€ annotation_model.py     # BoundingBox, PolygonAnnotation,
โ”‚   โ”‚   โ”‚                           # ImageClassification, FrameAnnotation
โ”‚   โ”‚   โ”œโ”€โ”€ project_config.py
โ”‚   โ”‚   โ”œโ”€โ”€ batch_config.py
โ”‚   โ”‚   โ”œโ”€โ”€ class_definition.py
โ”‚   โ”‚   โ”œโ”€โ”€ export_config.py
โ”‚   โ”‚   โ””โ”€โ”€ session.py
โ”‚   โ”‚
โ”‚   โ”œโ”€โ”€ storage/
โ”‚   โ”‚   โ”œโ”€โ”€ label_storage.py        # YOLO .txt / .seg.txt / .cls.txt I/O
โ”‚   โ”‚   โ”œโ”€โ”€ frame_storage.py
โ”‚   โ”‚   โ”œโ”€โ”€ project_storage.py
โ”‚   โ”‚   โ”œโ”€โ”€ session_storage.py
โ”‚   โ”‚   โ””โ”€โ”€ formats/                # YOLO / COCO / CSV / Pascal VOC / JSON
โ”‚   โ”‚
โ”‚   โ””โ”€โ”€ ui/                         # PySide6 desktop UI
โ”‚       โ”œโ”€โ”€ qt_main_window.py       # main window, toolbar, panel, event wiring
โ”‚       โ”œโ”€โ”€ qt_canvas.py            # annotation canvas (boxes + polygons)
โ”‚       โ””โ”€โ”€ qt_workers.py           # QThread load / detect workers
โ”‚
โ”œโ”€โ”€ server/                         # FastAPI web server (standalone)
โ”‚   โ”œโ”€โ”€ app.py
โ”‚   โ”œโ”€โ”€ config.py
โ”‚   โ”œโ”€โ”€ routes/                     # health, projects, frames
โ”‚   โ”œโ”€โ”€ schemas/                    # Pydantic request/response models
โ”‚   โ”œโ”€โ”€ services/                   # project, annotation, export services
โ”‚   โ””โ”€โ”€ static/                     # index.html, app.js, style.css
โ”‚
โ”œโ”€โ”€ packaging/                      # PyInstaller spec + Inno Setup wizard + CI
โ”œโ”€โ”€ tests/                          # pytest
โ””โ”€โ”€ output/                         # generated files (gitignored)

Running Tests

pip install -r requirements-test.txt
pytest tests/ -q

135 tests covering loaders, extractors, exporters, importers, annotation models, storage, pipeline, analytics, and utilities.


Docker

Build and run in a reproducible Linux environment with all dependencies pre-installed.

# Build
docker build -t tode .

# Smoke test
docker run --rm tode python -c "from core import YOLOAnnotator; print('OK')"

# GUI on Linux (X11)
xhost +local:docker
docker compose up

Outputs persist on the host via volume mounts (./output/).

GPU (NVIDIA)

Install nvidia-container-toolkit then uncomment deploy.resources in docker-compose.yml:

docker compose up          # GPU used automatically
Platform GUI in Docker? Recommended
Linux โœ… X11 forwarding Full app
Windows โŒ Needs WSL2 + VcXsrv Headless only
macOS โŒ No native X11 python main.py in venv

License

Licensed under the MIT License โ€” see LICENSE.

tode is fully permissive: use it privately or commercially, modify it, and ship it in closed-source products โ€” just keep the copyright notice. This is possible because every runtime dependency is permissively licensed: the PySide6 GUI is LGPL (dynamically linked, no copyleft on your code), RT-DETR / transformers are Apache-2.0, supervision is MIT, and torch/OpenCV/numpy are BSD/Apache.

Action Allowed?
Use locally / privately โœ…
Modify source code โœ…
Use in a closed-source or commercial product โœ… โ€” just keep the MIT notice
Redistribute / fork โœ…
Train on your own data and keep the weights โœ… โ€” your data, your weights

LGPL note (PySide6): MIT covers tode's own code. PySide6 is LGPL, so if you redistribute the bundled Qt libraries, keep them replaceable (the default PyInstaller/installer layout already satisfies this โ€” Qt ships as separate DLLs, not statically linked).

See THIRD_PARTY_LICENSES.md for the full dependency licence table.

Contributing

Contributions are welcome! Participation in this project is governed by our Code of Conduct.

About

Tode is an open-source auto-annotation platform for fast, accurate dataset labeling and AI workflow automation. open source Contributions welcome.

Resources

Code of conduct

Stars

6 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages