CV Draw Text
Burn the number into the picture
- source
- image
Your pipeline finally computes something - a dial reading, an object count, a match score, a confidence - and it lives in an INT socket nobody can see. CV Draw Text writes it onto the frame so that the debug image and the result are the same file. That's the whole job.
How it works
Underneath it's cv2.putText with FONT_HERSHEY_SIMPLEX and anti-aliasing, drawn on a copy of your input. x is the left edge of the text baseline and y is the baseline height, which is the detail that makes people think the node is broken: the glyphs sit above y, not on it. With the defaults (x=12, y=42, font_scale=1.2) a short label lands neatly near the top-left of a 512px image, which is clearly the intended use.
font_scale multiplies the base Hershey size - 1.0 is the base, and the default 1.2 is a little larger. There's no font picker, which is fine: Hershey is the only vector font cv2.putText has anyway.
The nice part is outline. Leave it on and the node draws a contrasting halo behind the glyphs first - black behind a light colour, white behind a dark one, following the colour you set. That's why text stays readable when it lands on both a blown-out sky and a dark building in the same frame. It's the difference between a caption and a caption you have to squint at, and people hand-roll this with two putText calls all the time.
Empty text passes the image through unchanged. No error, no blank rectangle - useful when a detection stage upstream returned nothing.
Wiring it usefully
text is a string widget, but right-click it and Convert widget to input and now anything that emits a STRING can drive it. The pack's own docs recommend building that string with StableLlama's Basic Data Handling nodes (to STRING, zfill, concat) - one of the few external packs the README lists as a soft dependency for the shipped example workflows, alongside ComfyUI-Inspire-Pack and pythongosssss's Custom-Scripts. So: decode a digit with a DNN node, zfill it to a fixed width, concat a label in front of it, and stamp the result. That's a readable annotated output with about four nodes.
Also worth remembering: source takes a MASK as happily as an IMAGE, and a single-value color string (like 255) broadcasts across channels. Drawing on masks is a legitimate way to label a batch of segmentation outputs before you save them.
Output is a single image, in the same format as the input.
Things that will annoy you
- Text near the edge.
xandyaccept anything from -1,000,000 to 1,000,000 and nothing clamps the glyphs back into frame. Long strings run off the right edge silently. - Resolution dependence. Everything is in pixels, so a label tuned on a 512px preview is a speck on a 4K render. Rerun the node after an upscale if you want the label visible.
- BGR again.
coloris a BGR tuple:(0, 255, 0)is green only because that one is symmetric,(0, 0, 255)is red. - One line per frame. No wrapping, no newlines -
putTextwill draw a control character as garbage.
Install
# ComfyUI Manager → search "ComfyUI CV" → install → restart
# or:
cd ComfyUI/custom_nodes
git clone https://github.com/bmad4ever/comfyui_cv
cd comfyui_cv && pip install -r requirements.txt
Restart ComfyUI. The pack needs Python ≥ 3.12 and a modern ComfyUI built on the V3 node API - if your install is old, the nodes won't register at all and nothing here is fixable from the node's own settings. The single real dependency is opencv-contrib-python-headless~=5.0.0.93, and you must keep a contrib wheel: installing plain opencv-python over it empties the shared cv2 package's contrib submodules without warning. The pack includes a repair script (tools/repair_opencv_contrib.py --check, then --apply) for exactly that accident.
The author is bmad4ever, who also maintains a couple of small ComfyUI utilities (a cartesian-product list node, a dirty undo/redo extension) - small, tidy tools are the house style here. This pack is a fork of geroldmeisinger's opencv-comfyui that grew into ~470 auto-generated cv2.* wrappers plus curated nodes like this one. The author states plainly that it was written with heavy LLM assistance and shouldn't go into production without your own review. For stamping a number onto a debug frame, that caveat costs you nothing.
Inputs (8)
| Name | Type | Default | Description |
|---|---|---|---|
| source | COMFY_MATCHTYPE_V3 | Image or mask to stamp the text onto (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. | |
| text | STRING | The label; convert to an input to feed a computed string. | |
| x | FLOAT | 12.00-1000000–1000000 | Left edge of the text baseline, in pixels. |
| y | FLOAT | 42.00-1000000–1000000 | Baseline height, in pixels (text sits above it). |
| font_scale | FLOAT | 1.200.1–64 | Font size multiplier (1.0 is the base Hershey size). |
| 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. |
| thickness | INT | 21–64 | Stroke width of the glyphs in pixels. |
| outline | BOOLEAN | true | Draw a contrasting halo behind the text: black behind a light 'color', white behind a dark one. It follows the colour, so black text on a black background is lifted off it rather than disappearing into a black halo. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| image | COMFY_MATCHTYPE_V3 | Same format as the image input. |