CV Scale Homography
Your warp works, it's just at the wrong resolution
- homography
- homography
You downscaled two images to make feature matching fast, you got a beautiful homography, and now you want to warp the full-resolution original with it. The matrix you're holding is in downscaled-image coordinates. Feed it to cv2.warpPerspective on the full-size source and the result is garbage - not slightly off, garbage.
CV Scale Homography rewrites that 3×3 into the coordinate space you actually want.
How it works
One line of numpy: T(scale_a) @ H @ T_inv(scale_b). Sandwich the matrix between a scale-up on the target side and a scale-down on the source side and the transformation lands on full-resolution pixels. If both images were downscaled by the same factor S for detection, you set scale_a = scale_b = 1/S and everything comes back to full resolution.
The math isn't the hard part; knowing which factor belongs to which side is. The tooltip spells it out and it's worth reading twice:
- scale_a is "for image A (target/warp-ref image)" - the plane you're warping onto.
- scale_b is "for image B (source/warp image)" - the plane you're warping from.
Both are FLOAT, default 1.0, min 1e-06. The homography itself is a 3×3 float64 NPARRAY, exactly what CV Find Homography and cv2.findHomography emit. One output: homography, same type.
This node is a numpy helper, not an OpenCV wrapper - the author says so in the description. That's the broader shape of this pack: a few hundred auto-generated cv2.* wrappers plus curated nodes that do the glue the wrappers can't express.
Where it goes in a graph
Full-res homography feeds cv2.warpPerspective (or the pack's homography/warp nodes) to warp the B image onto A. It also feeds CV DecomposeHomography if you need the rotation/translation/normal out of it. Keep the detection-resolution matrix around too - the two scale_a / scale_b values are a good audit trail of which downscale step you were on.
If what you have is points rather than a matrix, use CV Scale Points. If what you have is boxes, CV Scale BBoxes. Same problem, three different data shapes.
Install
ComfyUI Manager → search ComfyUI CV, install, restart. 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, a recent ComfyUI on the V3 node API, and the contrib wheel - the contrib part matters, see below. No model downloads for this node; it's pure numpy.
Common issues
- Warp is mirrored or wildly wrong. The classic is
scale_a/scale_bswapped. Remember A is the target plane. If you swapped them, the fix is one keystroke - but you'll have re-run the graph twice before you believe it. - Warp nearly right, off by a few percent. Your two images weren't downscaled by the same factor, or the resize used a non-integer factor and you rounded. Pass the two factors separately rather than assuming symmetry.
- Nodes disappear from the menu after installing something else. You now have a non-contrib OpenCV wheel.
opencv-python,opencv-python-headless,opencv-contrib-pythonandopencv-contrib-python-headlessall install into the samesite-packages/cv2, so the plain wheel silently wipes the contrib submodules and every contrib-backed node vanishes. The repo'stools/repair_opencv_contrib.py --checkdiagnoses it and--applyrepairs it. - You're on Python 3.11. The pack's
requires-pythonis>=3.12and it's written against the V3 node API. Don't fight it - update, or accept that this pack isn't yours yet.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| homography | NPARRAY | 3x3 homography matrix (float64). | |
| scale_a | FLOAT | 1.000.000001–1000000 | Scale factor from detection-space to full resolution for image A (target/warp-ref image). 1.0 = no change. |
| scale_b | FLOAT | 1.000.000001–1000000 | Scale factor from detection-space to full resolution for image B (source/warp image). 1.0 = no change. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| homography | NPARRAY | — |