cv2.HoughCircles
Cv2.HoughCircles for wheels, coins and dials
- image
- nparray
Hough circles find round things: wheels, coins, dials, lens rims, pupils. The output is not a mask and not a box - it is a list of (x, y, radius) triples, which is exactly the shape you want when "where" and "how big" are separate questions. Radius gives you a scale reference for free, which is why the classic use is not detection for its own sake but measurement: find the circle, and now you know the camera distance, the object's real size, or where to put a mask.
For the "find the object" job, a trained detector wins every time and this node is a poor substitute. Where it wins is the case with no model: something circular, on a plain background, and you do not want to download weights to find it. Cheap, deterministic, no GPU, no licence questions - a fine preprocessing step in the detector layer described in masking-detection-detailing.md.
How it works
cv2.HoughCircles(image, method, dp, minDist, param1, param2, minRadius, maxRadius). Internally it runs Canny first (param1 is the high threshold; the low one is half that), then accumulates votes in a 3-D space of centre-x, centre-y, radius. A genuine circle accumulates votes along a ridge; noise does not. Circles above the accumulator threshold (param2 for the gradient method) come back, strongest first.
dp is the accumulator's inverse resolution: dp = 1 means the accumulator matches the image resolution, dp = 2 halves it (faster, coarser). For the alternative method, OpenCV's recommendation is dp = 1.5.
And HOUGH_GRADIENT_ALT is not a variant of the same algorithm: it is more accurate on well-exposed images and recomputes radiuses properly, but its parameters change meaning, which is the trap below.
Inputs that matter
image- 8-bit single channel. The wrapper grayscales a colour IMAGE link for you. It reads frame 0 of a batch; this function is not in the pack's per-frame list.method- the dropdown offers all five Hough modes, but cv2's circle detector only implements the two gradient ones, and the author's tooltip says as much:HOUGH_GRADIENT(default) orHOUGH_GRADIENT_ALT. PickingHOUGH_STANDARDwill not give you a different algorithm, it will fail.dp- starts at 0 in the widget, which is not a usable resolution. Set 1 (or 1.5 for ALT) explicitly.minDist- minimum distance between circle centres. The classic failure knob: too small and one circle comes back five times with different radii; too large and you miss all but the strongest.param1- Canny's high threshold, default 100. ForHOUGH_GRADIENT_ALTOpenCV uses Scharr derivatives and expects something like 300 on a normal-contrast image.param2- read this carefully, because its meaning flips with the method. ForHOUGH_GRADIENTit is a vote count: lower finds more circles, including false ones. ForHOUGH_GRADIENT_ALTit is a perfectness measure between 0 and 1, where 0.9 is the recommended starting point. Leaving it at the 100 default while using ALT is meaningless.minRadius,maxRadius- always constrain these if you can.maxRadius <= 0means "the image's largest dimension", and a negative value makes the gradient method return centres without radiuses at all. Limiting the range is what kills most false positives.
Output is one nparray of (x, y, radius) triples - and CV Draw Circles takes that layout directly, with draw_centers on by default so concentric hits stay readable. Other consumers: cv2.minEnclosingCircle-adjacent geometry nodes, CV Array To Text to read radiuses out, or the same array into a crop policy if you want to crop what you found.
If nothing is found, cv2 returns nothing and the socket carries an empty value; CV Draw Circles explicitly passes the image through in that case and reports count = 0, so branching on count is the correct way to detect "no circles".
Install
Manager → search comfyui_cv (bmad4ever), or:
cd ComfyUI/custom_nodes
git clone https://github.com/bmad4ever/comfyui_cv
pip install "opencv-contrib-python-headless~=5.0.0.93"
Python ≥ 3.12 and a recent ComfyUI on the V3 node API. One dependency, no models. The pack is ~470 generated wrappers plus a few hundred curated nodes, forked from geroldmeisinger's opencv-comfyui - so older tutorials about that pack still describe the same concepts.
When it goes wrong
- The same circle, five times.
minDisttoo small, or strong circular texture (foliage, ripples, a brick wall). SetminRadius/maxRadiusto the actual size range and raiseminDistabove the object's diameter; the problem usually becomes trivial. - Nothing at all, on an image full of circles. Either you are feeding a grey photo instead of an edge-strong image (run
cv2.Cannyfirst - a soft circle has no gradient to vote with), orparam2is too high. - The radii are wrong or zero. You are on
HOUGH_GRADIENTwith a negativemaxRadius, or on ALT where radiuses are always computed - check which method the dropdown is actually on. - Frame 0 only. A batch of 12 frames gives you frame 0's circles; split with
CV Unstack Batchand stack results yourself. - Contrib wheel hygiene. All OpenCV distributions share one
site-packages/cv2; a later non-contrib install silently removes contrib nodes.tools/repair_opencv_contrib.py --check/--apply.
Inputs (8)
| Name | Type | Default | Description |
|---|---|---|---|
| image | NPARRAY,IMAGE,MASK | 8-bit, single-channel, grayscale input 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. | |
| method | COMBO | HOUGH_GRADIENT | Detection method, see #HoughModes. The available methods are #HOUGH_GRADIENT and #HOUGH_GRADIENT_ALT. |
| dp | FLOAT | 0.0000-1e+38–1e+38 | Inverse ratio of the accumulator resolution to the image resolution. For example, if dp=1 , the accumulator has the same resolution as the input image. If dp=2 , the accumulator has half as big width and height. For #HOUGH_GRADIENT_ALT the recommended value is dp=1.5, unless some small very circles need to be detected. |
| minDist | FLOAT | 0.0000-1e+38–1e+38 | Minimum distance between the centers of the detected circles. If the parameter is too small, multiple neighbor circles may be falsely detected in addition to a true one. If it is too large, some circles may be missed. |
| param1opt | FLOAT | 100.0000-1e+38–1e+38 | First method-specific parameter. In case of #HOUGH_GRADIENT and #HOUGH_GRADIENT_ALT, it is the higher threshold of the two passed to the Canny edge detector (the lower one is twice smaller). Note that #HOUGH_GRADIENT_ALT uses #Scharr algorithm to compute image derivatives, so the threshold value should normally be higher, such as 300 or normally exposed and contrasty images. Preset to the OpenCV default (100.0). |
| param2opt | FLOAT | 100.0000-1e+38–1e+38 | Second method-specific parameter. In case of #HOUGH_GRADIENT, it is the accumulator threshold for the circle centers at the detection stage. The smaller it is, the more false circles may be detected. Circles, corresponding to the larger accumulator values, will be returned first. In the case of #HOUGH_GRADIENT_ALT algorithm, this is the circle "perfectness" measure. The closer it to 1, the better shaped circles algorithm selects. In most cases 0.9 should be fine. If you want get better detection of small circles, you may decrease it to 0.85, 0.8 or even less. But then also try to limit the search range [minRadius, maxRadius] to avoid many false circles. Preset to the OpenCV default (100.0). |
| minRadiusopt | INT | 0-2147483648–2147483647 | Minimum circle radius. Preset to the OpenCV default (0). |
| maxRadiusopt | INT | 0-2147483648–2147483647 | Maximum circle radius. If <= 0, uses the maximum image dimension. If < 0, #HOUGH_GRADIENT returns centers without finding the radius. #HOUGH_GRADIENT_ALT always computes circle radiuses. Preset to the OpenCV default (0). |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| nparray | NPARRAY | — |