混合高斯背景建模原理及实现

简介: 前些日子一直在忙答辩的事情,毕业后去了华为,图像处理什么的都派不上用场了。打算分3-4篇文章,把我研究生阶段学过的常用算法为大家和4107的师弟师妹们分享下。

前些日子一直在忙答辩的事情,毕业后去了华为,图像处理什么的都派不上用场了。打算分3-4篇文章,把我研究生阶段学过的常用算法为大家和4107的师弟师妹们分享下。本次介绍混合高斯背景建模算法,还是老样子,首先介绍理论部分,然后给出代码,最后实验贴图。

一、理论

混合高斯背景建模是基于像素样本统计信息的背景表示方法,利用像素在较长时间内大量样本值的概率密度等统计信息(如模式数量、每个模式的均值和标准差)表示背景,然后使用统计差分(如3σ原则)进行目标像素判断,可以对复杂动态背景进行建模,计算量较大。

在混合高斯背景模型中,认为像素之间的颜色信息互不相关,对各像素点的处理都是相互独立的。对于视频图像中的每一个像素点,其值在序列图像中的变化可看作是不断产生像素值的随机过程,即用高斯分布来描述每个像素点的颜色呈现规律【单模态(单峰),多模态(多峰)】。

对于多峰高斯分布模型,图像的每一个像素点按不同权值的多个高斯分布的叠加来建模,每种高斯分布对应一个可能产生像素点所呈现颜色的状态,各个高斯分布的权值和分布参数随时间更新。当处理彩色图像时,假定图像像素点R、G、B三色通道相互独立并具有相同的方差。对于随机变量 X的观测数据集{ x1, x2,…, xN}, xt=( rt, gt, bt)为 t时刻像素的样本,则单个采样点 xt其服从的混合高斯分布概率密度函数:


其中k为分布模式总数,η(xt,μi,t, τi,t)为t时刻第i个高斯分布,μi,t为其均值,τi,t为其协方差矩阵,δi,t为方差,I为三维单位矩阵,ωi,tt时刻第i个高斯分布的权重。

详细算法流程:




二、代码实现

// my_mixgaussians.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "cv.h"
#include "highgui.h"

