cv2.initInverseRectificationMap
The reverse lookup that gets you from the clean image back to your lens
- cameraMatrix
- distCoeffs
- R
- newCameraMatrix
- size
- map1
- map2
Undistortion has a direction problem. You calibrate a camera, build a lookup table, and get a nice rectified image - but the original frame is the one you actually shot, and sometimes you need to go back to it: to overlay something on the raw wide-angle plate, to check a calibration by pushing a synthetic grid the other way, or to hand a compositor coordinates that make sense in the un-rectified footage.
cv2.initInverseRectificationMap is the second half of that round trip. It builds the inverse lookup table - still as a map1/map2 pair you feed to cv2.remap.
What it's for, mechanically
initUndistortRectifyMap answers: for each pixel of the corrected output, which source pixel does it sample? The inverse answers the opposite question: given this pixel in the distorted frame, where does it land in the corrected image? The result is the same kind of thing - two arrays that remap consumes - so once you have them, one cv2_remap node gives you the reverse-warped image.
It's a newer OpenCV entry point, so it's exactly the category of node the pack warns about: the registry is generated from whatever your installed build exposes. If the node isn't in the menu after a restart, the build you installed doesn't have the function. Don't go hunting for a different problem.
Inputs and outputs that matter
Four matrices and a size, then two map outputs. The matrices are all NPARRAY-only - the pack types them as data arrays, not pictures, so an IMAGE link is rejected with a tooltip telling you so:
cameraMatrix- the 3×3 intrinsic K. Build one by hand withCV Camera Matrix, read it back from a calibration run (CV Calibrate Camera (Chessboard)/(Circle Grid)outputcamera_matrix), or parse a stored one withParse Matrix.distCoeffs- the(k1, k2, p1, p2[, k3…])vector, straight from the same calibration node. CV's own default is an empty vector = no distortion.R- the rectification rotation, 3×3. For plain mono work an identity is what you want (CV Eyeproduces one); in stereo it's theR1/R2thatcv2_stereoRectifyoutputs.newCameraMatrix- the 3×3 you want the result framed with. K itself is the no-frills choice;cv2_getOptimalNewCameraMatrixgives you the version with a sensible crop/scale tradeoff, and stereoRectify'sP1/P2are the stereo answer.size- one atomicCV_TUPLEvalue, so it can't arrive half-connected. Wire it fromCV Array Size(which reads a real image) or type the two components. The author's tooltip says this is the distorted image size, which makes sense: the inverse map is defined back in the raw frame.m1type-CV_16SC2 (fixed-point, faster remap)by default, orCV_32FC1 (float32, standard). Fixed-point packs coordinates as int16 plus a separate coefficient map and remaps roughly 30% faster. The pack's own stereo workflows switch toCV_32FC1- do that if anything downstream is fussy about a two-channel int16 map.
Outputs are map1 and map2, both NPARRAY, both wired to cv2_remap.
Installing the pack
Manager → search comfyui_cv, 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 ComfyUI new enough for the V3 node API, and that specific OpenCV line - the pack is verified against 5.0.0.93. No models to download for this node.
Where people get burned
Wiring an image into a matrix slot. cameraMatrix, distCoeffs, R and newCameraMatrix all say NPARRAY for a reason. The bridge from a picture to a number is CV Array / CV Cast Array territory, and for these four you almost never want one.
Changing resolution after the fact. The maps are baked for the size you passed. Resize the footage and the map no longer lines up - regenerate it.
Expecting it to be the "undo" of a remap you already applied to a resized image. It's the inverse of the geometry, not of a pipeline. If your actual process resized, cropped or scaled between the two ends, the map can't know that.
Distortion coefficients of the wrong shape. Calibration nodes hand you a 1×N vector; something hand-typed as N×1 may or may not be accepted. If cv2 throws an assert at map-build time, that's the first thing to check.
The pack itself is honest that it's a personal project, heavily LLM-assisted and not production-ready. Verify on your own plate before you trust the numbers in a shot.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| cameraMatrix | NPARRAY | Input camera matrix $A=\vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{1}$ . A data array (points / matrix), NOT an image - only an NPARRAY link is accepted here. | |
| distCoeffs | NPARRAY | Input vector of distortion coefficients $(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6[, s_1, s_2, s_3, s_4[, \tau_x, \tau_y]]]])$ of 4, 5, 8, 12 or 14 elements. If the vector is NULL/empty, the zero distortion coefficients are assumed. A data array (points / matrix), NOT an image - only an NPARRAY link is accepted here. | |
| R | NPARRAY | Optional rectification transformation in the object space (3x3 matrix). R1 or R2, computed by #stereoRectify can be passed here. If the matrix is empty, the identity transformation is assumed. A data array (points / matrix), NOT an image - only an NPARRAY link is accepted here. | |
| newCameraMatrix | NPARRAY | New camera matrix $A'=\vecthreethree{f_x'}{0}{c_x'}{0}{f_y'}{c_y'}{0}{0}{1}$. A data array (points / matrix), NOT an image - only an NPARRAY link is accepted here. | |
| size | CV_TUPLE | 0,0 | Distorted image size. 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. |
| m1type | COMBO | CV_16SC2 (fixed-point, faster remap) | Type of the first output map. Can be CV_32FC1, CV_32FC2 or CV_16SC2, see #convertMaps |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| map1 | NPARRAY | — |
| map2 | NPARRAY | — |