Nodes/ComfyUI CV/cv2.ximgproc.computeMSE
ComfyUI Node

cv2.ximgproc.computeMSE

Two disparity maps, one number

By bmad4ever·Created 4 months ago·Updated 15 days ago· 1
cv2.ximgproc.computeMSE
  • GT
  • src
  • float
◄ROI_x0►
◄ROI_y0►
◄ROI_w0►
◄ROI_h0►

Mean squared error between two disparity maps. That's the whole node: GT and src, an ROI, and one float out. It's the plainest quality metric in the pack, and it's the one you want when you need a single monotonically-sensible number to sort candidates by.

It also has a specific weakness that its sibling in the same module exists to fix: squaring the error means outliers dominate. One bad region - a mislabelled patch, an invalid band, a depth estimator's edge-case failure - can move the mean more than a broadly mediocre map improves it. So when you're comparing, run both this and computeBadPixelPercent (which counts pixels over a tolerance instead of squaring them) and watch whether they agree. When MSE says one thing and bad-pixel-percent says another, you know you're looking at outliers rather than improvement.

Inputs

  • GT - ground-truth disparity. NPARRAY, IMAGE or MASK; frame 0 of a batch.
  • src - the map being evaluated, same accepted types.
  • ROI_x, ROI_y, ROI_w, ROI_h - the region to score, as four ints. There is no sensible default here and OpenCV's is all zeros, i.e. an empty rectangle. Set them. The reason ROI is exposed at all in these nodes is that a stereo map has an invalid band along one edge, and averaging that nonsense into your score measures the matcher's geometry rather than its quality. This pack's curated CV Disparity Filter (WLS) has an auto (skip the invalid left band) mode that picks the ROI for you.

Output: one FLOAT - there's no image preview, so wire it into Inspect CV Data to read the value.

When it's the right metric

Disparity maps and depth maps with real units, compared against something you trust. Use it to answer "did the refinement step make this better or worse", "is WLS or the interpolator better on this frame", "which of these two stereo settings should I ship". It's arithmetic, it's deterministic, and it doesn't have opinions - unlike your eyes, which will prefer the smoother map every time even when the smoother map is less accurate.

When it isn't

If you're comparing two images - a before/after of a denoiser, an upscaler, a filter - MSE is a poor proxy for what you perceive, and on 8-bit data it's dominated by tiny differences in flat regions. Use the pack's CV Quality Compare instead: it scores SSIM and hands back a per-pixel quality map so you can see where the two images disagree. Same idea, perceptual metric, and it takes images (colour included) rather than disparity maps.

And be careful with normalisation. MSE between a 0–1 float map and a 0–255 uint8 map will be enormous for reasons that have nothing to do with the algorithm. Cast to a common dtype (CV Cast Array) and make sure both are the same scale before you believe a comparison.

A practical loop

Load GT  ─┐
          ├→ computeMSE  → Inspect CV Data
Load A  ──┘
Load B  ──┘ → computeMSE → Inspect CV Data

Same ROI every run, one variable changed at a time, and write the numbers down. This is the least glamorous habit in computer vision and it's the one that separates people who tune filters from people who shuffle them.

Installing it

Part of ComfyUI CV, contrib module. 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"
# restart ComfyUI

Python ≥3.12 and a recent V3-API ComfyUI.

What goes wrong

  • ROI left at zero - an empty rectangle is the default, not a no-op.
  • A wild number. Units or dtype mismatch between the two maps, or an uninitialised region of the estimate (disparity maps are full of holes and sentinel values; filter them before scoring, with something like cv2_filterSpeckles or a validity mask).
  • Missing node. ximgproc is contrib-only. All four opencv-python* distributions share one site-packages/cv2, so a non-contrib install silently turns the submodule into an empty stub. tools/repair_opencv_contrib.py --check in the pack repo reports it.
  • Expecting a preview. The output is a float, not an image. Inspect CV Data is how you see it.
Categoryimage/CV/low-level/ximgproc

Inputs (6)

NameTypeDefaultDescription
GTNPARRAY,IMAGE,MASKground truth disparity map Accepts a ComfyUI IMAGE/MASK directly (frame 0 of a batch) or an NPARRAY. Arithmetic ops (add, multiply, etc.) process the full IMAGE batch when both inputs have the same batch size.
srcNPARRAY,IMAGE,MASKdisparity map to evaluate Accepts a ComfyUI IMAGE/MASK directly (frame 0 of a batch) or an NPARRAY. Arithmetic ops (add, multiply, etc.) process the full IMAGE batch when both inputs have the same batch size.
ROI_xINT0-2147483648–2147483647Rectangle top-left corner X in pixels.
ROI_yINT0-2147483648–2147483647Rectangle top-left corner Y in pixels.
ROI_wINT00–2147483647Rectangle width in pixels (>= 0).
ROI_hINT00–2147483647Rectangle height in pixels (>= 0).

Outputs (1)

NameTypeDescription
floatFLOAT—