CV Draw Circles
The debug overlay that plugs straight into HoughCircles
- source
- circles
- image
- count
Why you'd reach for this
Classic CV is a pipeline of numbers, and numbers are unreadable. You call Hough circles, you get a 1xNx3 array of (x, y, r) triples, and either those circles are on the coins in the photo or they are on the shadows. The only way to know is to draw them.
This is one of the pack's visualization nodes, and the class is deliberate: nothing in this pack's data nodes ever draws. Data stays data; you choose what gets rendered. That's why there's a separate node for every shape rather than one universal draw-anything box.
How it works
It reshapes the input to (-1, 3) and calls cv2.circle once per row, anti-aliased. thickness = -1 fills instead of outlining. With draw_centers on - and it defaults on - each circle also gets a 2-pixel filled dot at its centre. That dot is the point of the node for detection output: concentric or near-concentric Hough hits look like one blobby ring without it, and with it you can see there were four detections on the same iris.
The source input is polymorphic: IMAGE, MASK or an NPARRAY. A ComfyUI IMAGE is copied and drawn on frame 0, a MASK stays single-channel, and the output comes back in the same format you put in - which means the node drops into a mask pipeline without a converter on either side. The colour parser also adapts: a bare number broadcasts to every channel, a BGR tuple gets truncated or zero-padded to fit, so '255' is the right spelling on a MASK and '(0, 255, 0)' on an image.
Nothing-found is handled the way this whole pack handles it - cv2.HoughCircles returns None, and None/empty passes the image through untouched with count = 0 instead of raising. That matters because "no circles in this frame" is a normal result, not an error, and a graph that hard-fails on it is a graph you can't run over a folder.
Inputs and outputs that matter
- circles -
1xNx3orNx3triples. Hough circles' own output plugs in directly; from anywhere else, keep(x, y, radius)order. - thickness - outline width, default 2,
-1fills. Filled circles hide what's underneath; outlined ones don't. - color - the BGR literal described above. Worth varying between two overlays so you know which node drew which ring.
- draw_centers - default true. Turn it off only for a clean presentation render.
- image out → anything that takes an image, and
count→ a control-flow node. The tooltip's suggestion is the right instinct: branch oncountwith an if/else (Basic Data Handling's is the pack the README names) so the nothing-found case has an explicit path.
Install
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, current ComfyUI (V3 node API), or install ComfyUI CV from ComfyUI Manager. No model, no GPU tensor maths - the drawing is plain cv2 on the CPU, so this node costs milliseconds.
Common issues
- Nothing visible on a MASK. A BGR tuple on a single-channel canvas keeps only its blue component, so
'(0, 255, 0)'becomes 0 - literally invisible. Use'255'. - Everything looks like one thick ring. Concentric detections. Check
draw_centersis on and lower the thickness. - The output format surprised you. It mirrors the input on purpose. If you fed it a MASK, wire the output somewhere that wants a MASK.
- Circles off by a constant offset or scale. You drew detections found on a different image than the one you're drawing on - a resized or letterboxed copy. Draw on the same resolution the detector saw.
- Contrib wheels. All four OpenCV distributions share one
site-packages/cv2; installing a non-contrib wheel over the contrib one empties the contrib submodules and the pack's contrib-backed nodes disappear.tools/repair_opencv_contrib.py --check/--apply.
Inputs (5)
| Name | Type | Default | Description |
|---|---|---|---|
| source | COMFY_MATCHTYPE_V3 | Image or mask to draw on (a copy is made). 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. | |
| circles | NPARRAY | 1xNx3 or Nx3 (x, y, radius) triples; cv2_HoughCircles plugs in directly. | |
| thickness | INT | 2-1–64 | Outline thickness; -1 fills the circles. |
| color | STRING | (0, 255, 0) | Color as a single value (broadcast to all channels) or BGR tuple, e.g. '255' or '(0, 255, 0)'. Shorter tuples are zero-padded; longer tuples are truncated. |
| draw_centers | BOOLEAN | true | Also mark each center with a small dot. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| image | COMFY_MATCHTYPE_V3 | Same format as the image input. |
| count | INT | How many circles were drawn - branch on it with if/else for the nothing-found case. |