ComfyUI Node

LSD -> DCT Curve Smoother

Turn a sketched stroke into a smooth mathematical curve (and the math to prove it)

By bemoregt·Created about a month ago·Updated about a month ago· 1
LSD -> DCT Curve Smoother
  • image
  • image
  • curve_json
num_dct_coeffs16
num_samples256
min_segment_length5.0
max_gap0
canvas_mode
line_thickness2
line_color255,0,0

Most ComfyUI nodes are about making pixels prettier. This one is the odd cousin: give it an image with a line, stroke, or path in it and it hands you back the curve - as a smooth polyline drawn on an image, and as a JSON blob of coordinates and DCT coefficients you could wire into anything. It's not a diffusion node at all. It's a computer-vision utility that happens to live in your graph, and for the niche of "I need the actual geometry of that stroke," nothing else in the ecosystem does it in one click.

It's from a brand-new, single-node pack (basically no community footprint yet - a July 2026 release with zero search impressions), so treat it as a raw tool rather than a battle-tested one.

How it works

The pipeline is four steps, and each one is a real, named algorithm:

  1. Detect. OpenCV's LSD (cv2.createLineSegmentDetector) finds straight line segments. But LSD is patent-restricted, so on OpenCV builds without it the node silently falls back to FLD (cv2.ximgproc.createFastLineDetector). You'll see which one ran in the JSON output (engine).
  2. Chain. LSD returns dozens of short segments even for one smooth curve. The node greedily connects segment endpoints into a single ordered polyline, always extending from whichever open end is closest to an unused segment.
  3. Resample. DCT assumes uniformly spaced samples, so the polyline gets re-picked into num_samples points evenly spaced by arc length.
  4. Smooth. It applies a DCT-II to the x coordinates and another to the y, keeps only the low-frequency coefficients, and inverse-transforms. Low frequencies hold the shape; dropping the high ones strips the jitter. Yes, it's the same transform JPEG uses, just on a curve instead of an image.

The inputs and outputs that matter

You feed in an image, and the two knobs you'll actually touch are num_dct_coeffs (how much smoothing/compression - fewer means smoother but flatter) and canvas_mode (overlay_on_original, blank_black, or blank_white for the output background). The rest are set-and-forget: num_samples (256), min_segment_length (5, filters short noise segments), max_gap (0 = unlimited, so everything chains into one curve), plus line_thickness and line_color ("255,0,0" red) for drawing.

It returns two things:

  • image - the smoothed curve drawn on your chosen canvas, batch-safe (it processes each image in the batch and stacks them).
  • curve_json - a STRING holding the goods: which engine ran, how many raw segments vs. chained points, the smoothed_curve as [x, y] pairs, and dct_coeffs_x/dct_coeffs_y if you want to reconstruct or compare the curve elsewhere.

The curve_json is the real payoff. image is just a preview; the coordinates are what a script, a plotter, or another node can consume.

Installing it

ComfyUI Manager can usually find it if you search the pack title, but at this age it may not be in the registry yet - cloning is the reliable path:

cd ComfyUI/custom_nodes
git clone https://github.com/bemoregt/ComfyUI_DCTCompress4OpenCurve_CustomNode
cd ComfyUI_DCTCompress4OpenCurve_CustomNode
pip install -r requirements.txt

Then restart ComfyUI and it appears under curve/detection as "LSD -> DCT Curve Smoother."

Where people get burned

  • The opencv conflict. The pack needs opencv-contrib-python (that's where cv2.ximgproc/FLD lives), and the README is explicit: if you already have opencv-python installed, uninstall it first - they collide. The node's own error message says the same: if LSD and ximgproc are both missing, it raises and tells you to install contrib.
  • Multiple disjoint curves. The chaining assumes one dominant curve. Several separate strokes in one image get greedily stitched into a single polyline - the README shows this happening. If you want them separate, lower max_gap so the chaining stops once a gap gets too big.
  • Too few coefficients = saggy ends. Drop num_dct_coeffs very low and the curve's endpoints ripple a bit. That's a DCT boundary effect, not a bug. Also note the node quietly clamps num_dct_coeffs to num_samples, so don't bother setting it higher than the sample count.

It's a sharp little tool for a narrow job - sketch cleanup, stroke extraction, feeding coordinates to something that isn't a GPU. If you don't need the geometry, you don't need it. If you do, it's the only node I've seen that hands you the coefficients too.

Categorycurve/detection

Inputs (8)

NameTypeDefaultDescription
imageIMAGE
num_dct_coeffsINT162–512
num_samplesINT25616–4096
min_segment_lengthFLOAT5.00–1000
max_gapFLOAT00–5000
canvas_modeCOMBO3 options: overlay_on_original, blank_black, blank_white
line_thicknessINT21–20
line_colorSTRING255,0,0

Outputs (2)

NameTypeDescription
imageIMAGE
curve_jsonSTRING