int _tmain(int argc, _TCHAR* argv[])
{
	CvCapture *capture=cvCreateFileCapture("test.avi");
	IplImage *mframe,*current,*frg,*test;
	int *fg,*bg_bw,*rank_ind;
	double *w,*mean,*sd,*u_diff,*rank;
	int C,M,sd_init,i,j,k,m,rand_temp=0,rank_ind_temp=0,min_index=0,x=0,y=0,counter_frame=0;
	double D,alph,thresh,p,temp;
	CvRNG state;
	int match,height,width;
	mframe=cvQueryFrame(capture);

	frg = cvCreateImage(cvSize(mframe->width,mframe->height),IPL_DEPTH_8U,1);
	current = cvCreateImage(cvSize(mframe->width,mframe->height),IPL_DEPTH_8U,1);
	test = cvCreateImage(cvSize(mframe->width,mframe->height),IPL_DEPTH_8U,1);
	
	C = 4;						//number of gaussian components (typically 3-5)
	M = 4;						//number of background components
	sd_init = 6;				//initial standard deviation (for new components) var = 36 in paper
	alph = 0.01;				//learning rate (between 0 and 1) (from paper 0.01)
	D = 2.5;					//positive deviation threshold
	thresh = 0.25;				//foreground threshold (0.25 or 0.75 in paper)
	p = alph/(1/C);			//initial p variable (used to update mean and sd)

	height=current->height;width=current->widthStep;
	
	fg = (int *)malloc(sizeof(int)*width*height);					//foreground array
	bg_bw = (int *)malloc(sizeof(int)*width*height);				//background array
	rank = (double *)malloc(sizeof(double)*1*C);					//rank of components (w/sd)
	w = (double *)malloc(sizeof(double)*width*height*C);			//weights array
	mean = (double *)malloc(sizeof(double)*width*height*C);			//pixel means
	sd = (double *)malloc(sizeof(double)*width*height*C);			//pixel standard deviations
	u_diff = (double *)malloc(sizeof(double)*width*height*C);		//difference of each pixel from mean
	
	for (i=0;i<height;i++)
	{
		for (j=0;j<width;j++)
		{
			for(k=0;k<C;k++)
			{
				mean[i*width*C+j*C+k] = cvRandReal(&state)*255;
				w[i*width*C+j*C+k] = (double)1/C;
				sd[i*width*C+j*C+k] = sd_init;
			}
		}
	}

	while(1){
		rank_ind = (int *)malloc(sizeof(int)*C);
		cvCvtColor(mframe,current,CV_BGR2GRAY);
		// calculate difference of pixel values from mean
		for (i=0;i<height;i++)
		{
			for (j=0;j<width;j++)
			{
				for (m=0;m<C;m++)
				{
					u_diff[i*width*C+j*C+m] = abs((uchar)current->imageData[i*width+j]-mean[i*width*C+j*C+m]);
				}
			}
		}
		//update gaussian components for each pixel
		for (i=0;i<height;i++)
		{
			for (j=0;j<width;j++)
			{
				match = 0;
				temp = 0;
				for(k=0;k<C;k++)
				{
					if (abs(u_diff[i*width*C+j*C+k]) <= D*sd[i*width*C+j*C+k])      //pixel matches component
					{
						 match = 1;													// variable to signal component match
						 
						 //update weights, mean, sd, p
						 w[i*width*C+j*C+k] = (1-alph)*w[i*width*C+j*C+k] + alph;
						 p = alph/w[i*width*C+j*C+k];                  
						 mean[i*width*C+j*C+k] = (1-p)*mean[i*width*C+j*C+k] + p*(uchar)current->imageData[i*width+j];
						 sd[i*width*C+j*C+k] =sqrt((1-p)*(sd[i*width*C+j*C+k]*sd[i*width*C+j*C+k]) + p*(pow((uchar)current->imageData[i*width+j] - mean[i*width*C+j*C+k],2)));
					}else{
						w[i*width*C+j*C+k] = (1-alph)*w[i*width*C+j*C+k];			// weight slighly decreases
					}
					temp += w[i*width*C+j*C+k];
				}
				
				for(k=0;k<C;k++)
				{
					w[i*width*C+j*C+k] = w[i*width*C+j*C+k]/temp;
				}
			
				temp = w[i*width*C+j*C];
				bg_bw[i*width+j] = 0;
				for (k=0;k<C;k++)
				{
					bg_bw[i*width+j] = bg_bw[i*width+j] + mean[i*width*C+j*C+k]*w[i*width*C+j*C+k];
					if (w[i*width*C+j*C+k]<=temp)
					{
						min_index = k;
						temp = w[i*width*C+j*C+k];
					}
					rank_ind[k] = k;
				}

				test->imageData[i*width+j] = (uchar)bg_bw[i*width+j];

				//if no components match, create new component
				if (match == 0)
				{
					mean[i*width*C+j*C+min_index] = (uchar)current->imageData[i*width+j];
					//printf("%d ",(uchar)bg->imageData[i*width+j]);
					sd[i*width*C+j*C+min_index] = sd_init;
				}
				for (k=0;k<C;k++)
				{
					rank[k] = w[i*width*C+j*C+k]/sd[i*width*C+j*C+k];
					//printf("%f ",w[i*width*C+j*C+k]);
				}

				//sort rank values
				for (k=1;k<C;k++)
				{
					for (m=0;m<k;m++)
					{
						if (rank[k] > rank[m])
						{
							//swap max values
							rand_temp = rank[m];
							rank[m] = rank[k];
							rank[k] = rand_temp;

							//swap max index values
							rank_ind_temp = rank_ind[m];
							rank_ind[m] = rank_ind[k];
							rank_ind[k] = rank_ind_temp;
						}
					}
				}

				//calculate foreground
				match = 0;k = 0;
				//frg->imageData[i*width+j]=0;
				while ((match == 0)&&(k<M)){
					if (w[i*width*C+j*C+rank_ind[k]] >= thresh)
						if (abs(u_diff[i*width*C+j*C+rank_ind[k]]) <= D*sd[i*width*C+j*C+rank_ind[k]]){
							frg->imageData[i*width+j] = 0;
							match = 1;
						}
						else
							frg->imageData[i*width+j] = (uchar)current->imageData[i*width+j];     
					k = k+1;
				}
			}
		}		

		mframe = cvQueryFrame(capture);
		cvShowImage("fore",frg);
		cvShowImage("back",test);
		char s=cvWaitKey(33);
		if(s==27) break;
		free(rank_ind);
	}
	
	free(fg);free(w);free(mean);free(sd);free(u_diff);free(rank);
	cvNamedWindow("back",0);
	cvNamedWindow("fore",0);
	cvReleaseCapture(&capture);
	cvDestroyWindow("fore");
	cvDestroyWindow("back");
	return 0;
}

