Line Length Calculator
A total line length you can actually defend — diagonal-aware, skeletonized, and reported in plain text
- image
- skeleton_overlay
- total_length_px
- skeleton_pixel_count
- report
If you've ever needed to know "how much total line is in this diagram" - for estimating laser cut time, material usage, or just QC on a drawing - you know that counting black pixels lies to you. A 2px-thick line counts double a 1px line even though they're the same length. Line Length Calculator fixes that properly: it thins every line to a single pixel, then measures the skeleton with a diagonal-aware ruler so a diagonal step counts as √2 pixels instead of a flat 1.0. The result is a length in pixels that's actually proportional to distance, not to ink.
How it works
The pipeline: composite any alpha to a white background, convert to grayscale, binarize at threshold (default 128 - pixels darker than this count as line), then skeletonize with scikit-image's skeletonize so all lines are 1px wide. Measurement then walks the skeleton and, for each pixel, checks its eight neighbors: orthogonal neighbors contribute 1.0 per link, diagonal neighbors contribute √2. Each link is counted from both ends and halved, so you get a true path length rather than a pixel count.
The skeleton_pixel_count output is that raw count - the "all pixels" number - and total_length_px is the corrected one. The gap between them is exactly the diagonal correction, and seeing both is what makes the number defensible: a 45° line comes out at ~1.41× its pixel count, which is correct.
invert (default off) flips the logic for white-on-dark images.
What comes out
skeleton_overlay(IMAGE) - the original image with the measured skeleton drawn in red. This is your QA pass: if the red lines don't match the drawing, the number is garbage, and you'll see it immediately.total_length_px(FLOAT) - the headline number.skeleton_pixel_count(INT) - raw skeleton pixels.report(STRING) - a formatted text dump: image size, threshold, black-pixel count pre-skeleton, skeleton count, and final length. Wire it to a Show Text node and you've got an audit trail for whatever you're estimating.
Where it fits
Load Image → Extract Black → LineLengthCalculator → Show Text. The red overlay is the whole reason to trust the float. And if you're doing physical estimates, the numbers give you pixels-per-unit once you know one real dimension.
Install
Part of ComfyUI-HappNodeSet (mikemojen). Manager: search HappNodeSet. Manual:
cd ComfyUI/custom_nodes
git clone https://github.com/mikemojen/ComfyUI-HappNodeSet.git
pip install -r ComfyUI-HappNodeSet/requirements.txt
Restart ComfyUI. Standard pack deps - scikit-image does the skeletonization, OpenCV handles the binarization, nothing exotic.
Common issues
The threshold is the knob that matters: too high and faint lines don't make the binary mask; too low and paper texture becomes "line." The skeletonization assumption is that lines are thin - a thick solid shape will skeletonize to a single centerline, which is usually what you want, but a filled circle will measure as a diameter-ish line rather than a circumference, so don't feed it solid shapes and expect contour lengths. And with curved lines, the straight-step approximation underestimates slightly - fine for estimates, wrong if you need engineering-grade precision on tight curves. Check the red overlay once, trust it after.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| threshold | INT | 1281–254 | Pixel intensity threshold (0-255). Pixels darker than this are treated as line pixels. |
| invert | BOOLEAN | false | Enable if lines are white on dark background instead of black on light. |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| skeleton_overlay | IMAGE | — |
| total_length_px | FLOAT | — |
| skeleton_pixel_count | INT | — |
| report | STRING | — |