Skip to main content

visionstyle — expressive computer-vision styling

visionstyle

Beautiful, fully configurable bounding boxes for object detection. Boxes, labels, fills, glow, glass, film grain and tracking trails — described by one Style, tuned live in the Studio, saved as YAML, rendered with one call.

import visionstyle as vs

dets = vs.Detections(xyxy=boxes, class_id=classes, confidence=scores, track_id=ids, names=model.names)
frame = vs.annotate(frame, dets, style="cinematic")

CI Python License

Explore visionstyle on GitHub Pages →

The site deploys through GitHub Actions. Its static source and update notes live in site/README.md.


Install

pip install visionstyle              # core: numpy, opencv-headless, pillow, pydantic, pyyaml
pip install "visionstyle[yolo]"      # + ultralytics for the demos / CLI model support
pip install "visionstyle[studio]"    # + fastapi/uvicorn for the Studio web app
pip install "visionstyle[all]"

Presets

Twelve built-in looks. Every one is a plain YAML file you can copy and edit.

Gallery of the built-in presets

Preset Look
default Clean rectangle, solid tag
minimal Hairline outline, bare text
corners Thin L-brackets, monospace tag
rounded Rounded corners, gradient tint, pill label
dashed Dashed perimeter with marching ants
glass Frosted-glass fill and label
neon Glowing hue-cycling gradient outlines
hud Double frame, reticle marks, inside mono labels, dotted trails
cinematic Rounded amber/teal frames, gradient fill, pill labels, glow, filmic grade
tracking Bold per-track trails, id-first labels
spotlight Dims everything outside the detections
confidence Stroke and tag color follow the confidence score
visionstyle presets list
visionstyle presets show cinematic

Python API

import cv2
import visionstyle as vs

frame = cv2.imread("street.jpg")

# 1. detections: boxes in pixels, everything else optional
dets = vs.Detections(
    xyxy=[[590, 650, 720, 1040], [1060, 660, 1520, 1000]],
    class_name=["person", "car"],
    confidence=[0.93, 0.88],
    track_id=[14, 31],
)
# or: dets = vs.Detections.from_ultralytics(model.predict(frame)[0])

# 2. a style: preset name, YAML path, or built in code
style = vs.Style.preset("cinematic")
style.label.components = ["track_id", "text"]   # every option is a typed attribute
style.trail.enabled = True

# 3. render. Keep one Annotator per video stream so trails/animations carry across frames.
annotator = vs.Annotator(style)
out = annotator.annotate(frame, dets)

# one-liner for stills
out = vs.annotate(frame, dets, style="minimal")

Detections accepts lists, NumPy arrays or torch tensors; xyxy is pixel x1, y1, x2, y2 (Detections.from_xywh, from_xywh_topleft, from_dicts also exist). Frames are BGR uint8 like OpenCV; pass rgb=True for RGB arrays.

What you can configure

Section Options
Box rectangle, rounded (radius), corners (bracket length, curved elbows), reticle, none; double line; center mark
Stroke thickness, opacity, color (palette per class/track, confidence ramp, or any hex/rgb/name)
Fill on/off, opacity, color, solid / gradient (5 directions) / hatch
Line solid / dashed / dotted, dash & gap sizes, multi-color segments or perimeter gradient, animation march / hue_cycle / pulse
Label ordered components (text, confidence, track_id, class_id, custom template), 9 anchors × inside/outside, vertical tags on the sides, fonts (Inter, JetBrains Mono or your .ttf), size, weight, uppercase, solid / pill / glass / underline / none backgrounds, border, padding, formats
Effects glow, shadow, frosted glass, spotlight dimming, vignette, film grain, color grade
Tracking trail length, anchor (feet/center/top), solid / dotted / dashed / ribbon, fade & taper, smoothing, glow, points
Global palette (built-in or custom list), per-class color overrides, confidence threshold, resolution scaling, per-object scaling (strength, clamps, box/label), fps

All sizes are in reference pixels at ~1080p and scale automatically with the frame size (style.scale = "auto"), so one style looks the same on a webcam and a 4K photo. On top of that, strokes and label tags scale with each detected object's size (style.object_scale, on by default): far-away objects get thin outlines and small tags, close-up ones get heavier outlines and larger text. Tune strength, min_factor / max_factor, or restrict it with apply_to: box | label; set enabled: false for constant sizes.

Save and share styles

style.save("my_style.yaml")                 # anywhere
style.save_preset("my-look")                # ~/.visionstyle/presets/my-look.yaml
vs.Style.preset("my-look")                  # found by name from now on
vs.presets.list()                           # built-in + yours

