mirror of
https://github.com/visioncortex/vtracer.git
synced 2026-09-14 08:05:58 -07:00
46a1b90ccd
An alternative region-forming frontend selected by --clustering watershed (the color_mode field is replaced by clustering: color-cluster | bw | watershed across CLI, Rust, Python, and Node — it selects the algorithm, not a color space). The algorithm is the watershed hierarchy by volume on the 4-adjacency pixel graph, implemented from the papers: Cousty, Bertrand, Najman, Couprie, "Watershed Cuts: Minimum Spanning Forests and the Drop of Water Principle", IEEE TPAMI 31(8), 2009. Najman, Cousty, Perret, "Playing with Kruskal", ISMM 2013. Edge weights are the max per-channel color difference between adjacent pixels (no gradient image); a counting-sorted Kruskal pass builds the binary partition tree as a flat parents array; a leaves-to-root pass computes subtree area and volume; each merge's persistence (the volume of the smaller side, plateau-corrected) becomes its MST edge's saliency; and cutting the hierarchy is single-linkage over MST edges below the cut level. Watershed cuts label every pixel — no watershed-line pixel class — so the output is a strict, gapless partition that drops straight into both stacked and cutout modes. Integer arithmetic and flat u32 arrays throughout; deterministic across platforms; ~66 ms on a 1400x775 photo. The one dial, --watershed-detail (0..=255), maps exponentially to a target region count (each +25.5 doubles it) since the persistence distribution is far too skewed for a linear threshold. filter_speckle absorbs undersized basins into their most color-similar neighbour rather than dropping them, preserving the partition. The largest region is emitted first as a solid full-canvas background layer so stacked mode keeps its seam-free overdraw; the mosaic flatten is unaffected. Tests: partition invariant (disjoint masks tiling the canvas), detail monotonicity, min-area absorption, determinism, watershed cases in the pipeline/golden suites, stacked-vs-cutout interior equivalence, a watershed seam test, and SegmentKey coverage for the new params.
VTracer 1.0 Design Documents
VTracer is being rearchitected from a single hardcoded pipeline into a vectorization framework. These documents describe the target design.
| Document | Contents |
|---|---|
| architecture.md | Workspace layout, core IR, stage traits, pipeline driver, optimizer & SVG writer, CLI |
| mosaic.md | The seam-free cutout/mosaic mode: boundary-graph tracing and shared-edge curve fitting |
| bindings.md | Python (PyPI), wasm, and the new Node.js (npm) package |
| roadmap.md | Milestones and verification strategy |
Motivation
VTracer today (0.6.x) is a thin driver around the visioncortex crate: one pipeline (color clustering → per-cluster tracing → SVG string), a CLI, a pyo3 binding, and a web demo that duplicates the pipeline. The rewrite turns it into a framework with pluggable stages:
- Frontend — any algorithm that produces clusters/segmentation from a raster image
- Curve fitting backend — pluggable polyline→curve fitters (pixel, polygon, spline, future potrace-style)
- Color fitting — mapping cluster colors to final paints, including custom fixed palettes
- Optimizer — a pass pipeline that shrinks output (relative path syntax, shorthand commands, precision reduction)
- True mosaic cutout — a perfect, gapless tessellation with shared boundary geometry, replacing today's fake cutout (which re-clusters a re-rendered image and shows seams)
The project stays backend/CLI focused, and everything except image file I/O compiles to wasm32-unknown-unknown.
Decisions
visioncortexremains a dependency, wrapped behind traits. Development uses a path/[patch]dependency on the local checkout; API additions are committed to visioncortex directly and published as 0.8.x releases. Verified that everything the new design needs is already public: the fitting primitives (fit_points_with_bezier,find_corners,subdivide_keep_corners,reduce,PathSimplify::*) and cluster pixel access viaClustersView.- In-repo rewrite, clean break. New workspace layout, new API, version bump. Old CLI flags are kept only where they map naturally.
- Python binding stays (ported to the new API). The webapp GUI is dropped; a wasm library crate replaces it.
- New Node.js library published to npm, using the wasm build internally plus a native image reader (sharp).
Pipeline at a glance
┌───────────┐ ┌──────────────┐ ┌─────────────────────────────┐
raster ───▶ │ Frontend │ ─▶│ ColorFitter* │ ─▶│ Compositing │
image │ (segment) │ │ (palette, │ │ Stacked: closed outlines │
└───────────┘ │ quantize, │ │ Mosaic: boundary graph + │
│ merge) │ │ shared-edge fit │
└──────────────┘ └──────────────┬──────────────┘
│ CurveFitter
▼ (pixel/polygon/spline)
┌──────────────────────────────┐
SVG ◀──── │ VectorDoc ─ OptimizerPass* ─ │
│ SvgWriter │
└──────────────────────────────┘