单分布高斯背景模型认为,对一个背景图像,特定像素亮度的分布满足高斯分布,即对背景图像B,(x,y)点的亮度满足:
IB(x,y) ~ N(u,d)
这样我们的背景模型的每个象素属性包括两个参数:平均值u 和 方差d。
对于一幅给定的图像G,如果 Exp(-(IG(x,y)-u(x,y))^2/(2*d^2)) >T,认为(x,y)是背景点,反之是前景点。
同时,随着时间的变化,背景图像也会发生缓慢的变化,这时我们要不断更新每个像素点的参数
u(t+1,x,y) = a*u(t,x,y) + (1-a)*I(x,y)
这里,a称为更新参数,表示背景变化的速度,一般情况下,我们不更新d(实验中发现更不更新d,效果变化不大)。
高斯混合模型是用于背景提取的方法,OpenCV的cvaux中cvbgfg_gaussmix.cpp文件根据文献An improved adaptive background mixture model for real-time tracking with shadow中提供的方法编写了高斯混合模型函数。其中定义了CvGaussBGModel类用于存放高斯混合模型的各个参数。我用OpenCV使用高斯混合模型函数分以下几步:
1。需要用到icvUpdateGaussianBGModel,icvReleaseGaussianBGModel两个函数,但是源程序中将这两个函数定义为内部函数,需要做一些修改,首先将cvbgfg_gaussmix.cpp中前面两个函数的声明static void CV_CDECL icvReleaseGaussianBGModel( CvGaussBGModel** bg_model )
static int CV_CDECL icvUpdateGaussianBGModel( IplImage* curr_frame, CvGaussBGModel* bg_model )两行代码注释掉。然后在cvbgfg_gaussmix.cpp中间部分两个函数的定义部分,函数头static int和static void改成CV_IMPL int 和CV_IMPL void。最后在cvaux.h文件中CVAPI(CvBGStatModel*) cvCreateGaussianBGModel( IplImage* first_frame,
CvGaussBGStatModelParams* parameters CV_DEFAULT(NULL))这句后面加上以下两句CVAPI(void) icvReleaseGaussianBGModel( CvGaussBGModel** bg_model )
CVAPI(int) icvUpdateGaussianBGModel( IplImage* curr_frame, CvGaussBGModel* bg_model )
程序修改完毕,点rebuild all,全部重新编译。
2。在程序初始化部分定义高斯混合模型参数CvGaussBGModel* bg_model=NULL在读取第一帧图像(背景图像)时,进行高斯背景建模bg_model = (CvGaussBGModel*)cvCreateGaussianBGModel(image, 0)image可以是灰度图象也可以是彩色图像。接下来再读取当前帧时,更新高斯模型
regioncount=icvUpdateGaussianBGModel(currframe, bg_model )regioncount的含义我不确定,我理解是代表背景中不同颜色区域的个数,这个参数我没有用到,它只是icvUpdateGaussianBGModel函数的返回值。
3。现在bg_model已经保存了经过高斯混合模型分类后的结果,bg_model->background保存了背景图像,bg_model->foreground保存了前景图像。
include <stdio.h>
#include <cv.h>
#include <cxcore.h>
#include <highgui.h>
#include <cvaux.h>//必须引此头文件
int main( int argc, char** argv )
{
IplImage* pFrame = NULL
IplImage* pFrImg = NULL
IplImage* pBkImg = NULL
CvCapture* pCapture = NULL
int nFrmNum = 0
cvNamedWindow(video, 1)
cvNamedWindow(background,1)
cvNamedWindow(foreground,1)
cvMoveWindow(video, 30, 0)
cvMoveWindow(background, 360, 0)
cvMoveWindow(foreground, 690, 0)
if( argc >2 )
{
fprintf(stderr, Usage: bkgrd [video_file_name]\n)
return -1
}
//打开视频文件
if(argc == 2)
if( !(pCapture = cvCaptureFromFile(argv[1])))
{
fprintf(stderr, Can not open video file %s\n, argv[1])
return -2
}
//打开摄像头
if (argc == 1)
if( !(pCapture = cvCaptureFromCAM(-1)))
{
fprintf(stderr, Can not open camera.\n)
return -2
}
//初始化高斯混合模型参数
CvGaussBGModel* bg_model=NULL
while(pFrame = cvQueryFrame( pCapture ))
{
nFrmNum++
if(nFrmNum == 1)
{
pBkImg = cvCreateImage(cvSize(pFrame->width, pFrame->height), IPL_DEPTH_8U,3)
pFrImg = cvCreateImage(cvSize(pFrame->width, pFrame->height), IPL_DEPTH_8U,1)
//高斯背景建模,pFrame可以是多通道图像也可以是单通道图像
//cvCreateGaussianBGModel函数返回值为CvBGStatModel*,
//需要强制转换成CvGaussBGModel*
bg_model = (CvGaussBGModel*)cvCreateGaussianBGModel(pFrame, 0)
}
else
{
//更新高斯模型
cvUpdateBGStatModel(pFrame, (CvBGStatModel *)bg_model )
//pFrImg为前景图像,只能为单通道
//pBkImg为背景图像,可以为单通道或与pFrame通道数相同
cvCopy(bg_model->foreground,pFrImg,0)
cvCopy(bg_model->background,pBkImg,0)
//把图像正过来
pBkImg->origin=1
pFrImg->origin=1
cvShowImage(video, pFrame)
cvShowImage(background, pBkImg)
cvShowImage(foreground, pFrImg)
if( cvWaitKey(2) >= 0 )
break
}
}
//释放高斯模型参数占用内存
cvReleaseBGStatModel((CvBGStatModel**)&bg_model)
cvDestroyWindow(video)
cvDestroyWindow(background)
cvDestroyWindow(foreground)
cvReleaseImage(&pFrImg)
cvReleaseImage(&pBkImg)
cvReleaseCapture(&pCapture)
return 0
}
% gauss.mfunction x = gauss(A,B)
%The sizes of matrices A,B are supposed to be NA x NA and NA x NB.
%This function solves Ax = B by Gauss elimination algorithm.
NA = size(A,2)[NB1,NB] = size(B)
if NB1 ~= NA, error('A and B must have compatible dimensions')end
N = NA + NBAB = [A(1:NA,1:NA) B(1:NA,1:NB)]% Augmented matrix
epss = eps*ones(NA,1)
for k = 1:NA
%Scaled Partial Pivoting at AB(k,k) by Eq.(2.2.20)
[akx,kx] = max(abs(AB(k:NA,k))./max(abs([AB(k:NA,k + 1:NA) epss(1:NA - k + 1)]'))')
if akx <eps, error('Singular matrix and No unique solution')end
mx = k + kx - 1
if kx >1 % Row change if necessary
tmp_row = AB(k,k:N)
AB(k,k:N) = AB(mx,k:N)
AB(mx,k:N) = tmp_row
end
% Gauss forward elimination
AB(k,k + 1:N) = AB(k,k+1:N)/AB(k,k)
AB(k,k) = 1%make each diagonal element one
for m = k + 1: NA
AB(m,k+1:N) = AB(m,k+1:N) - AB(m,k)*AB(k,k+1:N)%Eq.(2.2.5)
AB(m,k) = 0
end
end
%backward substitution for a upper-triangular matrix eqation
% having all the diagonal elements equal to one
x(NA,:) = AB(NA,NA+1:N)
for m = NA-1: -1:1
x(m,:) = AB(m,NA + 1:N)-AB(m,m + 1:NA)*x(m + 1:NA,:)%Eq.(2.2.7)
end
例:
>>A = [0 1 12 -1 -11 1 -1]b = [2 0 1]'
>>x = gauss(A,b)
x =
1.00000000000000
1.00000000000000
1.00000000000000
混合高斯模型:运动检测的一般方法
目前,运动物体检测的问题主要分为两类,摄像机固定和摄像机运动。对于摄像机运动的运动物体检测问题,比较著名的解决方案是光流法,通过求解偏微分方程求的图像序列的光流场,从而预测摄像机的运动状态。对于摄像机固定的情形,当然也可以用光流法,但是由于光流法的复杂性,往往难以实时的计算,所以我采用高斯背景模型。因为,在摄像机固定的情况下,背景的变化是缓慢的,而且大都是光照,风等等的影响,通过对背景建模,对一幅给定图像分离前景和背景,一般来说,前景就是运动物体,从而达到运动物体检测的目的。
单分布高斯背景模型
单分布高斯背景模型认为,对一个背景图像,特定像素亮度的分布满足高斯分布,即对背景图像B,(x,y)点的亮度满足: IB(x,y) ~ N(u,d) 这样我们的背景模型的每个象素属性包括两个参数:平均值u 和 方差d。 对于一幅给定的图像G,如果 Exp(-(IG(x,y)-u(x,y))^2/(2*d^2)) >T,认为(x,y)是背景点,反之是前景点。 同时,随着时间的变化,背景图像也会发生缓慢的变化,这时我们要不断更新每个象素点的参数 u(t+1,x,y) = a*u(t,x,y) + (1-a)*I(x,y) 这里,a称为更新参数,表示背景变化的速度,一般情况下,我们不更新d(实验中发现更不更新d,效果变化不大)。 高斯混合模型是用于背景提取的方法,OpenCV的cvaux中cvbgfg_gaussmix.cpp文件根据文献An improved adaptive background mixture model for real-time tracking with shadow中提供的方法编写了高斯混合模型函数。其中定义了CvGaussBGModel类用于存放高斯混合模型的各个参数。我用OpenCV使用高斯混合模型函数分以下几步: 1。需要用到icvUpdateGaussianBGModel,icvReleaseGaussianBGModel两个函数,但是源程序中将这两个函数定义为内部函数,需要做一些修改,首先将cvbgfg_gaussmix.cpp中前面两个函数的声明static void CV_CDECL icvReleaseGaussianBGModel( CvGaussBGModel** bg_model )static int CV_CDECL icvUpdateGaussianBGModel( IplImage* curr_frame, CvGaussBGModel* bg_model )两行代码注释掉。然后在cvbgfg_gaussmix.cpp中间部分两个函数的定义部分,函数头static int和static void改成CV_IMPL int 和CV_IMPL void。最后在cvaux.h文件中CVAPI(CvBGStatModel*) cvCreateGaussianBGModel( IplImage* first_frame, CvGaussBGStatModelParams* parameters CV_DEFAULT(NULL))这句后面加上以下两句CVAPI(void) icvReleaseGaussianBGModel( CvGaussBGModel** bg_model )CVAPI(int) icvUpdateGaussianBGModel( IplImage* curr_frame, CvGaussBGModel* bg_model )程序修改完毕,点rebuild all,全部重新编译。 2。在程序初始化部分定义高斯混合模型参数CvGaussBGModel* bg_model=NULL在读取第一帧图像(背景图像)时,进行高斯背景建模bg_model = (CvGaussBGModel*)cvCreateGaussianBGModel(image, 0)image可以是灰度图象也可以是彩色图像。接下来再读取当前帧时,更新高斯模型 regioncount=icvUpdateGaussianBGModel(currframe, bg_model )regioncount的含义我不确定,我理解是代表背景中不同颜色区域的个数,这个参数我没有用到,它只是icvUpdateGaussianBGModel函数的返回值。 3。现在bg_model已经保存了经过高斯混合模型分类后的结果,bg_model->background保存了背景图像,bg_model->foreground保存了前景图像。 include <stdio.h>#include <cv.h>#include <cxcore.h>#include <highgui.h>#include <cvaux.h>//必须引此头文件 int main( int argc, char** argv ) { IplImage* pFrame = NULLIplImage* pFrImg = NULLIplImage* pBkImg = NULLCvCapture* pCapture = NULLint nFrmNum = 0cvNamedWindow("video", 1)cvNamedWindow("background",1)cvNamedWindow("foreground",1)cvMoveWindow("video", 30, 0)cvMoveWindow("background", 360, 0)cvMoveWindow("foreground", 690, 0)if( argc >2 ) { fprintf(stderr, "Usage: bkgrd [video_file_name]\n")return -1} //打开视频文件 if(argc == 2) if( !(pCapture = cvCaptureFromFile(argv[1]))) { fprintf(stderr, "Can not open video file %s\n", argv[1])return -2} //打开摄像头 if (argc == 1) if( !(pCapture = cvCaptureFromCAM(-1))) { fprintf(stderr, "Can not open camera.\n")return -2} //初始化高斯混合模型参数 CvGaussBGModel* bg_model=NULLwhile(pFrame = cvQueryFrame( pCapture )) { nFrmNum++if(nFrmNum == 1) { pBkImg = cvCreateImage(cvSize(pFrame->width, pFrame->height), IPL_DEPTH_8U,3)pFrImg = cvCreateImage(cvSize(pFrame->width, pFrame->height), IPL_DEPTH_8U,1)//高斯背景建模,pFrame可以是多通道图像也可以是单通道图像 //cvCreateGaussianBGModel函数返回值为CvBGStatModel*, //需要强制转换成CvGaussBGModel* bg_model = (CvGaussBGModel*)cvCreateGaussianBGModel(pFrame, 0)} else { //更新高斯模型 cvUpdateBGStatModel(pFrame, (CvBGStatModel *)bg_model )//pFrImg为前景图像,只能为单通道 //pBkImg为背景图像,可以为单通道或与pFrame通道数相同 cvCopy(bg_model->foreground,pFrImg,0)cvCopy(bg_model->background,pBkImg,0)//把图像正过来 pBkImg->origin=1pFrImg->origin=1cvShowImage("video", pFrame)cvShowImage("background", pBkImg)cvShowImage("foreground", pFrImg)if( cvWaitKey(2) >= 0 ) break} } //释放高斯模型参数占用内存 cvReleaseBGStatModel((CvBGStatModel**)&bg_model)cvDestroyWindow("video")cvDestroyWindow("background")cvDestroyWindow("foreground")cvReleaseImage(&pFrImg)cvReleaseImage(&pBkImg)cvReleaseCapture(&pCapture)return 0}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)