Files
vtracer/CHANGELOG.md
T
Chris Tsang c3f56a6339 Watershed: hierarchy stacking, native cutout, and cached re-cuts
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.
2026-07-27 15:12:12 +01:00

4.0 KiB
Raw Blame History

Changelog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog and this project adheres to Semantic Versioning.

Unreleased

Added

  • Binary thresholding: a tunable fixed threshold and BradleyRoth adaptive thresholding for uneven lighting — CLI --threshold / --adaptive (--adaptive-window, --adaptive-t), also on Config, Python, and Node.
  • Cutout mode merges neighbouring mosaic regions whose colors are within one gradient step — the flattened tessellation no longer keeps the near-identical faces that stacked gradient layering splits a smooth area into.
  • Watershed clustering (--clustering watershed): an alternative region-forming frontend — a hierarchical watershed by volume on the pixel graph (Cousty et al., TPAMI 2009; Najman, Cousty & Perret, ISMM 2013), cut at a single --watershed-detail dial (0..=255, each +25.5 roughly doubles the region count). Content-adaptive regions with no watershed-line pixels. With cutout the partition reaches the mosaic natively (no gradient-step re-merge); with stacked the merge tree itself is the stack — coarse ancestors below, refined regions on top, the same principle as color clustering — so sub-pixel gaps show ancestor colors and overdraw stays seam-free.
  • WatershedHierarchy is public and split into build (expensive, depends only on the image) and cut (near-instant): Session builds it once and re-cuts on every watershed_detail/filter_speckle change, making the detail slider fully interactive (~25 ms re-cut vs ~40 ms rebuild on a 1400×775 photo).

Changed

  • color_mode is replaced by clustering (color-cluster | bw | watershed) across the CLI (--clustering), Rust (Config::clustering, enum Clustering), Python, and Node — the field selects the region-forming algorithm, not a color space.

1.0.0-alpha.1 - 2026-07-24

Ground-up rewrite of VTracer into a vectorization framework with pluggable stages.

Added

  • Pluggable pipeline: swappable frontend (segmentation), color fitting (incl. custom palettes), curve-fitting backend, and an optimizer pass phase.
  • Mosaic mode: true seam-free, gapless tessellation via shared boundary-graph tracing (pixel, polygon, and spline fitters), replacing the old "cutout" that produced seams.
  • SVG optimizer: relative path syntax, shorthand commands, and coordinate-precision reduction for smaller files.
  • @visioncortex/vtracer Node.js package (npm): wasm core with a native image reader.
  • Rewritten Python bindings (vtracer-py) with a richer API; pyo3 bumped to 0.26 (fixes CPython 3.14 segfaults, #124).
  • CLI accepts positional input/output arguments (#114).

Changed

  • Workspace restructured into crates/vtracer (core lib), crates/vtracer-cli, crates/vtracer-py, and nodejs/.
  • CLI upgraded from clap 2.x to 4.x (#118).
  • filter_speckle CLI cap raised from 16 to 128, matching the web app (#115).
  • Depends on visioncortex 0.9.
  • Python wheel CI now runs only on release tags and manual dispatch, not on every commit.

Removed

  • The pre-1.0 cmdapp crate and the demo webapp GUI.

0.6.12 - 2026-02-04

  • Python Binding

0.6.5 - 2025-10-17

  • Update fastrand to 2.3

0.6.4 - 2024-03-29

  • Update visioncortex version to 0.8.8

0.6.3 - 2023-11-21

0.6.1 - 2023-09-23

  • Fixed "The two lines are parallel!"

Python Binding

Thanks to the contribution of @etjones, we now have an official Python binding! https://github.com/visioncortex/vtracer/pull/55

https://pypi.org/project/vtracer/0.6.10/

0.5.0 - 2022-10-09

0.4.0 - 2021-07-23

  • SVG path string numeric precision

0.3.0 - 2021-01-24

  • Added cutout mode

0.2.0 - 2020-11-15

  • Use relative & closed paths

0.1.1 - 2020-11-01

  • SVG namespace

0.1.0 - 2020-10-31

  • Initial release