This tutorial explain the basics of background substraction. First of all we need define what is a background and what is a foreground.

We consider a background the pixels of image without motion. And a foreground the pixels with motion. Then the simplest background model assume each background pixel his brightness varies independently with normal distribution. Then we can calculate our statistical model of background by accumulating several dozens of frames and his squares, this is:

$$ \displaystyle{S(x,y)=\sum_{f=1}^N p(x,y)}$$
$$ \displaystyle{Sq(x,y)=\sum_{f=1}^N p(x,y)^2}$$

Where:

$$\displaystyle{f=frame; N= total frames}$$

Then the average is:

$$ \displaystyle{M(x,y)=\frac{S(x,y)}{N}}$$

BG substraction mean pixelBG substraction mean pixel

And need the standar derivation for our statistical model:

$$ \displaystyle{\sigma(x,y)=\sqrt{ \frac{Sq(x,y)}{N} - M(x,y)^2 }}$$

Then, when we have our statistical background model, we can give a image and divide it in background and foreground, the pixels that are in foreground are the P(x,y) that met this condition:

$$ \displaystyle{ | M(x,y) - P(x,y) | \ge \lambda \sigma(x,y) }$$

For optimize a litle the operations we can use this for evaluate the condition:

$$ \displaystyle{ {| M(x,y) - P(x,y) |}^2 \ge {(\lambda \sigma(x,y))}^2 }$$

$$ \displaystyle{ {| M(x,y) - P(x,y) |}^2 \ge \lambda^2 \sigma(x,y)^2 }$$

Where $ \displaystyle{ sigma(x,y)^2 }$ is

$$ \displaystyle{\sigma(x,y)^2 = \frac{Sq(x,y)}{N} - M(x,y)^2 }$$

And $ \displaystyle{ \lambda }$ is a constant or variable and we can set it to 3, it is the well-known "three sigmas" rule.

BG substraction Standar derivation compareBG substraction Standar derivation compare

Ok, then we now have the theory, then, we go to implement it.

To develop it opencv give us some functions, cvAcc and cvSquareAcc

cvAcc(frame,acc,NULL);
cvSquareAcc(frame, sqacc, NULL);
N++;
cvConvertScale(acc, M, (double)(1.0/N), 0);
cvConvertScale(sqacc, sqaccM, (double)(1.0/N),0);
cvMul( M, M, M2, 1 );
cvSub( sqaccM, M2, sig2, NULL);//The sig is sig2

//For detect FG Condition
cvConvertScale(sig2, lambda_sig2, (double)9, 0);
cvSub(M, frame, leftCondition, NULL);
cvMul(leftCond, leftCond, leftCond2, NULL);

//Compare leftCondition > lambda_sig2
//to detect foreground.

Results:

Note:
This code is an example and it's no completed.
In next tutorial a more advanced background substranction.