前景检测算法GMM

1.参考

http://www.cnblogs.com/tornadomeet/archive/2012/06/02/2531565.html

http://www.doc88.com/p-7435437562598.html


2.没有形态学处理的代码

#include "cv.h"
#include "highgui.h"
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <stdio.h>
#include <iostream>
 using namespace cv;
 using namespace std;

 const char* openfile="C:\\Users\\dell\\Desktop\\hall_night.avi";

#define  GMM_MAX_COMPONT  5
#define  GMM_LEARN_ALPHA1  0.01    //该学习率越大的话,学习速度太快,效果不好
#define  GMM_LEARN_ALPHA2  0.005   //采用前20帧训练GMM时,学习速率较大。建立好后学习速率改小
#define  GMM_THRESHOD_SUMW  0.7    //如果取值太大了的话,则更多树的部分都被检测出来了
#define  END_FRAME 100 

Mat w[GMM_MAX_COMPONT];
Mat u[GMM_MAX_COMPONT];
Mat sigma[GMM_MAX_COMPONT];
Mat w_sigma[GMM_MAX_COMPONT];      //用来给高斯模型排序的量
Mat fit_num,gmask;

bool pause=false;

//gmm模型初始化函数声明
 void gmm_init(Mat img); 

 //gmm第一帧初始化函数声明
 void gmm_firstframe_init(Mat img);

 //高斯模型更新函数声明,并且将高斯模型按w/sigma从大到小排序
 void gmm_renew(Mat img,float GMM_LEARN_ALPHA);

 //对输入图像每个像素gmm选择合适的个数函数声明
 void gmm_fit_num(Mat img);

//gmm测试函数的实现
 void gmm_test(Mat img);

 void main()
 {
	 cvNamedWindow("1",CV_WINDOW_AUTOSIZE);
	 cvNamedWindow("2",CV_WINDOW_AUTOSIZE);
	 CvCapture* capture=cvCreateFileCapture(openfile);
	 IplImage* frame;
	 int t=0;
	 while(1)
	 {
		frame=cvQueryFrame(capture);   //每3帧提取一次背景
		frame=cvQueryFrame(capture);
		frame=cvQueryFrame(capture);
		if(!frame)break;
		t=t+1;
		IplImage *frame_gray=cvCreateImage(cvGetSize(frame),IPL_DEPTH_8U,1);
		cvCvtColor(frame,frame_gray,CV_BGR2GRAY);
		cvShowImage("1",frame_gray);
		Mat img=Mat(frame_gray);
		if(t==1){
			gmm_init(img);
			gmm_firstframe_init(img);
		}
		else if(t<END_FRAME){                                                  //注意这里没有=
			float GMM_LEARN_ALPHA=GMM_LEARN_ALPHA1;
			gmm_renew(img,GMM_LEARN_ALPHA);
			gmm_fit_num(img);
		    gmm_test(img);
			imshow("2",gmask);
		}
		else{
			float GMM_LEARN_ALPHA=GMM_LEARN_ALPHA2;
			gmm_renew(img,GMM_LEARN_ALPHA);
			gmm_fit_num(img);
			gmm_test(img);
			imshow("2",gmask);	
		}
		char  c = cvWaitKey(33);
		if(c==27)break;
	 }	
 }

void gmm_init(Mat img){
	for(int j=0;j<GMM_MAX_COMPONT;j++)
	{
		w[j]=Mat(img.size(),CV_32FC1,0.0);
		u[j]=Mat(img.size(),CV_8UC1,-1);             //为什么如果这个地方赋值为0就会出错??
		sigma[j]=Mat(img.size(),CV_32FC1,0.0);
		w_sigma[j]=Mat(img.size(),CV_32FC1,0.0);
	}
}

void gmm_firstframe_init(Mat img){
	for(int m=0;m<img.rows;m++)
		for(int n=0;n<img.cols;n++)
		{
			w[0].at<float>(m,n)=1.0;
			u[0].at<unsigned char>(m,n)=img.at<unsigned char>(m,n);
			sigma[0].at<float>(m,n)=15.0;
			for(int k=1;k<GMM_MAX_COMPONT;k++)
			{
				w[k].at<float>(m,n)=0.0;
				u[k].at<unsigned char>(m,n)=-1;
				sigma[k].at<float>(m,n)=15.0;
			}
		}
}

