CV Detect Corners
Picking corner detectors that hand you keypoints, not bare points
- image
- keypoints
- points
- sizes
- responses
- count
CV Detect Corners is the descriptor-free corner detector: FAST, or GFTT scored with Shi-Tomasi or Harris. It finds interesting pixels and gives you cv2.KeyPoints - no descriptors, no matching, just locations and strengths.
The distinction that makes this node exist: the pack also ships a raw cv2_goodFeaturesToTrack wrapper, and that returns bare point coordinates. This node returns proper keypoints with a response value, so they chain into CV Draw Keypoints, CV Compute Descriptors and the matching nodes. And FAST has no function form in OpenCV at all - it's a class - so for "give me corners as fast as possible" this is the only door.
When to reach for each: FAST when you need thousands of corners per millisecond and don't care how many - tracking, optical-flow seeding, a SLAM-style front end. GFTT when you want a bounded, evenly-spread set, which is the classic Kanade-Lucas-Tomasi seed and what you want before CV Track Features (KLT).
How it works
FAST tests a ring of 16 pixels around each candidate; if enough of them are consistently brighter or darker than the centre by threshold, it's a corner. fast_type picks how many of the 16 must agree - 9/16 is the standard, and shorter arcs fire more often (and on noise). With non_max_suppression on, you keep only the locally strongest corner instead of every pixel that passed, which is the difference between a usable set and a wall of dots.
GFTT computes a second-moment matrix in a block_size window and scores it: Shi-Tomasi takes the smaller eigenvalue, Harris takes det(M) - k*trace(M)^2 with harris_k as the free parameter. Then it keeps at most max_features of the strongest, subject to quality_level (a fraction of the best corner's score) and min_distance - that last one being what spreads them out instead of clustering them all on one high-contrast edge.
Inputs and outputs
Required: image (grayscale internally), detector (FAST / GFTT Shi-Tomasi / GFTT Harris), then the knobs for whichever you chose - threshold and non_max_suppression for FAST; max_features (default 500), quality_level (0.01) and min_distance (10) for GFTT. The fields belonging to the other detector are simply ignored, so don't panic when changing harris_k does nothing on FAST.
Optional: fast_type (9/16 by default), block_size (3, forced odd) and harris_k (0.04) for the GFTT side.
Outputs are the standard four plus a count: keypoints, points (Nx2 centres for the point-set nodes - k-means, polar conversion, CV Delaunay / Voronoi), sizes, responses, and count. Zero corners is a valid result.
Install
From comfyui_cv (bmad4ever/comfyui_cv). ComfyUI Manager → search "ComfyUI CV", or:
cd ComfyUI/custom_nodes
git clone https://github.com/bmad4ever/comfyui_cv
pip install "opencv-contrib-python-headless~=5.0.0.93"
Restart ComfyUI. Python ≥ 3.12 and a V3-API ComfyUI. The contrib requirement is about the pack as a whole rather than this node, but it's not optional: all four OpenCV distributions share one site-packages/cv2, so a plain opencv-python installed by some other pack silently removes the contrib nodes. tools/repair_opencv_contrib.py --check detects that, --apply repairs it.
Common issues
- FAST returns tens of thousands of points. That's FAST working as designed. Raise
threshold(from 10 upward) and keepnon_max_suppressionon. Left at defaults on a detailed image it will absolutely fill the frame. - GFTT gives you all 500 corners on one object.
min_distancetoo small andquality_leveltoo low. Raisequality_levelto ~0.05 andmin_distanceuntil the corners spread out - that's literally the point of the node. - Corners land a pixel or two off. FAST is a discrete test, and GFTT's Shi-Tomasi peak is not sub-pixel.
cv2_cornerSubPixexists in the low-level wrappers if you need to refine, and the feature detectors (CV Detect Features) refine for you. - You wanted descriptions, not just locations. Corners alone can't be matched. Send
keypointsthroughCV Compute Descriptors, or useCV Detect Features, which detects and describes in one step.
A last note: adding CLAHE-style contrast equalisation upstream (CV Contrast (CLAHE/Equalize)) will change your corner count substantially on badly-lit images. Worth doing once, deliberately, rather than wondering why the same photo gives you 400 corners on one node run and 40 on another.
Inputs (10)
| Name | Type | Default | Description |
|---|---|---|---|
| image | NPARRAY,IMAGE | Image to search (converted to grayscale internally). 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. | |
| detector | COMBO | GFTT (Shi-Tomasi) | FAST: very fast, unbounded count, driven by 'threshold'. GFTT Shi-Tomasi: bounded, evenly spread, driven by max_features/quality_level/min_distance. GFTT Harris: same but scored with the Harris measure (harris_k), which prefers sharper corners. |
| threshold | INT | 101–255 | FAST only: how much brighter/darker the arc of pixels around a candidate must be. Lower = many more corners. |
| non_max_suppression | BOOLEAN | true | FAST only: keep only the locally strongest corner instead of every pixel that passes the test. |
| max_features | INT | 5001–100000 | GFTT only: keep at most this many of the strongest corners. |
| quality_level | FLOAT | 0.0100.0001–1 | GFTT only: minimum corner score as a FRACTION of the best corner's score. 0.01 keeps everything within 1% of the best; raise it to keep only strong corners. |
| min_distance | FLOAT | 100–1000 | GFTT only: minimum spacing in pixels between kept corners - this is what spreads them over the image. |
| fast_typeopt | COMBO | 9/16 (default) | FAST only: how many of the 16 ring pixels must agree. 9/16 is the standard; shorter arcs fire more often. |
| block_sizeopt | INT | 31–31 | GFTT only: neighbourhood size used to compute the corner score (forced odd). |
| harris_kopt | FLOAT | 0.040.001–0.5 | GFTT Harris only: the free parameter k of the Harris response det(M) - k*trace(M)^2. |
Outputs (5)
| Name | Type | Description |
|---|---|---|
| keypoints | CV_KEYPOINTS | cv2.KeyPoint list - draw with 'CV Draw Keypoints', or give them descriptors with 'CV Compute Descriptors' to feed 'CV Match Features'. |
| points | NPARRAY | Nx2 float32 (x, y) centres - the point-set form for 'OpenCV Draw Points', k-means, polar conversion, ... |
| sizes | NPARRAY | (N,) float32 keypoint diameter in pixels. |
| responses | NPARRAY | (N,) float32 detector strength per keypoint - threshold it to keep only the strong ones. |
| count | INT | How many were found; 0 is a valid result, not an error. |