实验结果:

前景:


背景:



目录
相关文章
|
机器学习/深度学习 传感器 算法
数字图像处理实验(五)|图像复原{逆滤波和伪逆滤波、维纳滤波deconvwnr、大气湍流扰动模型、运动模糊处理fspecial}(附matlab实验代码和截图)
数字图像处理实验(五)|图像复原{逆滤波和伪逆滤波、维纳滤波deconvwnr、大气湍流扰动模型、运动模糊处理fspecial}(附matlab实验代码和截图)
597 0
数字图像处理实验(五)|图像复原{逆滤波和伪逆滤波、维纳滤波deconvwnr、大气湍流扰动模型、运动模糊处理fspecial}(附matlab实验代码和截图)
|
4天前
用图直观上理解梯度算子(一阶)与拉普拉斯算子(二阶)的区别,线检测与边缘检测的区别
用图直观上理解梯度算子(一阶)与拉普拉斯算子(二阶)的区别,线检测与边缘检测的区别
62 1
|
9月前
|
计算机视觉
【图像去噪】基于混合自适应(EM 自适应)实现自适应图像去噪研究(Matlab代码实现)
【图像去噪】基于混合自适应(EM 自适应)实现自适应图像去噪研究(Matlab代码实现)
|
9月前
|
机器学习/深度学习 传感器 算法
基于自适应双残差反馈控制变形矢量场迭代反演附matlab代码
基于自适应双残差反馈控制变形矢量场迭代反演附matlab代码
|
12月前
|
机器学习/深度学习 固态存储
姿态估计 | 基于CenterNet究竟还可以做多少事情?AdaptivePose便是经典!(二)
姿态估计 | 基于CenterNet究竟还可以做多少事情?AdaptivePose便是经典!(二)
50 0
|
12月前
|
机器学习/深度学习 编解码 监控
姿态估计 | 基于CenterNet究竟还可以做多少事情?AdaptivePose便是经典!(一)
姿态估计 | 基于CenterNet究竟还可以做多少事情?AdaptivePose便是经典!(一)
92 0
|
机器学习/深度学习 传感器 人工智能
【图像去噪】基于自适应全变分算法实现图像去噪附matlab代码
【图像去噪】基于自适应全变分算法实现图像去噪附matlab代码
|
编解码 计算机视觉 C++
【C++】高斯金字塔和拉普拉斯金字塔原理和实现(三)
图像中各个像素与其相邻像素之间的有很强的相关性,包含的信息也十分丰富,目标的尺寸有大有小,对比度有强有弱,此时就需要一个“显微镜”或者“望远镜”-----多尺度图像技术。它可以在不同分辨率下观察目标的特征进而进行处理。
1247 0
【C++】高斯金字塔和拉普拉斯金字塔原理和实现(三)
|
编解码 计算机视觉 C++
【C++】高斯金字塔和拉普拉斯金字塔原理和实现(一)
图像中各个像素与其相邻像素之间的有很强的相关性,包含的信息也十分丰富,目标的尺寸有大有小,对比度有强有弱,此时就需要一个“显微镜”或者“望远镜”-----多尺度图像技术。它可以在不同分辨率下观察目标的特征进而进行处理。
148 0
【C++】高斯金字塔和拉普拉斯金字塔原理和实现(一)
|
编解码 C++ 计算机视觉
【C++】高斯金字塔和拉普拉斯金字塔原理和实现(二)
图像中各个像素与其相邻像素之间的有很强的相关性,包含的信息也十分丰富,目标的尺寸有大有小,对比度有强有弱,此时就需要一个“显微镜”或者“望远镜”-----多尺度图像技术。它可以在不同分辨率下观察目标的特征进而进行处理。
207 0
【C++】高斯金字塔和拉普拉斯金字塔原理和实现(二)