OpenCV goodFeaturesToTrack_2
Corner detection with a mask and a blur you control
- image
- mask
- corners
- nparray
goodFeaturesToTrack_2 is the "give me corners, but only where I point, with smoothing I control" version of the Shi-Tomasi detector. Compared to goodFeaturesToTrack_0, two things change: the mask input goes from optional to required, and a new gradientSize input appears. Both changes are genuinely useful once you know what they're for, which makes this the variant you reach for when corner detection needs to be targeted rather than shotgun.
The two new inputs
- mask (
NPARRAY, required): a single-channel array, same size as the image, where nonzero pixels mark the search area. Everything outside the mask is ignored, so you can restrict corner hunting to, say, the top quarter of the frame or a box around a subject. In the_0variant the mask was optional and defaulted to "search everywhere"; here you must provide it, even if it's an all-ones array meaning "everywhere." - gradientSize (
INT, required): the size of the blur applied to the image before the gradient is computed.3is the classic default and works for most clean images; larger sizes like5or7smooth over texture noise and give you more stable corners on busy, high-frequency content. The tradeoff: bigger blur can swallow genuinely fine corners. Since OpenCV 4.4, this is the parameter to tune when your corner list looks jittery between frames.
The rest is the familiar Shi-Tomasi setup: maxCorners caps the count, qualityLevel (a fraction, ~0.01) sets the floor relative to the best corner, minDistance keeps corners apart in pixels, blockSize is the gradient-window size, and useHarrisDetector (False for Shi-Tomasi) with k (0.04) covers the Harris path. The optional corners input is an out-parameter from the underlying C++ API - leave it unconnected.
The output (and the usual trap)
Output is a single nparray: N×1×2 float32 of (x, y) corner coordinates. It is not an image. Try to run it through Nparrays2Image and you'll hit the pack's 'NoneType' object has no attribute 'shape' error, because a point list has no image shape. Draw points with the pack's circle node if you want visual confirmation, or hand the array to the optical-flow node for tracking.
A mask is the natural way to make this useful in a real workflow: detect corners inside a region of interest, then use those corners as the reference set for calcOpticalFlowPyrLK on a later frame. That's the intended pattern - corner detection and optical flow were designed to work together.
Install
Same pack, same drill:
cd ComfyUI/custom_nodes
git clone https://github.com/geroldmeisinger/opencv-comfyui
or ComfyUI Manager (search "opencv-comfyui"), restart. Depends on opencv-contrib-python; no models, no keys.
Gotchas
- You need a real mask nparray, matching the image's spatial size. If you don't have one, generate an all-ones array - or just use
goodFeaturesToTrack_0, which doesn't demand one. gradientSizemust be odd, or OpenCV asserts.3,5,7.- Watch the grayscale/color type assertion (
CV_8UC1) - convert to the channel layout the function wants withcvtColor. - The usual startup clash,
Cannot import name 'guidedFilter' from 'cv2.ximgproc', means duplicate OpenCV wheels - keep one.
The _3 node in this pack is an identical overload of this one - same schema, same behavior. Use _2, and treat _3 as the duplicate it is.
Inputs (10)
| Name | Type | Default | Description |
|---|---|---|---|
| image | NPARRAY | — | |
| maxCorners | INT | — | |
| qualityLevel | FLOAT | — | |
| minDistance | FLOAT | — | |
| mask | NPARRAY | — | |
| blockSize | INT | — | |
| gradientSize | INT | — | |
| useHarrisDetector | BOOLEAN | — | |
| k | FLOAT | — | |
| cornersopt | NPARRAY | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| nparray | NPARRAY | — |