Nodes/ComfyUI PenPlotter/Image to Centerline SVG
ComfyUI Node

Image to Centerline SVG

Image to Centerline SVG

By wouterverweirder·Created about a year ago·Updated 4 months ago· 0
Image to Centerline SVG
  • image
  • svg_string
optimize_exhaustivetrue
colorblack

This is the node that gives the whole pack its point. Pen plotters don't draw pixels - they draw lines, one continuous stroke at a time. Feed a normal ComfyUI image into Image to Centerline SVG and it traces the linework down to a single-pixel-wide skeleton, then emits that skeleton as a vector SVG you can plot. If you've ever tried to plot a raster drawing and watched the pen wander over thick, doubled-up outlines, you know why this matters: a pen can only follow the middle of a line, and this node finds the middle for you.

It's the entry point of the classic pipeline: generate or load an image → ImageToCenterline → Optimize SVG with vpype → Plot SVG with AxiDraw (or SVG to Submission File → Upload). Dark lines on a light background work best, which is exactly what most line-art generations produce.

How it works

Four steps under the hood, all grounded in the code. The image tensor is converted to OpenCV format and inverted, so your dark lines become white on black. That binary image goes through a thinning pass - Zhang-Suen skeletonization, or scikit-image's skeletonize if it's importable - that strips each line down to a one-pixel-wide centerline. Then a tracing routine (a port of Lingdong Huang's well-known skeleton-tracing algorithm, MIT-licensed and vendored into the pack) walks the skeleton and breaks it into polylines. Finally those polylines are stitched into a single <path> inside an SVG, colored by the color input (default black), and returned as svg_string.

The image input is your raster. color sets the stroke color of the output path. And optimize_exhaustive (default on)? Here's the honest part: in the shipped code it's accepted but doesn't actually branch anything - the tracing parameters are hardcoded. Don't burn time toggling it and expecting different output.

How to get good results

  • Give it clean line art. Strong contrast, thin strokes, no fill. Thick blobby shapes skeletonize into weird spidery skeletons.
  • Output goes straight into Optimize SVG with vpype for layout and line-merging before anything plots it - the raw skeleton is full of tiny segments, and that's expected.
  • Watch the size. The skeleton is traced at the image's native resolution, so a huge image makes a huge SVG. Resize down first unless you actually want every pixel of detail.

Install

It's the flagship node of the ComfyUI PenPlotter pack. ComfyUI Manager → search "ComfyUI PenPlotter", or:

cd ComfyUI/custom_nodes
git clone https://github.com/wouterverweirder/comfyui-penplotter

Restart ComfyUI. This node specifically needs numpy, opencv-python and numba (the skeleton tracing is JIT-compiled with numba), which the pack installs alongside vpype, websockets, requests, qrcode[pil] and the AxiDraw API.

Common issues

  • "Error: ..." as the output string - this node is unusual in that it returns error text as the SVG string instead of throwing. If your svg_string starts with "Error:", something in the tracing failed; check the console for the real exception.
  • Skeleton looks broken or noisy - the input needs to be a clean binary-ish line drawing. Run thresholding, denoise, or a posterize step upstream before you trace.
  • The optimize_exhaustive flag does nothing - correct, in the current version. It's vestigial; leave it on and move on.

For a niche pack this node is genuinely good at its one job. If you plot AI-generated line art, it's the reason to install the whole thing.

CategoryPen Plotter

Inputs (3)

NameTypeDefaultDescription
imageIMAGE
optimize_exhaustiveoptBOOLEANtrue
coloroptSTRINGblack

Outputs (1)

NameTypeDescription
svg_stringSTRING