Three refinements that make the watershed frontend a first-class citizen of both compositing modes and of interactive tuning: Stacked mode now stacks for real. Instead of one full-canvas background plus disjoint regions, the cut emits the merge tree itself: the root (whole canvas, mean color) first, then progressively finer ancestor regions, then the final regions on top — the same principle as the color clustering frontend, just with watershed-born clusters. Sub-pixel gaps between abutting regions therefore show their common ancestor's color rather than an unrelated backdrop, and overdraw stays seam-free. A painted-area budget (3x canvas) keeps pathological persistence chains from ballooning the stack; the root and final regions are always emitted so coverage never depends on it. Cutout is native. The watershed hierarchy already decided every merge, so the flattened partition reaches the mosaic untouched: merge_diff is 0 for watershed (the gradient-step re-merge still applies to the color path). Faces are exactly the cut regions. Re-cuts are cached. WatershedHierarchy is now public and split into build(img) — Kruskal, BPT, volume persistence; depends only on the image — and cut(detail, min_area), which is near-linear: region formation, graph-level small-basin absorption (region adjacencies, not pixel sweeps), then the merge tree. Session builds the hierarchy lazily on the first watershed render and re-cuts it on every watershed_detail or filter_speckle change: ~25 ms per re-cut vs ~40 ms rebuild on a 1400x775 photo, with the one-shot Frontend::segment path unchanged (build + cut), so Session output still equals the one-shot pipeline exactly. Tests: flatten-based stack invariants (solid bottom layer, full coverage, final regions topmost, exact region counts), hierarchy re-cut == one-shot, Session re-cut == one-shot across detail changes, and cutout keeping two regions one gradient step apart that the color path's merge would rejoin. Watershed goldens re-blessed for the new stack structure.
Packages
VTracer 1.0 is a vectorization framework (pluggable frontends, curve fitters, color fitting, and output optimization) shipped across four surfaces from this repository:
| Package | Registry | Source | Use |
|---|---|---|---|
vtracer-cli |
crates.io | crates/vtracer-cli |
Command-line tool (vtracer binary) |
vtracer |
crates.io | crates/vtracer |
Rust library / the framework core |
vtracer |
PyPI | crates/vtracer-py |
Python native extension (pyo3 + maturin) |
@visioncortex/vtracer |
npm | nodejs |
Node.js WebAssembly build, no native dependency |
Introduction
visioncortex VTracer is an open source software to convert raster images (like jpg & png) into vector graphics (svg). It can vectorize graphics and photographs and trace the curves to output compact vector files.
Comparing to Potrace which only accept binarized inputs (Black & White pixmap), VTracer has an image processing pipeline which can handle colored high resolution scans. tl;dr: Potrace uses a O(n^2) fitting algorithm, whereas vtracer is entirely O(n).
Comparing to Adobe Illustrator's Image Trace, VTracer's output is much more compact (less shapes) as we adopt a stacking strategy and avoid producing shapes with holes.
VTracer is originally designed for processing high resolution scans of historic blueprints up to gigapixels. At the same time, VTracer can also handle low resolution pixel art, simulating image-rendering: pixelated for retro game artworks.
Technical descriptions of the tracing algorithm and clustering algorithm.
Desktop App (coming soon)
VTracer App features:
- Higher performance
- Adaptive thresholding in B/W mode
- Perfect cutout mode
- Fixed color palette
Cmd App
Input and output can be given as positional arguments or as named flags:
vtracer input.jpg output.svg
# equivalent to:
vtracer --input input.jpg --output output.svg
Full options (flag names are kebab-case, e.g. --filter-speckle):
Usage: vtracer [OPTIONS] [INPUT] [OUTPUT]
Arguments:
[INPUT] Input raster image (positional; or use --input)
[OUTPUT] Output SVG (positional; or use --output)
Options:
-i, --input <INPUT> Path to the input raster image
-o, --output <OUTPUT> Path to the output SVG
--preset <PRESET> Start from a preset: bw, poster, photo
--clustering <CLUSTERING> Region forming: `color-cluster` (default), `bw`, `watershed`
--hierarchical <HIERARCHICAL> Clustering: `stacked` (default) or `cutout` (seam-free mosaic)
-m, --mode <MODE> Curve-fitting mode: `pixel`, `polygon`, `spline`
-f, --filter-speckle <FILTER_SPECKLE> Discard patches smaller than X px in size (0..=128)
-p, --color-precision <COLOR_PRECISION> Significant bits per RGB channel (1..=8)
-g, --gradient-step <GRADIENT_STEP> Color difference between gradient layers (0..=255)
-c, --corner-threshold <CORNER_THRESHOLD> Minimum momentary angle (degrees) to be a corner (0..=180)
-l, --segment-length <SEGMENT_LENGTH> Subdivide until all segments are shorter than this (3.5..=10)
-s, --splice-threshold <SPLICE_THRESHOLD> Minimum angle displacement (degrees) to splice a spline (0..=180)
--path-precision <PATH_PRECISION> Decimal places to use in path coordinates
--palette <PALETTE> Fixed palette: comma-separated hex colors, e.g. '#112233,#445566'
--palette-file <PALETTE_FILE> Fixed palette from a file (hex colors, comma/newline separated)
--max-colors <MAX_COLORS> Auto-quantize to at most N colors
--optimize <OPTIMIZE> Output optimization: 0 = off, 1 = quantize+simplify, 2 = + shorthands
--threshold <THRESHOLD> Binary mode: fixed threshold 0..=255 (foreground below it)
--adaptive Binary mode: Bradley–Roth adaptive threshold (uneven lighting)
--adaptive-window <ADAPTIVE_WINDOW> Adaptive window size in px (0 = auto); implies --adaptive
--adaptive-t <ADAPTIVE_T> Adaptive sensitivity: % below local mean (default 15)
--watershed-detail <WATERSHED_DETAIL> Watershed: hierarchy cut level 0..=255 (higher = more regions)
-h, --help Print help
-V, --version Print version
New in 1.0
- Positional arguments —
vtracer in.png out.svg. --hierarchical cutoutis now a true seam-free mosaic (a gapless tessellation with shared boundaries), replacing the old re-clustered cutout.--palette/--palette-file— snap colors to a fixed palette (nearest in OKLab);--max-colorsauto-quantizes the palette.- Binary thresholding — a tunable fixed cutoff (
--threshold) or Bradley–Roth adaptive thresholding (--adaptive, with--adaptive-window/--adaptive-t) for scans with uneven lighting. --clustering watershed— an alternative region-forming algorithm: a hierarchical watershed on the pixel graph (Cousty et al., TPAMI 2009; Najman, Cousty & Perret, ISMM 2013), cut at--watershed-detail. Content-adaptive regions that follow object shape — pairs beautifully withcutout.
Downloads
You can download pre-built binaries from Releases.
You can also install the program from source:
cargo install vtracer-cli
You are strongly advised to not download from any other third-party sources
Usage
# simplest form
./vtracer input.jpg output.svg
# black & white line art
./vtracer input.jpg output.svg --preset bw
# scanned/photographed line art with uneven lighting
./vtracer scan.jpg output.svg --clustering bw --adaptive
# seam-free mosaic (gapless tessellation)
./vtracer input.jpg output.svg --hierarchical cutout
# watershed region forming, cut to taste
./vtracer photo.jpg output.svg --clustering watershed --watershed-detail 192
# constrain to a fixed palette
./vtracer input.jpg output.svg --palette '#1b1b1b,#e0c088,#5a7d3c,#8fb0d0'
Rust Library
You can install vtracer as a Rust library.
cargo add vtracer@1.0.0-alpha.1
use vtracer::{ColorImage, Config, FitMode, Hierarchical, Preset, Session};
// Decode with whatever you like, then hand over pixels.
let raw = image::open("in.png")?.to_rgba8();
let (width, height) = (raw.width() as usize, raw.height() as usize);
let img = ColorImage { pixels: raw.into_raw(), width, height };
// one-liner
let svg = Config::default().build()?.to_svg(&img)?;
// presets + per-field config
let mut cfg = Config::from_preset(Preset::Poster);
cfg.mode = FitMode::Polygon;
cfg.hierarchical = Hierarchical::Cutout; // seam-free mosaic
cfg.max_colors = Some(8);
let svg = cfg.build()?.to_svg(&img)?;
Split the pipeline when you want the stages separately — segment caches, finish re-runs:
let pipeline = cfg.build()?;
let seg = pipeline.segment(&img)?; // the expensive part
let doc = pipeline.finish(&seg)?; // VectorDoc, ready to serialize
See docs.rs/vtracer for the full API.
Python Library
vtracer is also packaged as a Python native extension.
pip install --pre vtracer
import vtracer
# one-liners
vtracer.convert_file("in.png", "out.svg")
svg = vtracer.convert_bytes(open("in.png", "rb").read())
# rich, reusable config + presets
cfg = vtracer.Config(mode="polygon", hierarchical="cutout")
cfg.palette = ["#1b1b1b", "#e0c088", "#5a7d3c"]
svg = cfg.convert_bytes(data)
vtracer.Config.poster().convert_file("photo.jpg", "poster.svg")
# watershed region forming
ws = vtracer.Config(clustering="watershed", watershed_detail=192)
svg = ws.convert_file("photo.jpg", "photo.svg")
# binary with adaptive (Bradley–Roth) thresholding
bw = vtracer.Config(clustering="bw", adaptive=True)
svg = bw.convert_file("scan.jpg", "scan.svg")
See crates/vtracer-py for the full API.
Node.js Library
@visioncortex/vtracer is available for Node as a WebAssembly build (from the nodejs package) — image decoding and vectorization both run in wasm, so there is no native dependency. Decodes PNG, JPEG, GIF, BMP, and WebP; for other formats, decode yourself and pass raw RGBA to convertPixels.
npm install @visioncortex/vtracer@1.0.0-alpha.1
const vtracer = require('@visioncortex/vtracer');
await vtracer.convertFile('in.png', 'out.svg', { mode: 'polygon' });
const svg = vtracer.convertBuffer(buffer, { preset: 'poster' });
const svg2 = vtracer.convertPixels(rgba, width, height, { clustering: 'bw' });
// binary with adaptive thresholding
const bw = vtracer.convertBuffer(buffer, { clustering: 'bw', adaptive: true });
Citations
VTracer has since been cited by a few academic papers in computer graphics / vision research. Please kindly let us know if you have cited our work:
- SKILL 2023 Framework to Vectorize Digital Artworks for Physical Fabrication based on Geometric Stylization Techniques
- arXiv 2023 Image Vectorization: a Review
- arXiv 2023 StarVector: Generating Scalable Vector Graphics Code from Images
- arXiv 2024 Text-Based Reasoning About Vector Graphics
- arXiv 2024 Delving into LLMs' visual understanding ability using SVG to bridge image and text

