OpenCV estimateAffine2D_0
The node that finds the transform between two sets of matching points
- from_
- to
- inliers
- nparray_0
- nparray_1
Imagine you've matched two sets of points - say, keypoints on frame 1 and the same keypoints on frame 2 of a video. You know they line up, but how? What rotation, scale, shear, and translation turn one set into the other? That's the question estimateAffine2D answers: it takes two point sets and hands back a 2×3 affine transform matrix that best maps one onto the other, plus a mask saying which points it trusted.
This node is the OpenCV cv2.estimateAffine2D wrapper from opencv-comfyui (geroldmeisinger/opencv-comfyui), the auto-generated "every cv2 function as a node" pack. It's the mathematical core of image alignment - image stitching, frame registration, motion estimation, stabilizing a wobbling shot. In ComfyUI you'll mostly reach for it when you're building a registration pipeline, because the transform it produces is the thing you'd feed into a warpAffine node (which this pack also ships) to actually move the image.
How it works
The function computes the best-fit affine transform (rotation + scale + shear + translation - 6 degrees of freedom) from corresponding point pairs. The method parameter decides how it handles the "best" part:
0- plain least squares: fits all points, falls apart if there are outliers.8- RANSAC (the default in OpenCV): randomly samples subsets, finds the fit most points agree on, and rejects outliers. This is what you want with real-world keypoint matches, which always contain garbage.4- LMEDS: least-median-of-squares, another robust estimator.16- RHO, RANSAC's newer, usually faster cousin.
RANSAC's robustness is the whole point - a handful of wrong keypoint matches can skew least squares badly, and RANSAC just ignores them.
Inputs and outputs
- from_ (NPARRAY) - source points, one per row, N×2.
- to (NPARRAY) - matching destination points, N×2, same count.
- method (INT) - the enum above; leave at RANSAC (8) unless you know better.
- ransacReprojThreshold (FLOAT) - how far a point may sit from the predicted transform and still count as an inlier. Default ~3.0; raise it for noisy point clouds.
- maxIters (INT), confidence (FLOAT), refineIters (INT) - RANSAC tuning knobs. The defaults (2000 iterations, 0.99 confidence, 10 refine iterations) work; you almost never need to touch them.
- inliers (NPARRAY, optional) - an out-parameter. Leave it unconnected.
- Outputs: nparray_0 - the 2×3 transform matrix; nparray_1 - the inlier/outlier mask (1 = trusted, 0 = rejected).
Wiring it up
The honest advice: this is a math node with awkward wiring. Your point arrays have to be built as nparrays (from feature detectors or manual coordinate lists), the pack only takes batch_size-1 images through Image2Nparray, and the outputs aren't displayable images - nparray_1 is a 1-D mask array. The realistic flow is: compute matches somewhere, feed both point sets here, take nparray_0 into a warpAffine_0 node to apply the transform to the actual frame. If that sounds like a lot of plumbing, it is. For most people this pack's _0/_1 overload twins are interchangeable - and so are the two estimateAffine2D nodes here, which ship byte-identical.
Install
ComfyUI Manager (search "opencv-comfyui") or git clone https://github.com/geroldmeisinger/opencv-comfyui into ComfyUI/custom_nodes, then restart. Needs opencv-contrib-python (plus numpy, torch in requirements); no model downloads. Author's warning applies: "Expect dragons!" - raw enums, literal-string composites, auto-generated ugliness.
Inputs (8)
| Name | Type | Default | Description |
|---|---|---|---|
| from_ | NPARRAY | — | |
| to | NPARRAY | — | |
| method | INT | — | |
| ransacReprojThreshold | FLOAT | — | |
| maxIters | INT | — | |
| confidence | FLOAT | — | |
| refineIters | INT | — | |
| inliersopt | NPARRAY | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| nparray_0 | NPARRAY | — |
| nparray_1 | NPARRAY | — |