平均背景法提取前景

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


#include <cv.h>
#include <highgui.h>
#include <stdio.h>
//float 3-channel iamges
IplImage *IavgF,*IdiffF,*IprevF,*IhiF,*IlowF;

IplImage *Iscratch,*Iscratch2;

//float 1-channel iamges
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;

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 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);
}
/*积累背景图像和每一帧图像差值的绝对值
/函数调用需要通道为3,深度为8的彩色图像
*/
void  accumulateBackground(IplImage* I){
	static int first = 1;
	cvCvtScale(I,Iscratch,1,0);//convert to float,3-channel
	if(!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 something
	cvAddS(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 float
	cvSplit(Iscratch,Igray1,Igray2,Igray3,0);
	//channel-1
	cvInRange(Igray1,Ilow1,Ihi1,Imask);
	//channel-2
	cvInRange(Igray2,Ilow2,Ihi2,Imaskt);
	cvOr(Imask,Imaskt,Imask);
	//channel-3
	cvInRange(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
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值