Lookup order: $VISIONSTYLE_PRESETS_DIR → ~/.visionstyle/presets → built-ins → file path.

Studio

Design a style visually, on your own image and model, and save it as a preset the package loads by name.

pip install "visionstyle[studio,yolo]"
visionstyle studio          # opens http://127.0.0.1:8420

The visionstyle Studio

  • Source: choose a bundled scene or upload an image or video, set the confidence threshold, and run detection. The sample video includes tracks; new video tracking requires the YOLO extra.
  • Design: start with a preset, then adjust boxes, strokes, labels, effects, and trails beside the preview. The Python package itself renders every change, matching annotate() output. Save (next to the Style menu) stores the look as a named preset with an optional description; the Style menu lists your saved presets, and built-ins stay in the Library.
  • Objects: filter by class, hide objects, or isolate a track. Scrub video frames or play the timeline; use the preview menu to save an annotated frame.
  • Export: copy or download the YAML, a self-contained Python snippet, or a prompt for AI coding tools.

Presets saved in the Studio go to ~/.visionstyle/presets and load by name anywhere on that machine with vs.Style.preset("my-look"). To keep them with a project instead, start the Studio from the repo with visionstyle studio --presets-dir ./styles; each preset becomes styles/<name>.yaml, which you commit and load with vs.Style.load("styles/my-look.yaml") (or set VISIONSTYLE_PRESETS_DIR=./styles to load them by name).

Keyboard shortcuts: Space plays or pauses, ← / → steps through video frames, Shift + ← / → jumps ten frames, and R resets the style. Focused controls keep their own keyboard behavior.

CLI

visionstyle render photo.jpg -s neon --model yolo11n.pt -o out.jpg
visionstyle render clip.mp4  -s tracking --model yolo11n.pt --track -o out.mp4
visionstyle render 0         -s hud --model yolo11n.pt --track -o webcam.mp4   # webcam index
visionstyle render photo.jpg -d detections.json -s corners                    # no model needed
visionstyle gallery photo.jpg --model yolo11n.pt -o gallery.png               # every preset at once
visionstyle presets list | show NAME | export NAME -o my.yaml
visionstyle schema -o style.schema.json

detections.json is a list of {"xyxy": [...], "class_name": "...", "confidence": 0.9, "track_id": 1}.

Development

uv sync --all-extras --group dev
uv run pytest && uv run ruff check . && uv run mypy src

cd studio && npm install
npm run dev            # Vite dev server on :5173 proxying /api to :8420
npm run build          # -> src/visionstyle/studio/static (bundled into the wheel)

When src/visionstyle/style/schema.py changes, regenerate the frontend schema and types:

uv run visionstyle schema -o studio/schema.json && (cd studio && npm run gen:types)

Releases: bump __version__ in src/visionstyle/__init__.py, update CHANGELOG.md, tag vX.Y.Z and push. release.yml builds the frontend + wheel, publishes to PyPI via trusted publishing (register the pypi environment / publisher once on pypi.org) and creates a GitHub release. For a dry run first, start the TestPyPI workflow from the Actions tab: it publishes the current commit as X.Y.Z.devN to test.pypi.org (environment testpypi), installs it into a clean venv and smoke-tests the CLI and the Studio.

Credits

Sample photos: see src/visionstyle/assets/samples/CREDITS.md. Fonts: Inter and JetBrains Mono, both under the SIL Open Font License.

MIT © Basel Mather

Release files for visionstyle 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for visionstyle 0.1.0
File Size Uploaded
visionstyle-0.1.0.tar.gz 4.3 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for visionstyle 0.1.0
File Interpreter ABI Platform
visionstyle-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 8.6 MB

Release files / visionstyle-0.1.0.tar.gz

Download URL visionstyle-0.1.0.tar.gz
Size 4.3 MB
Tags Source
SHA-256 checksum
How to use checksums
d4521b24b9e6cb9a1bcc1fec0e77a4ca38cd310b914985736b6119ba2c72e39d
BLAKE2b-256 checksum
How to use checksums
87bdf51ff804817544916b3b11b1e368b87b97eea14e3d0f1c27ea3d3ed998ff
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.

Transparency log

Release files / visionstyle-0.1.0-py3-none-any.whl

Download URL visionstyle-0.1.0-py3-none-any.whl
Size 4.3 MB
Tags Python 3
SHA-256 checksum
How to use checksums
8134e4156b1d66b7f784cd0ac31e9a71b0c442f3d3ab9ea41a914c483186e2b4
BLAKE2b-256 checksum
How to use checksums
ecc8099e5b3bebf61204157bfa631279776bda9af9dba38eab398ddde848f97f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page