Nodes/comfyui_cv/CV Local Linear Fit (per pixel)
ComfyUI Node

CV Local Linear Fit (per pixel)

Fits 'target ~ slope * predictor + intercept' inside a window around EVERY pixel and returns the fit as image sized maps. This is the local counterpart of 'Photometric Align (Gain/Bias)': one global gain there, a gain per pixel here. It is also the algebra behind guided filtering, shading/flat-field estimation and clean plate matting - a matte falls straight out of it, because a shot over a known background obeys C = (1-a) B + a F, so a regression of the shot on the plate has slope 1-a and intercept a*F wherever alpha and the foreground colour are roughly constant across the window. Never raises on flat data: where the predictor does not vary there is nothing to fit, and the slope comes back 0 with the intercept holding the local mean (check 'predictor_sigma' to find those pixels).

By bmad4ever·Created 3 months ago·Updated 2 days ago· 0
CV Local Linear Fit (per pixel)
  • target
  • predictor
  • slope
  • intercept
  • predictor_sigma
  • residual
radius5
scopepooled (one slope for all channels)
windowbox (uniform)
ridge0
Categoryimage/CV

Inputs (6)

NameTypeDefaultDescription
targetNPARRAYThe array being explained (the 'y' of the fit). [H,W] or [H,W,C], any dtype; the maths runs in float32.
predictorNPARRAYThe array explaining it (the 'x'). Same size and channel count as the target.
radiusINT51–200Half-size of the window, in pixels: the fit at each pixel uses a (2*radius+1) square around it. Bigger windows average out noise but assume the relationship holds over a wider area - for matting that means the alpha edge gets smeared, so keep it just large enough to contain some predictor texture.
scopeCOMBOpooled (one slope for all channels)Pooled fits ONE slope per pixel using every channel as evidence (the right choice when the slope is a physical scalar, e.g. 1-alpha in matting, and it is far more stable). Per channel fits B, G and R independently, which also captures a colour shift.
windowCOMBObox (uniform)Shape of the averaging window. Box weights every pixel in the square equally; gaussian (sigma = radius/2) weights the centre more, which makes the maps smoother and their edges less blocky.
ridgeoptFLOAT00–1000000Added to the predictor variance before dividing, in SQUARED input units (so ~1.0 for the sensor noise of an 8-bit image). It pulls the slope toward 0 where the predictor barely varies instead of letting noise decide it.

Outputs (4)

NameTypeDescription
slopeNPARRAYfloat32 [H,W] (pooled) or [H,W,C] (per channel). 0 where the predictor is flat.
interceptNPARRAYfloat32, same shape as the inputs: local_mean(target) - slope * local_mean(predictor), i.e. the target's value where the predictor would be 0.
predictor_sigmaNPARRAYfloat32 [H,W] (pooled: sqrt of the summed per-channel variance) or [H,W,C]. How much the predictor varies inside the window - the confidence of the slope, in input units. A flat region reads ~0 and its slope means nothing.
residualNPARRAYfloat32: local standard deviation of the target AROUND the fitted line, in input units. Large where a single line cannot describe the window (e.g. an alpha edge crossing it).