Files
tooll3--t3/Operators/Lib/Assets/shaders/img/analyze/remove-static-background-cs1-learning.hlsl
2026-07-13 13:13:17 +08:00

91 lines
2.5 KiB
HLSL

// Pass1_BackgroundAndMask.hlsl
// Corrected version: separates learning-space and detection-space z
// ZScale affects detection ONLY, never learning.
Texture2D<float4> InputFrame : register(t0);
RWTexture2D<float4> BgModel : register(u0); // rgb = mean, a = spread
RWTexture2D<float> MaskRaw : register(u1);
cbuffer Params : register(b0)
{
float MeanRate; // ~0.002 .. 0.02
float SpreadUpRate; // ~0.05
float SpreadDownRate; // ~0.001
float MinSpread; // ~0.005 (in 0..1 RGB space)
float ZScale; // detection sensitivity only (>= 0)
float BrightSupp; // 0..1, e.g. 0.35 (projector suppression)
float BgGateLo; // learning gate low (zLearn)
float BgGateHi; // learning gate high (zLearn)
float UseChroma; // 0 or 1
float ChromaWeight; // e.g. 0.5
float IsTraining; // 0 = live, 1 = training
float Reset;
};
static const float3 LUMA = float3(0.2126, 0.7152, 0.0722);
[numthreads(16, 16, 1)] void main(uint3 id : SV_DispatchThreadID)
{
int2 p = int2(id.xy);
float3 C = InputFrame.Load(int3(p, 0)).rgb;
float4 state = BgModel[p];
float3 M = state.rgb;
float S = max(state.a, MinSpread);
float3 d = C - M;
// Signed luminance delta
float lumDiff = dot(d, LUMA);
float absLum = abs(lumDiff);
// Optional chroma delta
float chroma = 0.0;
if (UseChroma > 0.5)
{
float3 Cn = normalize(max(C, 1e-5));
float3 Mn = normalize(max(M, 1e-5));
chroma = length(Cn - Mn);
}
// Base distance (semantic difference signal)
float dist = absLum + ChromaWeight * chroma;
// Brightening suppression (affects both learning + detection semantics)
float brightBias = (lumDiff > 0.0) ? BrightSupp : 1.0;
dist *= brightBias;
float zLearn = dist / S;
float bgWeight = 1.0 - smoothstep(BgGateLo, BgGateHi, zLearn);
bgWeight = lerp(bgWeight, 1.0, IsTraining);
// Update mean
M += d * (MeanRate * bgWeight);
// Update spread (asymmetric)
float target = max(dist, MinSpread);
float rate = (target > S) ? SpreadUpRate : SpreadDownRate;
S += (target - S) * (rate * bgWeight);
// DETECTION SPACE
float zDetect = zLearn * max(ZScale, 0.0);
// Smooth foreground confidence (Gaussian-like)
float bgProb = 1.0 / (1.0 + zDetect * zDetect);
float fg = saturate(1.0 - bgProb);
// -------------------------------------------------
if (Reset)
{
S = 0;
}
BgModel[p] = float4(M, S);
MaskRaw[p] = fg;
}