Canny Edges (batched)
The boring fix for the node that OOMs on frame 40
- image
- IMAGE
Canny is the least glamorous preprocessor in the stack, and the one that never went away. Every union ControlNet shipped since 2024 includes it - Flux, Qwen-Image, Z-Image, Flux 2 all list canny in the box. Hard outlines remain the cheapest way to tell a model where things go while the prompt decides what they are, and unlike depth or pose, canny needs no model download. It's just math.
Which is why it's annoying that the core Detect Edges (Canny) node is a still-image node wearing a batch input. Feed it a clip and the whole thing goes to kornia in one call. Measured at 1344x768, the author's own notes put that at roughly 170 MB of peak VRAM per frame - a 158-frame pass wants about 27 GB, a 362-frame pass about 57 GB. You know how that ends, and the error blames everything except the preprocessor.
Canny Edges (batched) does the obvious thing: slice the batch, run each slice, concatenate.
How it actually works
The node walks the batch in chunks of frames_per_pass, moves each chunk to the GPU as float32, converts BHWC to BCHW, calls kornia.filters.canny(), keeps element [1] of the return (the binary edge map, not the magnitude map), copies it back to ComfyUI's intermediate device in the original dtype, repeats the single channel to RGB, flips back to BHWC, and cats the lot.
The important part is why slicing is safe. Canny's hysteresis step - the bit that decides whether a weak edge is connected to a strong one - runs per image, so no frame ever consults its neighbour. Cutting the batch into slices gives you the same edges, bit for bit. That's why frames_per_pass is a memory dial and not a quality dial, and why the author can say so in the tooltip without hedging.
The inputs that matter
image - the batch, from a video loader chain, an image batch loader, or any IMAGE output.
low_threshold (0.2) - in the author's words, "weak edges above this join a strong edge. Lower for more lines." This is the one people actually tweak. Worth knowing: the core node defaults to 0.4 / 0.8, so this node's 0.2 / 0.5 starts noticeably denser than the stock preprocessor out of the box. Same math, different starting point - if it looks too busy, that's why, and you didn't do anything wrong.
high_threshold (0.5) - edges above this always count. "Raise to keep only silhouettes," which is the honest description of what a high threshold does: it stops describing texture and starts describing outlines.
frames_per_pass (8) - frames sent to the GPU at once, about 1.5 GB at 1344x768. Only touch this when you need to. On a 12 GB card with a clip already resident, dropping to 2 or 4 buys back the headroom for a couple of seconds.
One output: IMAGE, three-channel, batch in / batch out. The RGB repeat means it drops straight into the control image slot of a ControlNet apply node with no channel fiddling.
The rest of the pack is workflow plumbing (iterative video, context frames, resolution pickers, LoRA dataset tools), and this node has the same origin: a utility the author needed while building video pipelines, extracted and shipped.
Install
ComfyUI Manager, search "Mickmumpitz", Install, restart. Or:
cd ComfyUI/custom_nodes
git clone https://github.com/mickmumpitz/ComfyUI-Mickmumpitz-Nodes.git
The node itself needs kornia, which ComfyUI core already installs (kornia>=0.7.1 is in its requirements), so there's no extra pip step for this one.
The pack, however, ships a requirements.txt (and matching pyproject deps) of numpy, Pillow, opencv-python and ultralytics, and Manager installs that file wholesale. That's a chunky install for something whose face-area nodes are the only users - the README says those run fine with an Impact Subpack detector wired in, and that ultralytics is only needed if you let Face Area Batch Splitter load its own model. Installing by hand and skipping the requirements is a legitimate move if you only came for Canny.
Where people get burned
- Still OOM?
frames_per_pass: 1is not a defeat, it's the floor. The node caps peak memory; total runtime barely moves. - Changing
frames_per_passre-runs the node. ComfyUI caches on inputs, and this one changes the execution even though the output is identical. Don't nudge it for a free preview on a long clip - you're paying for a full pass each time. ModuleNotFoundError: kornia. Not really a pack problem - a mismatched venv where core deps didn't land.pip install korniain the environment ComfyUI actually runs from.- The
weights_only/ultralytics.nn.tasks.DetectionModelerror people hit after installing this pack belongs to the face-detection nodes, not to Canny. Torch 2.6 pickle-allowlist stuff, chased in the wrong place constantly. If your graph has no detector, ignore it and fix the real error.
Reach for this when the batch is long - video control passes, 100+ frame sequences, or any job where the core node has already OOM'd once. For a single still, save the install and use the core Canny. Same edges, fewer widgets.
Inputs (4)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| low_threshold | FLOAT | 0.200.01–0.99 | Weak edges above this join a strong edge. Lower for more lines. |
| high_threshold | FLOAT | 0.500.01–0.99 | Edges above this always count. Raise to keep only silhouettes. |
| frames_per_pass | INT | 81–512 | Frames sent to the GPU at once. 8 needs about 1.5 GB at 1344x768; the result does not depend on this number. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| IMAGE | IMAGE | — |