cv2.detail.overlapRoi
Do these two frames even overlap?
- tl1
- tl2
- sz1
- sz2
- bool
A one-question node: given two rectangles - each as a top-left corner and a size - do they intersect, yes or no? The output is a single boolean. In the stitching pipeline it's the cheap test the compositor runs before it bothers trying to blend a pair of warped frames, because warping can push a frame entirely off the canvas and there's no point finding a seam through nothing.
The inputs
tl1 and tl2 are the two top-left corners, and sz1, sz2 the two sizes. All four are CV_TUPLE values: "one value with 2 components (x, y)" per the pack's tooltips, which "travels as a whole, so it cannot arrive half-connected. Wire it from 'CV Tuple' or type the components in place." So you can either type (0, 0) and (1920, 1080) straight into the widgets, or build them with the pack's CV Tuple node when the numbers come from somewhere else in the graph.
Then there are four more inputs, roi_x, roi_y, roi_w, roi_h, with tooltips describing "Rectangle top-left corner X in pixels" and so on. Here's the thing worth understanding before you're confused by them: cv2's signature takes the overlap rectangle as an output parameter - the caller hands in a rectangle and cv2 writes the intersection into it. In the Python binding that means a value you pass rather than a value you get back, and the pack exposes it accordingly, splitting it into its four integer components. What you type there is the buffer's initial content, not an instruction. What comes back from the node is only the boolean; the computed intersection rectangle is written into that parameter and not surfaced as an output.
So: use this as a predicate. If you need the intersection rectangle's numbers, compute them from the four inputs yourself (or with the pack's geometry helpers) - the arithmetic is trivial, it's just max of the two corners to min of the two far corners.
When you'd reach for it
Only really in the "I'm building the compositing loop myself" case, where you're iterating over frames with their warped positions and want to skip pairs that don't overlap, or validate that your panning sequence has enough overlap to stitch at all. A quick sanity check on an image sequence - feed the corners and sizes, and a false tells you those two frames share no pixels.
If you just want a panorama, use CV Stitch or CV Stitch (Advanced) from this pack. You'll never see this node in a working stitch graph, because the stitcher's own compositor calls it internally. This is one of the stitcher's internals you get to poke at because the pack is auto-generated from what cv2 exposes - useful for understanding the pipeline, rarely useful in a real workflow.
An honest aside on the whole cv2.detail.* family: OpenCV documents the stitching module's public surface but not its internals, so the parameter tooltips in these nodes are partly blank placeholders. Read any of them with that in mind rather than assuming a missing tooltip means a parameter does something obvious.
Install
Manager → Install Custom Nodes → ComfyUI CV (publisher bmad4ever), 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 recent V3-API ComfyUI. The contrib headless OpenCV wheel is the only dependency and this node downloads nothing. If your CV Tuple or CV Stitch neighbours are missing, or the whole cv2.detail.* group never appears, the pack skipped wrappers your cv2 doesn't expose at import time - the usual culprit is a non-contrib opencv-python overwriting the shared site-packages/cv2 (python tools/repair_opencv_contrib.py --check, then --apply). The pack is GPL-3.0, forked from geroldmeisinger/opencv-comfyui, largely AI-generated, and its author's disclaimer says not production-ready, no prompt support.
Common issues
- The tuple inputs won't accept a half-wired link. By design -
CV_TUPLEis one composite value. Wire the whole tuple or type it inline. - The node runs but the roi widgets show what you typed. Correct. They're the buffer cv2 overwrites, and the node doesn't hand the intersection back; the boolean is the result.
- Always
falsefor frames you know overlap. Check the units and the convention: sizes are (w, h) and corners are in the same coordinate space as those sizes. Mixing a canvas origin with a frame-local corner gives you a consistent, wrong answer.
Inputs (8)
| Name | Type | Default | Description |
|---|---|---|---|
| tl1 | CV_TUPLE | 0,0 | One value with 2 components (x, y) - it travels as a whole, so it cannot arrive half-connected. Wire it from 'CV Tuple' or type the components in place. |
| tl2 | CV_TUPLE | 0,0 | One value with 2 components (x, y) - it travels as a whole, so it cannot arrive half-connected. Wire it from 'CV Tuple' or type the components in place. |
| sz1 | CV_TUPLE | 0,0 | One value with 2 components (w, h) - it travels as a whole, so it cannot arrive half-connected. Wire it from 'CV Tuple' or type the components in place. |
| sz2 | CV_TUPLE | 0,0 | One value with 2 components (w, h) - it travels as a whole, so it cannot arrive half-connected. Wire it from 'CV Tuple' or type the components in place. |
| roi_x | INT | 0-2147483648–2147483647 | Rectangle top-left corner X in pixels. |
| roi_y | INT | 0-2147483648–2147483647 | Rectangle top-left corner Y in pixels. |
| roi_w | INT | 00–2147483647 | Rectangle width in pixels (>= 0). |
| roi_h | INT | 00–2147483647 | Rectangle height in pixels (>= 0). |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| bool | BOOLEAN | — |