Nodes/opencv-comfyui/OpenCV cornerSubPix_0
ComfyUI Node

OpenCV cornerSubPix_0

CornerSubPix_0 — make your corners sub-pixel precise (yes, really)

By geroldmeisinger·Created about a year ago·Updated about a year ago· 35
OpenCV cornerSubPix_0
  • image
  • corners
  • nparray
winSize
zeroZone
criteria

cornerSubPix_0 is cv2.cornerSubPix, and it does a genuinely neat thing: takes corner locations that are only accurate to the nearest pixel and refines them to sub-pixel precision - fractions of a pixel. That sounds like overkill until you need it. Camera calibration, stereo matching, and precision registration all fail quietly on whole-pixel corner locations; the calibration error budget is often measured in hundredths of a pixel. If your workflow involves any geometry that gets turned into numbers (not pictures), this is the node that takes your corners from "good enough for the eye" to "good enough for the math."

Where does it fit in a diffusion pipeline? Honestly, rarely - same story as the other corner nodes. But it sits right after the other corner nodes in a graph: detect corners (say with cornerHarris_0, or the pack's goodFeaturesToTrack), then feed the detected points here to polish them, then use the refined points for alignment or calibration. It's the finishing step of a feature-detection stage.

How it works

You hand it an image and a starting set of corner points. Around each point it iteratively fits the local image gradient structure - the same structure tensor family - and nudges the location toward where the gradients actually intersect, using a window you specify. The iteration stops when the movement per step drops below a threshold or hits a max iteration count. Result: the same points, moved by sub-pixel amounts, returned as an nparray you can feed straight into geometry code.

The inputs that matter - and the string trap

This is where the pack's quirks bite. Composite OpenCV types can't be widgets, so the generator turned them into STRING inputs parsed with ast.literal_eval. You type Python literals:

  • image - grayscale nparray (it must be the same image the corners came from).
  • corners - your detected corner points as an N×2 (or N×1×2) float32 nparray.
  • winSize - string, e.g. "(5, 5)" - the search window.
  • zeroZone - string, e.g. "(-1, -1)" - a dead zone in the middle (use -1 for "none").
  • criteria - string, a TermCriteria tuple (type, maxIter, epsilon), e.g. "(3, 40, 0.001)" - type 3 means EPS + MAX_ITER. This is the "stop when movement < 0.001 px" control.

The classic failure: you type (5, 5) and it works, then you type [5, 5] and get invalid syntax (<unknown>, line 0) - that's the literal_eval choke. The README's troubleshooting section calls this exact error out. Tuples parse fine; malformed literals don't.

Install

Ships with opencv-comfyui. ComfyUI Manager → search opencv-comfyui → install, or:

cd ComfyUI/custom_nodes
git clone https://github.com/geroldmeisinger/opencv-comfyui

Restart. Needs opencv-contrib-python (+ numpy, torch). No model files.

Common issues

  • invalid syntax (<unknown>, line 0) → one of the STRING inputs isn't a valid Python literal. Check your tuple syntax.
  • Wrong point typecorners must be float32. If goodFeaturesToTrack gave you ints, cast before wiring.
  • Output looks like the input → that's correct behavior. Sub-pixel shifts are invisible at a glance; that's the point. Compare coordinates numerically, not visually.
  • _0 vs _1 → identical overloads; either works.
Categoryimage/OpenCV

Inputs (5)

NameTypeDefaultDescription
imageNPARRAY
cornersNPARRAY
winSizeSTRING
zeroZoneSTRING
criteriaSTRING

Outputs (1)

NameTypeDescription
nparrayNPARRAY