Nodes/ComfyUI CV/cv2.goodFeaturesToTrack (2/2)
ComfyUI Node

cv2.goodFeaturesToTrack (2/2)

Cv2.goodFeaturesToTrack (2/2)

By bmad4ever·Created 4 months ago·Updated 15 days ago· 1
cv2.goodFeaturesToTrack (2/2)
  • image
  • mask
  • nparray
◄maxCorners0►
◄qualityLevel0.0000►
◄minDistance0.0000►
◄blockSize0►
◄gradientSize0►
◄useHarrisDetectorfalse►
◄k0.0400►

Shi-Tomasi corners - the points a tracker can actually hang onto. If you have ever read a ComfyUI workflow that does "find points, track points, estimate motion," this function is step one. It answers a narrow question honestly: which pixels in this frame are distinctive enough that I could find them again in the next frame? A flat region, a straight edge, or a smooth gradient is useless for that; a corner is where two edges disagree, and that disagreement survives a small camera move.

Everything expensive in ComfyUI - diffusion, matting, upscaling - has no idea where "interesting" is. Classic CV does, cheaply, on the CPU. These points are the seed for optical flow, homography estimation, panorama stitching and the pack's own CV Track Features (KLT) node: the small data-typed node layer that big graphs actually run on (comfyui-node-plumbing.md).

How it works

For each pixel, OpenCV measures the gradient structure of a blockSize neighbourhood and reduces it to one score - the smaller eigenvalue of the derivative covariance matrix, or the Harris response if useHarrisDetector is on. Everything below qualityLevel × the best score is discarded, then the survivors are picked strongest-first with minDistance enforcing spacing.

That greedy step matters more than people expect: minDistance is what spreads your points over the frame, and raising it is the single best fix when a tracker keeps re-finding the same corner.

Inputs you actually set

OpenCV 5's signature is (image, maxCorners, qualityLevel, minDistance, mask, blockSize, gradientSize, useHarrisDetector?, k?), and this node is the 2/2 variant - the "2" is because the pack generates one node per function overload, and both share the display name cv2.goodFeaturesToTrack.- image - 8-bit or 32-bit single channel. You can wire a colour IMAGE straight in; the wrapper converts it to grayscale for you. But it takes frame 0 of a batch only - this function is not in the pack's per-frame list, so a 16-frame batch gives you frame 0's corners and silence about the rest.

  • maxCorners - 0 means "no limit, return everything". For KLT you want 300–1000, not everything.
  • qualityLevel - the fraction of the best corner's score to keep. 0.01 is the classic value; 0.001 floods you with weak corners.
  • minDistance - in pixels. 10–20 is sane at 1024px.
  • blockSize / gradientSize - both start at 0 in the UI, and the author left them with blank tooltips because OpenCV's docs give no text for them. 0 is not a meaningful neighbourhood size; type 3 and 3 and move on.
  • mask - required in this variant, unlike the 1/2 node where it is optional. It is a real ROI gate: white pixels are searched, black are ignored. If you do not want a mask, use the other variant.
  • useHarrisDetector / k - leave alone unless you want Harris scoring (k = 0.04).

Output is a single nparray of (x, y) corner coordinates, float32, ordered strongest first.

Wiring it up

Draw it with CV Draw Points (it eats (N,1,2) or (N,2) directly), refine it with the raw cv2.cornerSubPix node, feed it to cv2.calcOpticalFlowPyrLK as prevPts, or hand it to cv2.HoughLinesPointSet for the dominant line through a scattered point set. The pack ships 34_corner_detection_playground.json, which wires exactly this loop with Harris and sub-pixel refinement side by side, and 35_keypoint_detectors.json for the class-based detectors.

Worth knowing before you commit: CV Detect Corners is the curated alternative, wrapping GFTTDetector/FASTFeatureDetector - real KEYPOINT objects with a response value, which chain into CV Draw Keypoints and the descriptor matchers. This raw node hands back bare coordinates. Use the raw one when you want points as data; use the curated one when you are feeding a matching pipeline.

Install

ComfyUI Manager → search the pack comfyui_cv (author bmad4ever). By hand:

cd ComfyUI/custom_nodes
git clone https://github.com/bmad4ever/comfyui_cv

It needs Python ≥ 3.12, a recent ComfyUI on the V3 node API, and one real dependency: opencv-contrib-python-headless~=5.0.0.93, pinned because the behavior is curated against it. No models.

When it goes wrong

  • Nothing comes back. Legitimately possible - a blurry or low-contrast frame has no strong corners. qualityLevel at 0.01 on a soft image can genuinely yield zero points, and zero points is not an error you can see: it is an empty array flowing into CV Draw Points, which happily draws nothing. Preview the output array, not just the overlay.
  • Contribute your cv2 install to the community pile. Stock wheels are built with OPENCV_ENABLE_NONFREE=OFF, so nonfree functions are not something to go hunting for here, but the more common injury is version: the four OpenCV distributions all share one site-packages/cv2, so if something else later installs plain opencv-python, contrib submodules quietly empty out and nodes vanish. The pack ships tools/repair_opencv_contrib.py (--check, then --apply) for exactly that. This is a very old wound in the ComfyUI ecosystem - the community's own dependency-feedback thread is full of people "slamming" opencv versions around to stop custom-node import errors.
  • Production caveat. The README is candid that the pack was written with heavy LLM assistance and partly test-overfitted - verify what you rely on.
Categoryimage/CV/low-level/cv2 G

Inputs (9)

NameTypeDefaultDescription
imageNPARRAY,IMAGE,MASKInput 8-bit or floating-point 32-bit, single-channel image. Accepts a ComfyUI IMAGE/MASK directly (frame 0 of a batch) or an NPARRAY. Arithmetic ops (add, multiply, etc.) process the full IMAGE batch when both inputs have the same batch size.
maxCornersINT0-2147483648–2147483647Maximum number of corners to return. If there are more corners than are found, the strongest of them is returned. `maxCorners <= 0` implies that no limit on the maximum is set and all detected corners are returned.
qualityLevelFLOAT0.0000-1e+38–1e+38Parameter characterizing the minimal accepted quality of image corners. The parameter value is multiplied by the best corner quality measure, which is the minimal eigenvalue (see #cornerMinEigenVal ) or the Harris function response (see #cornerHarris ). The corners with the quality measure less than the product are rejected. For example, if the best corner has the quality measure = 1500, and the qualityLevel=0.01 , then all the corners with the quality measure less than 15 are rejected.
minDistanceFLOAT0.0000-1e+38–1e+38Minimum possible Euclidean distance between the returned corners.
maskNPARRAY,IMAGE,MASKOptional region of interest. If the image is not empty (it needs to have the type CV_8UC1 and the same size as image ), it specifies the region in which the corners are detected. Accepts a ComfyUI IMAGE/MASK directly (frame 0 of a batch) or an NPARRAY. Arithmetic ops (add, multiply, etc.) process the full IMAGE batch when both inputs have the same batch size.
blockSizeINT0-2147483648–2147483647Size of an average block for computing a derivative covariation matrix over each pixel neighborhood. See cornerEigenValsAndVecs .
gradientSizeINT0-2147483648–2147483647 - - -
useHarrisDetectoroptBOOLEANfalseParameter indicating whether to use a Harris detector (see #cornerHarris) or #cornerMinEigenVal. Preset to the OpenCV default (False).
koptFLOAT0.0400-1e+38–1e+38Free parameter of the Harris detector. Preset to the OpenCV default (0.04).

Outputs (1)

NameTypeDescription
nparrayNPARRAY—