平均背景法提取前景

来源:互联网 发布:水泥掺量20 算法 编辑:程序博客网 时间:2024/05/02 06:13

平均背景法的基本思路是计算每个像素的平均值和标准差作为它的背景模型
四个函数:
1.cvAcc():累积图像
2.cvAbsDiff():计算一定时间内的每帧图像之差
3.cvInRange():将图像分割成前景区域和背景区域
4.cvOr():将不同的彩色通道图像中合成为一个掩模图像
这种方法只能用于背景场景中不包含运动的部分,而且光线保持不变


#include <cv.h>#include <highgui.h>#include <stdio.h>//float 3-channel iamgesIplImage *IavgF,*IdiffF,*IprevF,*IhiF,*IlowF;IplImage *Iscratch,*Iscratch2;//float 1-channel iamgesIplImage *Igray1,*Igray2,*Igray3;IplImage *Ilow1,*Ilow2,*Ilow3;IplImage *Ihi1,*Ihi2,*Ihi3;//byte  1-channel imageIplImage *Imaskt;//counts number of images learned for averaging laterfloat Icount;void  AllocateImages(IplImage* I);void  accumulateBackground(IplImage* I);void  createModelsfromStats();void  setHighThreshold(float scale);void  setLowThreshold(float scale);void  backgroundDiff(IplImage *I,IplImage * Imask);void  DeallocateImage(); int main(int argc,char** argv){     cvNamedWindow("intput",CV_WINDOW_AUTOSIZE);                    //创建输入显示窗口  cvNamedWindow("output",CV_WINDOW_AUTOSIZE);                    //创建输出显示窗口  CvCapture* capture = cvCreateFileCapture(argv[1]);          //返回一个capture指针,指向视频   IplImage* img = cvQueryFrame(capture);                          //从视频中取出的图片   IplImage* Imask =  cvCreateImage(cvGetSize(img),IPL_DEPTH_8U,1);//创建输出图片,这里不能去掉cvCreateImage(cvGetSize(Img),IPL_DEPTH_8U,1),虽然我看例程里省略了    AllocateImages(img);//给图像分配内存   /*累积图像,只取了前30帧图片*/  while(Icount<30){                                     accumulateBackground(img);                                   //调用累积图像的函数,循环30次                               img = cvQueryFrame(capture); //从视频中取出的图片cvShowImage("intput",img);    cvWaitKey(20);  }       createModelsfromStats();                                        //背景建模    while(1)  {  img = cvQueryFrame(capture);                               if(!img) break;  backgroundDiff(img,Imask);                                 //根据模型分割前景   cvShowImage("output",Imask);                               //显示图像,视频是一张一张图片连续播放的结果  cvShowImage("intput",img);  char c = cvWaitKey(33);                                    //当前帧被显示后,等待33ms再读取下一张图片  if(c==27) break;                                           //等待期间按下esc键,ASCII码为27,则循环退出  }  cvReleaseCapture(&capture);  cvDestroyWindow("output");  cvDestroyWindow("intput");  DeallocateImage();}//给需要的所有临时图像分配内存void  AllocateImages(IplImage* I){CvSize sz = cvGetSize(I);IavgF     = cvCreateImage(sz,IPL_DEPTH_32F,3);cvZero(IavgF);IdiffF    = cvCreateImage(sz,IPL_DEPTH_32F,3);cvZero(IdiffF);IprevF    = cvCreateImage(sz,IPL_DEPTH_32F,3);cvZero(IprevF);IhiF      = cvCreateImage(sz,IPL_DEPTH_32F,3);cvZero(IhiF);IlowF     = cvCreateImage(sz,IPL_DEPTH_32F,3);cvZero(IlowF);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);Icount    = 0.00001;//protect against divide by zeroIscratch  = 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);}/*积累背景图像和每一帧图像差值的绝对值/函数调用需要通道为3,深度为8的彩色图像*/void  accumulateBackground(IplImage* I){static int first = 1;cvCvtScale(I,Iscratch,1,0);//convert to float,3-channelif(!first){cvAcc(Iscratch,IavgF);cvAbsDiff(Iscratch,IprevF,Iscratch2);cvAcc(Iscratch2,IdiffF);Icount += 1.0;}first = 0;cvCopy(Iscratch,IprevF);}//计算每一个像素的均值和方差观测(平均绝对差分)void createModelsfromStats(){cvConvertScale(IavgF,IavgF,(double)(1.0/Icount));cvConvertScale(IdiffF,IdiffF,(double)(1.0/Icount));//make sure diff is always somethingcvAddS(IdiffF,cvScalar(1.0,1.0,1.0),IdiffF);setHighThreshold(7.0);setLowThreshold(6.0);}void setHighThreshold(float scale){cvConvertScale(IdiffF,Iscratch,scale);cvAdd(Iscratch,IavgF,IhiF);cvSplit(IhiF,Ihi1,Ihi2,Ihi3,0);}void setLowThreshold(float scale){cvConvertScale(IdiffF,Iscratch,scale);cvAdd(IavgF,Iscratch,IlowF);cvSplit(IlowF,Ilow1,Ilow2,Ilow3,0);}//图像分割void backgroundDiff(IplImage *I,IplImage *Imask){cvConvertScale(I,Iscratch,1,0);//to floatcvSplit(Iscratch,Igray1,Igray2,Igray3,0);//channel-1cvInRange(Igray1,Ilow1,Ihi1,Imask);//channel-2cvInRange(Igray2,Ilow2,Ihi2,Imaskt);cvOr(Imask,Imaskt,Imask);//channel-3cvInRange(Igray3,Ilow3,Ihi3,Imaskt);cvOr(Imask,Imaskt,Imask);cvSubRS(Imask,cvScalar(255),Imask);}//内存释放void DeallocateImage(){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);}



1 0