OpenCV phaseCorrelate_0
How far did the frame move? Sub-pixel shift detection with OpenCV phaseCorrelate_0
- src1
- src2
- window
- literal
- float
phaseCorrelate_0 answers one specific, very useful question: how far has this image shifted relative to that one? It's a port of cv2.phaseCorrelate, which measures global translational motion between two images down to sub-pixel accuracy. No models, no training, no API - just two arrays and a Fourier transform.
This node comes from opencv-comfyui, the pack that auto-generated ~635 nodes from OpenCV's Python type stubs. The author (Gerold Meisinger, who launched it on r/comfyui in April 2025) frames the whole pack honestly: these are thin wrappers for "small and quick transformations", not full-blown OpenCV apps, and the README warns you to "expect dragons". phaseCorrelate_0 is one of the more genuinely useful dragons, though.
How it works
Phase correlation is a frequency-domain trick. The node runs a discrete Fourier transform on both images, computes the cross-power spectrum, and the inverse transform of that spectrum produces a sharp peak whose location tells you the sub-pixel shift (dx, dy) between the two inputs. The float output is the response - the height of that peak, in [0, 1]. Higher response means a confident match; a low response means the two images don't line up well (or don't share much content).
What's it for? The classic jobs: aligning a denoised or upscaled frame back onto the original so you can compare them pixel-for-pixel, measuring camera shake between consecutive video frames, or registering two shots of the same scene before blending. If your workflow has a "did this pass actually preserve the framing?" moment, this is the cheap way to check it.
The inputs and outputs
src1,src2- the two NPARRAY images to compare. Both must be single-channel and floating point (CV_32FC1). That means grayscale, and likely acvtColornode (code6for BGR2GRAY) in front of this.window- optional NPARRAY, a Hann/tapering window you can build to suppress edge effects. In OpenCV's API the window overload is separate; here it's just optional. Most beginners should leave it unconnected and accept a little edge ringing.- Outputs are
literal(STRING) andfloat. Here's the gotcha: the(dx, dy)shift is aPoint2f, and since the pack can't express composite types as a proper socket, it comes out as a string - you read the shift in the node, you don't wire it into anything numeric. Thefloatresponse is the usable signal.
Install and the usual pack gotchas
Install once per pack: ComfyUI Manager → search "opencv-comfyui", or
cd ComfyUI/custom_nodes
git clone https://github.com/geroldmeisinger/opencv-comfyui
restart ComfyUI, and make sure OpenCV is present (pip install opencv-contrib-python). You work in NPARRAY space: Image2Nparray in, Nparrays2Image out, batch size 1 only - use ImageFromBatch (length 1) if you get the batch error.
Two traps bite people here. First, feeding uint8 RGB images straight in - phaseCorrelate wants float, single-channel, so convert first or you'll hit an assertion error. Second, expecting to use the shift value downstream. The string output means this node is really an observation tool: it tells you the shift and the confidence, and you act on that information manually or through a branching node, rather than feeding the numbers straight into a warp.
It's niche, but it's the kind of niche that saves you an hour of squinting at misaligned comparisons.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| src1 | NPARRAY | — | |
| src2 | NPARRAY | — | |
| windowopt | NPARRAY | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| literal | STRING | — |
| float | FLOAT | — |