Background Subtraction

Jun 7, 2009 at 5:49am
I really need help in the codes below? If anyone knows pls help me out! I don't understand that why we need to set the high threshold to 7.0 and low threshold to 6.0? I have read up that if the pixel values fall within the range of low and high threshold, the pixel is consider as background! And why we need to use cvNorm? It will be best if you can briefly explain the whole codes for me! Sorry for the trouble... Thanks Thanks!

The codes:

#include “stdafx.h”
#include “cv.h”
#include “cxcore.h”
#include “highgui.h”

//Global storage
//
//Float, 3 channels
//
IplImage *IavgF, *IdiffF, *IprevF, *IhiF, *IlowF;
IplImage *Iscratch, *Iscratch2;

//Float, 1-channel images
//
IplImage *Igray1, *Igray2, *Igray3;
IplImage *Ilow1, *Ilow2, *Ilow3;
IplImage *Ihi1, *Ihi2, *Ihi3;

//Byte, 1-channel image
//
IplImage *Imaskt;

//Counts number of images learned for averaging later.
//
float Icount;

// I is just sample image for allocation purposes
// (passed in for sizing)
//
void AllocateImages( IplImage* I)
{
CvSize sz = cvGetSize(I);

IavgF = cvCreateImage(sz, IPL_DEPTH_32F, 3); //default BGR
IdiffF = cvCreateImage(sz, IPL_DEPTH_32F, 3);
IprevF = cvCreateImage(sz, IPL_DEPTH_32F, 3);
IhiF = cvCreateImage(sz, IPL_DEPTH_32F, 3);
IlowF = cvCreateImage(sz, IPL_DEPTH_32F, 3);

Ilow1 = cvCreateImage(sz, IPL_DEPTH_32F, 1);
Ilow2 = cvCreateImage(sz, IPL_DEPTH_32F, 1);
Ilow3 = cvCreateImage(sz, IPL_DEPTH_32F, 1);

Ihi1 = cvCreateImage(sz, IPL_DEPTH_32F, 1);
Ihi2 = cvCreateImage(sz, IPL_DEPTH_32F, 1);
Ihi3 = cvCreateImage(sz, IPL_DEPTH_32F, 1);

cvZero(IavgF); //cvZero(array) is equivalent to cvSet(array,cvScalarAll(0),0),
cvZero(IdiffF); //in case of sparse arrays all the elements are removed.
cvZero(IprevF);
cvZero(IhiF);
cvZero(IlowF);

Icount = 0.0001; //Protect against divide by zero

Iscratch = cvCreateImage(sz, IPL_DEPTH_32F, 3);
Iscratch2 = cvCreateImage(sz, IPL_DEPTH_32F, 3);

Igray1 = cvCreateImage(sz, IPL_DEPTH_32F, 1);
Igray2 = cvCreateImage(sz, IPL_DEPTH_32F, 1);
Igray3 = cvCreateImage(sz, IPL_DEPTH_32F, 1);

Imaskt = cvCreateImage(sz, IPL_DEPTH_8U, 1);

cvZero(Iscratch);
cvZero(Iscratch2);
}

//Learn the background ststistics for one more frame
// I is a color sample of the background, 3 channel, 8u
//
void accumlateBackground(IplImage *I)
{
static int first = 1; //only first time 1. rest are 0. Not thread safe
cvCvtScale( I, Iscratch, 1, 0); //convert the 8-bit per channel, 3 color channel image to floating point channel image
if(!first){
cvAcc(Iscratch, IavgF); //accumulates the background image
cvAbsDiff(Iscratch, IprevF, Iscratch2);
cvAcc(Iscratch2, IdiffF); //accumulates the absolute values of frame to frame image differences
Icount+=1.0; //every accumlate add to global Icount
}
first = 0;
cvCopy(Iscratch, IprevF); // first image frame, copy Iscratch to IprevF
}

void PrintOut(IplImage* I)
{
int nl= I->height; // number of lines
int nc= I->width * I->nChannels; // total number of element per line
int step = I->widthStep;

// get the pointer to the image buffer
unsigned char *data= reinterpret_cast(I->imageData);

for (int i=1; i<2/*nl*/; i++) {

for (int j=0; j<1/*nc*/; j+= I->nChannels) {
printf("%dn", data[j]); //3 channels
printf("%dn", data[j+1]);
printf("%dn", data[j+2]);
}

data+= step;
}

}

void setHighThreshold( float scale ) //7.0 times
{
cvConvertScale( IdiffF, Iscratch, scale); //can convert 8bit images to 32bit etc, with additional scaling and shifting of image values
cvAdd(Iscratch, IavgF, IhiF);
cvSplit(IhiF, Ihi1, Ihi2, Ihi3, 0);
}

