Centerline to SVG
The actual magic of line art → vector
- line_mask
- original_image
- svg_string
- centerline_image
- statistics
This is the node the whole pack is named for, and the one you'll actually tell people about. Everything before it prepares a mask; everything after it edits text. Here is where a line-art image finally becomes an SVG.
What it actually does
Your line art is a raster image where each stroke is maybe 5–20 pixels thick. If you traced the outline of each stroke you'd get a blob, not a line - a mess for laser cutting or plotting. So this node first thins each stroke down to a one-pixel-wide spine (the centerline), then converts those spines into SVG path data.
Mechanically, from the source: it takes your line_mask and runs one of three extraction algorithms - skeleton (Zhang-Suen thinning via scikit-image's skeletonize), medial_axis (same idea but distance-weighted, with a filter that drops spurious noise branches), or ridge (distance transform + threshold, then thin). Then cv2.findContours walks each thinned spine into a point list, cv2.approxPolyDP applies Douglas-Peucker simplification at your simplify_tolerance, and optional bezier_smoothing rounds the result into smooth curves. Out comes a clean, editable SVG string.
Inputs that matter
line_mask- the MASK output from Line Region Detector (or Mask Line Cleanup). Garbage in, garbage out: a noisy mask makes noisy paths.algorithm-ridge,skeleton, ormedial_axis. Start with the defaultridge; switch tomedial_axisif you're getting a lot of spurious little branches,skeletonif you want the most literal trace.simplify_tolerance- Douglas-Peucker tolerance, default 1.0. Raise it for fewer, simpler points; lower it toward 0 for fidelity at the cost of file size. This is the knob you'll fiddle with most.min_path_length- drops paths shorter than this (default 10). Perfect for killing dust specks.smoothing- path smoothing strength, 0–10. High values can round off corners you wanted.dilate_before_thin- dilate the mask first to fuse close parallel lines into one. This is your fix for the classic "double line" problem where extraction picks up both edges of a thick stroke.
Optional: original_image plus color_info and preserve_colors - if you run color_clustering on the detector, you can carry detected colors through into the SVG's stroke attributes.
Outputs: svg_string (feed it to any other TJ_Vector SVG node), centerline_image (a raster preview of the thinned lines - wire this to a preview to see what you actually extracted), and statistics (JSON: path counts, lengths, that sort of thing).
How it fits
In a typical ComfyUI graph you've already got clean line art - ControlNet lineart preprocessors are a whole ecosystem for producing it (the lineart_anime / lineart_coarse family are the usual suspects). The problem was never getting lines, it was getting them out as vectors for a laser cutter, a vinyl plotter, or a real Illustrator file. That's the gap this pack fills, and this node is the center of it.
Install and troubleshooting
Same pack-wide story: ComfyUI Manager search TJ_ComfyUI_Lineart2Vector, or:
cd ComfyUI/custom_nodes
git clone https://github.com/TJ16th/TJ_ComfyUI_Lineart2Vector.git
# restart
Dependencies come from requirements.txt - the notable ones beyond stock ComfyUI are opencv-contrib-python and scikit-image (for the thinning), so if you cloned by hand and skipped pip, that's what will bite. Nothing to download model-wise.
Where people get burned: raising smoothing too far and wondering why corners melted; setting min_path_length too high and losing small facial features or thin accent lines; and feeding it a mask with doubled-up edges without using dilate_before_thin. If the paths look lumpy, simplify more; if they look like tangled spaghetti, the mask was the problem, not this node. When in doubt, run Mask Line Cleanup on the mask first - it exists for exactly this.
Inputs (10)
| Name | Type | Default | Description |
|---|---|---|---|
| line_mask | MASK | — | |
| algorithm | COMBO | 3 options: ridge, skeleton, medial_axis | |
| smoothing | FLOAT | 2.00–10 | — |
| min_path_length | INT | 101–1000 | — |
| simplify_tolerance | FLOAT | 1.00–10 | — |
| bezier_smoothing | BOOLEAN | true | — |
| dilate_before_thin | INT | 00–10 | Dilate mask before thinning to merge close lines (0=disabled) |
| original_imageopt | IMAGE | — | |
| color_infoopt | STRING | — | |
| preserve_colorsopt | BOOLEAN | true | — |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| svg_string | STRING | — |
| centerline_image | IMAGE | — |
| statistics | STRING | — |