void gmm_renew(Mat img,float GMM_LEARN_ALPHA){
	for(int m=0;m<img.rows;m++)
		for(int n=0;n<img.cols;n++)
		{
			pause=false;
			int k=0;
			for(k=0;k<GMM_MAX_COMPONT;k++)
		{
			//如果有匹配的高斯模型则将该高斯模型按下面方法来更新,对于不匹配的高斯模型,其权值会变化。说明每个高斯组件在3*sigma内不会相交。
			if((double)(abs(img.at<unsigned char>(m,n)-u[k].at<unsigned char>(m,n))*abs(img.at<unsigned char>(m,n)-u[k].at<unsigned char>(m,n)))<9*sigma[k].at<float>(m,n))    //
			{
				pause=true;     //如果有匹配成功的,则成功匹配的标志标记为1
				w[k].at<float>(m,n)=(1-GMM_LEARN_ALPHA)*w[k].at<float>(m,n)+GMM_LEARN_ALPHA;
				u[k].at<unsigned char>(m,n)=u[k].at<unsigned char>(m,n)+GMM_LEARN_ALPHA*(img.at<unsigned char>(m,n)-u[k].at<unsigned char>(m,n))/w[k].at<float>(m,n);
				sigma[k].at<float>(m,n)=sigma[k].at<float>(m,n)+(GMM_LEARN_ALPHA/w[k].at<float>(m,n))*((img.at<unsigned char>(m,n)-u[k].at<unsigned char>(m,n))*(img.at<unsigned char>(m,n)-u[k].at<unsigned char>(m,n))-sigma[k].at<float>(m,n));
			}
			else
			{
				w[k].at<float>(m,n)=(1-GMM_LEARN_ALPHA)*w[k].at<float>(m,n);
			}
			w_sigma[k].at<float>(m,n)=w[k].at<float>(m,n)/sigma[k].at<float>(m,n);
		}
			//把高斯模型按w/sigma从大到小进行排序
			for(int i=1;i<GMM_MAX_COMPONT;i++)                //插入排序
				{
					if(w_sigma[i-1].at<float>(m,n)<w_sigma[i].at<float>(m,n))
					{
						float temp1=w_sigma[i].at<float>(m,n);
						float temp2=w[i].at<float>(m,n);
						unsigned char temp3=u[i].at<unsigned char>(m,n);
						float temp4=sigma[i].at<float>(m,n);
						int j=i;
						while(j>0&&w_sigma[j-1].at<float>(m,n)<temp1)
						{
							w_sigma[j].at<float>(m,n)=w_sigma[j-1].at<float>(m,n);
							w[j].at<float>(m,n)=w[j-1].at<float>(m,n);
							u[j].at<unsigned char>(m,n)=u[j-1].at<unsigned char>(m,n);
							sigma[j].at<float>(m,n)=sigma[j-1].at<float>(m,n);
							j--;
						}
						w_sigma[j].at<float>(m,n)=temp1;
						w[j].at<float>(m,n)=temp2;
						u[j].at<unsigned char>(m,n)=temp3;
						sigma[j].at<float>(m,n)=temp4;
					}
				}
			//当有新值出现的时候,如果组件个数小于 GMM_MAX_COMPONENT ,则新添加一个组件,新采样值作为均值,赋予较大方差 较小权值
			if(k==GMM_MAX_COMPONT&&pause==false&&u[k-1].at<unsigned char>(m,n)==0)
			{
				int c=0;
				for(;c<GMM_MAX_COMPONT;c++)
				{
					if(u[c].at<unsigned char>(m,n)==0)
					{
						w[c].at<float>(m,n)=GMM_LEARN_ALPHA;
						u[c].at<unsigned char>(m,n)=img.at<unsigned char>(m,n);
						sigma[c].at<float>(m,n)=15.0;

						//归一化权重,使其总和为1
						int d=0;
						for(;d<GMM_MAX_COMPONT&&d!=c;d++)
						{
							w[d].at<float>(m,n) *=(1-GMM_LEARN_ALPHA);
						}
						break;
					}
				}
			}
			//如果GMM_MAX_COMPONENT 都赋有值 ,则用新的高斯组件 代替 权值最弱的高斯组件,权值不变,只更新均值和方差
			else if(k==GMM_MAX_COMPONT&&pause==false&&u[k-1].at<unsigned char>(m,n)!=0){	
				u[k-1].at<unsigned char>(m,n)=img.at<unsigned char>(m,n);
				sigma[k-1].at<float>(m,n)=15.0;
			}
		}
}

void gmm_fit_num(Mat img){
	fit_num=Mat(img.size(),CV_8UC1,-1);
	for(int m=0;m<img.rows;m++)
		for(int n=0;n<img.cols;n++)
		{
			float sum=0;
			for(int k=0;k<GMM_MAX_COMPONT;k++)
		    {
				sum=sum+w[k].at<float>(m,n);
			    if(sum>=GMM_THRESHOD_SUMW)
				{
					fit_num.at<unsigned char>(m,n)=k+1;
					break;
				}
		    }
		}		
}

void gmm_test(Mat img){
	gmask=Mat(img.size(),CV_8UC1,-1);
	for(int m=0;m<img.rows;m++)
		for(int n=0;n<img.cols;n++)
		{
			unsigned char a=0;
			for(;a<fit_num.at<unsigned char>(m,n);a++)
			{
				if((double)(abs(img.at<unsigned char>(m,n)-u[a].at<unsigned char>(m,n))*abs(img.at<unsigned char>(m,n)-u[a].at<unsigned char>(m,n)))<(9*sigma[a].at<float>(m,n)))    //注意这里是9,另外要有double
				{
					gmask.at<unsigned char>(m,n)=0;    //背景
					break;
				}
			}
			if(a==fit_num.at<unsigned char>(m,n))
				gmask.at<unsigned char>(m,n)=255;    //前景
		}		  
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值