void setLowThreshold( float scale )
{
cvConvertScale( IdiffF, Iscratch, scale);
cvAdd(Iscratch, IavgF, IlowF);
cvSplit(IlowF, Ilow1, Ilow2, Ilow3, 0); //split to 3 channels
}

void createModelsfromStats(){ //computes the mean and standard deviation
cvConvertScale(IavgF, IavgF, (double)(1.0/Icount));
printf("%fn", (double)(1.0/Icount));
cvConvertScale(IdiffF, IdiffF, (double)(1.0/Icount));

//Make sure diff is always something
//cvScalar -> A container for 1-,2-,3- or 4-tuples of numbers
//
cvAddS(IdiffF, cvScalar(1.0, 1.0, 1.0), IdiffF); //Computes sum of array and scalar
//The function cvAddS adds scalar value to every element in the source array src1 and stores the result in dst
PrintOut(IdiffF);
setHighThreshold(7.0); //if is within the threshold then it is a background!
PrintOut(IdiffF);
setLowThreshold(6.0);
}

// Create a binary: 0-255 mask where 255 means foreground pixel
//I Input image, 3-channel, 8u
//Imask Mask image to be created, 1-channel 8u
//
void backgroundDiff( IplImage *I, IplImage *Imask ){
cvCvtScale( I, Iscratch, 1, 0); // to float
cvSplit( Iscratch, Igray1, Igray2, Igray3, 0 );

// channel 1
//
cvInRange( Igray1, Ilow1, Ihi1, Imask ); // in range Imask->255, otherwise 0

// channel 2
//
cvInRange( Igray2, Ilow2, Ihi2, Imaskt );
cvOr( Imask, Imaskt, Imask );

// channel 3
//
cvInRange( Igray3, Ilow3, Ihi3, Imaskt ); //background in range!
cvOr( Imask, Imaskt, Imask );

//Finally, invert the result
//
//cvSubRS(Imask, cvScalar(255), Imask);
}

void DeallocateImages()
{
cvReleaseImage( &IavgF );
cvReleaseImage( &IdiffF );
cvReleaseImage( &IprevF );
cvReleaseImage( &IhiF );
cvReleaseImage( &IlowF );
cvReleaseImage( &Ilow1 );
cvReleaseImage( &Ilow2 );
cvReleaseImage( &Ilow3 );
cvReleaseImage( &Ihi1 );
cvReleaseImage( &Ihi2 );
cvReleaseImage( &Ihi3 );
cvReleaseImage( &Iscratch );
cvReleaseImage( &Iscratch2 );
cvReleaseImage( &Igray1 );
cvReleaseImage( &Igray2 );
cvReleaseImage( &Igray3 );
cvReleaseImage( &Imaskt );
}

int _tmain(int argc, _TCHAR* argv[])
{
cvNamedWindow( “Background Averaging”, CV_WINDOW_AUTOSIZE );
CvCapture* capture = cvCreateFileCapture( “pellican.avi” );
IplImage *frame, *mask1, *mask3;

int frameCount = 0;
while(1) {
frameCount++;
frame = cvQueryFrame( capture );
if( !frame ) while(1);//break;
CvSize sz = cvGetSize( frame );
mask1 = cvCreateImage( sz, IPL_DEPTH_8U, 1 );
mask3 = cvCreateImage( sz, IPL_DEPTH_8U, 3 );
if(frameCount == 1)
AllocateImages( frame ); //reference frame


if( frameCount < 30 )
{ //for 30-1,000 frames, sometimes taking just a few frames from each second or sometimes taking all the available frames
accumlateBackground( frame );
}
else if( frameCount == 30 ) //enough frames to calculate the statistical of the background model (computes the mean and standard deviation)
{
createModelsfromStats();
}
else{
backgroundDiff( frame, mask1 ); //Imask ->255 means in range!

cvCvtColor(mask1,mask3,CV_GRAY2BGR); //change Imask to bgr mask = 255->white range!
double norm = cvNorm( mask3, mask3, CV_C, 0);//Calculates absolute difference norm [[max abs(arr1 - arr2)]] // get the color of the image!
printf("The norm result: %fn”, norm);
cvThreshold(mask3, mask3, 100, 1, CV_THRESH_BINARY);//set the big different as 1->background and 100 as foreground
//any values above 100 is set to white else is black //set it to black!
cvMul( frame, mask3, frame, 1.0 ); //multiplication of two array
cvShowImage( “Background Averaging”, frame ); //show the frame, the frame is bg color black

}

char c = cvWaitKey(33);
if( c == 27 ) break;
}
cvReleaseCapture( &capture );
cvDestroyWindow( “Background Averaging” );
DeallocateImages();
}
Jun 9, 2009 at 6:05pm
If you used Code tag's then maybe your code would be slightly readable
Topic archived. No new replies allowed.