www.pudn.com > Gesture[20040824].rar > Background.cpp
// Background.cpp: implementation of the CBackground class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Gesture.h"
#include "Background.h"
#include "Image.h"
#include "math.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
static double threshold[3] = {0.5,0.5,0.5};
#define pi 3.1415926535897
double (*P) [3];
double (*L) [3];
double* S;
double (*P2) [3];
//double* xx;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CBackground::CBackground(CCamAvi *avi)
{
BkgAvi = avi;
Th_diff = 10;
m_BkgImage = new CImage;
m_BkgType = GaussianAndThreshold;
m_bBkgReady = false;
displayflag = false;
testflag = false;
imageshow1 = new CImage;
imageshow2 = new CImage;
imageshow3 = new CImage;
}
CBackground::~CBackground()
{
}
IplImage* CBackground::Thresholding_GrayLevel(IplImage *image)
{
CvSize imsize;
imsize.width = image->width;
imsize.height = image->height;
IplImage *grayimage;
if (image->nChannels>1) {
grayimage = cvCreateImage(imsize, image->depth, 1);
iplColorToGray(image, grayimage);
} else grayimage = image;
IplImage *tempimage = cvCreateImage(imsize, image->depth, 1);
IplImage *diffimage = cvCreateImage(imsize, image->depth, 1);
switch ( m_BkgType ) {
case GaussianAndThreshold :
cvAbsDiff(grayimage, GrayBkg, tempimage);
cvThreshold(tempimage, diffimage, Th_diff, 255, CV_THRESH_BINARY);
break;
default :
return NULL;
}
cvReleaseImage(&tempimage);
if (image->nChannels>1) cvReleaseImage(&grayimage);
return diffimage;
}
void CBackground::ConvertColorBkg2GrayBkg()
{
CvSize imsize;
imsize.width = m_BkgImage->Width();
imsize.height = m_BkgImage->Height();
IplImage *image = m_BkgImage->GetImage();
GrayBkg = cvCreateImage( imsize, image->depth, 1);
if ( image->nChannels > 1 )
iplColorToGray( image, GrayBkg);
else cvCopyImage( image, GrayBkg);
}
void CBackground::ExtractBackgroundFromVideo()
{
CvSize imsize;
int length = BkgAvi->GetAviLength();
IplImage* gray[2000];//怎么用动态表示?
BkgAvi->SetReaderPosition(0);
//读第一帧
imsize.width = BkgAvi->GetFramePointer()->Width();
imsize.height = BkgAvi->GetFramePointer()->Height();
BkgAvi->GetFrameFromAvi();
for (int i = 0;i < length;i++){
BkgAvi->GetFrameFromAvi();
gray[i] = cvCreateImage(imsize,BkgAvi->GetFramePointer()->GetImage()->depth,1);
iplColorToGray(BkgAvi->GetFramePointer()->GetImage(), gray[i]);
BkgAvi->NextFrame();
}
ExtractMoGBackground(gray);
}
void CBackground::ExtractGaussianBackground()
{
}
void CBackground::ExtractMoGBackground(IplImage** gray)
{
int length = BkgAvi->GetAviLength();
int h = BkgAvi->GetFramePointer()->Height();
int w = BkgAvi->GetFramePointer()->Width();
m_MoG = new struct MoGParameters [h*w];
unsigned char *pixelprocess= new unsigned char [length];
for (int a= 0;a < h;a++){
for (int b= 0;b < w;b++){
for (int c = 0;c < length;c++){
//得到一个象素过程的数组,然后操作
pixelprocess[c] = gray[c]->imageData[a*w+b];
}
P = (double (*)[3]) (new double[length*3]);
L = (double (*)[3]) (new double[length*3]);
S = new double [length];
P2 = (double (*)[3]) (new double[length*3]);
EM(pixelprocess,a,b);
}
}
imageshow1->Create(w,h,8);
imageshow2->Create(w,h,8);
imageshow3->Create(w,h,8);
for (int d = 0;d < h*w;d++)
imageshow1->GetImage()->imageData[d] = m_MoG[d].miu[0];
for (int e = 0;e < h*w;e++)
imageshow2->GetImage()->imageData[e] = m_MoG[e].miu[1];
for (int f = 0;f < h*w;f++)
imageshow3->GetImage()->imageData[f] = m_MoG[f].miu[2];
//释放所有指针
for (int j = 0;j < length;j++){
cvReleaseImage(&gray[j]);
}
displayflag = true;
}
void CBackground::EM(unsigned char* pixelprocess,int x_co,int y_co)
{
//初始化
int height = BkgAvi->GetFramePointer()->Height();
int width = BkgAvi->GetFramePointer()->Width();
double ome[3];
double miu[3];
double xig[3];
for (int a = 0;a < 3; a++){
ome[a] = 0.333333333333;
xig[a] = 900;
}
int length = BkgAvi->GetAviLength();
miu[0] = pixelprocess[length/4]; miu[1] = pixelprocess[length/2]; miu[2] = pixelprocess[3*length/4];
//调用EM23
EM23(pixelprocess,ome,miu,xig,x_co,y_co,height,width);
}
void CBackground::EM23(unsigned char* pixelprocess,double* ome,double* miu,double* xig,int x_co,int y_co,int height,int width)
{
double miutemp[3];
double temp[3];
bool flag;
double fenzi[3],fenmu[3];
double T[3];
double T2[3];
bool ok = false;
int max,mid,min;
int length = BkgAvi->GetAviLength();
flag = false;
for (int m = 0;m < 3;m++){
miutemp[m] = 255;
T[m] = 0;
T2[m] = 0;
fenzi[m] = 0;
fenmu[m] = 0;
}
//K-mean算法,求得带入EM的初值
double muu[3],muutemp[3];
muu[0] = 60; muu[1] = 120; muu[2] = 180;
bool kflag = false;
int leibie[256],count1=0,count2=0,count3=0;
double tem1=0,tem2=0,tem3=0,te1=0,te2=0,te3=0;
while(!kflag){
muutemp[0] = muu[0];muutemp[1] = muu[1];muutemp[2] = muu[2];
for (int w=0;w<256;w++){
leibie[w] = KJudge(w,muu[0],muu[1],muu[2]);
}
for (int v=0;v<256;v++){
if (leibie[v]==1){tem1 += v;count1 += 1;}
else{
if (leibie[v]==2){tem2 +=v;count2 += 1;}
else{
if (leibie[v]==3){tem3 +=v;count3 += 1;}
}
}
}
muu[0] = tem1/count1;muu[1] = tem2/count2;muu[2] = tem3/count3;
if (((muu[0]-muutemp[0])<=1)&&((muu[1]-muutemp[1])<=1)&&((muu[2]-muutemp[2])<=1)){
kflag = true;
}
}
for (int u=0;u<256;u++){
if (leibie[u]==1){te1 += pow((u-muu[0]),2);}
else{
if (leibie[u]==2){te2 += pow((u-muu[1]),2);}
else{
if (leibie[u]==3){te3 += pow((u-muu[2]),2);}
}
}
}
xig[0] = te1/(count1-1);xig[1] = te2/(count2-1);xig[2] = te3/(count3-1);
miu[0] = muu[0];miu[1] = muu[1];miu[2] = muu[2];
//如果不小于阈值,就进行操作,否则返回
while (!flag){
for (int f = 0;f < length;f++){
P[f][0] = (exp(-(pixelprocess[f]-miu[0])*(pixelprocess[f]-miu[0])/(2*xig[0])))/((pow(2*pi,0.5))*(pow(xig[0],0.5)));
P[f][1] = (exp(-(pixelprocess[f]-miu[1])*(pixelprocess[f]-miu[1])/(2*xig[1])))/((pow(2*pi,0.5))*(pow(xig[1],0.5)));
P[f][2] = (exp(-(pixelprocess[f]-miu[2])*(pixelprocess[f]-miu[2])/(2*xig[2])))/((pow(2*pi,0.5))*(pow(xig[2],0.5)));
L[f][0] = ome[0]*P[f][0];
L[f][1] = ome[1]*P[f][1];
L[f][2] = ome[2]*P[f][2];
S[f] = L[f][0] + L[f][1] + L[f][2];
P2[f][0] = L[f][0]/S[f];
P2[f][1] = L[f][1]/S[f];
P2[f][2] = L[f][2]/S[f];
T[0] += P2[f][0];
T[1] += P2[f][1];
T[2] += P2[f][2];
T2[0] += P2[f][0]*pixelprocess[f];
T2[1] += P2[f][1]*pixelprocess[f];
T2[2] += P2[f][2]*pixelprocess[f];
}
//第三步
//ome[0] = T[0]/length;
//ome[1] = T[1]/length;
//ome[2] = T[2]/length;
miu[0] = T2[0]/T[0];
miu[1] = T2[1]/T[1];
miu[2] = T2[2]/T[2];
for (int h = 0;h < length;h++){
fenzi[0] += ((pixelprocess[h]-miu[0])*(pixelprocess[h]-miu[0])*P2[h][0]);
fenzi[1] += ((pixelprocess[h]-miu[1])*(pixelprocess[h]-miu[1])*P2[h][1]);
fenzi[2] += ((pixelprocess[h]-miu[2])*(pixelprocess[h]-miu[2])*P2[h][2]);
fenmu[0] += P2[h][0];
fenmu[1] += P2[h][1];
fenmu[2] += P2[h][2];
}
xig[0] = fenzi[0]/fenmu[0];
xig[1] = fenzi[1]/fenmu[1];
xig[2] = fenzi[2]/fenmu[2];
//判断flag
for (int j = 0;j < 3;j++){
temp[j] = abs(miu[j] - miutemp[j]);
}
for (int l = 0;l < 3;l++){
if (temp[l] <= threshold[l]){flag = true;}
else {flag = false; break;}
}
//记录上一次的结果
for (int e = 0;e < 3;e++){
miutemp[e] = miu[e];
}
}
//记录miu[i],需要归类
if (miu[0]>=miu[1]){
if (miu[1]>=miu[2]){max=0;mid=1;min=2;}
else{
if (miu[0]>=miu[2]){max=0;mid=2;min=1;}
else{max=2;mid=0;min=1;}
}
}
else{
if (miu[0]>=miu[2]){max=1;mid=0;min=2;}
else{
if (miu[1]>=miu[2]){max=1;mid=2;min=0;}
else{max=2;mid=1;min=0;}
}
}
m_MoG[x_co*width+y_co].miu[0] = miu[max];
m_MoG[x_co*width+y_co].miu[1] = miu[mid];
m_MoG[x_co*width+y_co].miu[2] = miu[min];
delete(P);
delete(L);
delete(S);
delete(P2);
//delete(x);
}
int CBackground::KJudge(int w,double x,double y,double z)
{
double tt1,tt2,tt3;
tt1 = abs(w-x);
tt2 = abs(w-y);
tt3 = abs(w-z);
if (tt1 <= tt2){
if (tt2 <= tt3){return 1;}
if (tt1 <= tt3){return 1;}
if (tt3 < tt1){return 3;}
}
else{
if (tt1 <= tt3){return 2;}
if (tt2 <= tt3){return 2;}
if (tt3 < tt2){return 3;}
}
}
int CBackground::Judge(double ranran,double* probb)
{
for (int a = 0; a < 256; a++){
if (ranran == probb[a]) { return a; break; }
if ((ranran > probb[a])&&(ranran < probb[a+1])) { return (a+1); break; }
}
}
void CBackground::Test()
{
//给定mu和xg
double mu[3],xg[3],om[3];
mu[0] = 50; mu[1] = 130; mu[2] = 190;
xg[0] = 200,xg[1] = 300,xg[2] = 400;
om[0] = 0.333333333333,om[1] = 0.333333333333,om[2] = 0.333333333333;
double temp0=0,temp1=0,temp2=0;
double ran=0;
double EMP[12000][3],EML[12000][3],EMP2[12000][3],EMS[12000],T[3],T2[3],miutemp[3],temp[3],fenzi[3],fenmu[3];
bool flag=false;
double ome[3],miu[3],xig[3];
//利用公式生成Gauss分布的一个象素过程
for (int a = 0; a < 256; a++){
temp0 = (om[0]*exp(-pow((a-mu[0]),2)/(2*xg[0])))/(pow(2*pi,0.5)*pow(xg[0],0.5));
temp1 = (om[1]*exp(-pow((a-mu[1]),2)/(2*xg[1])))/(pow(2*pi,0.5)*pow(xg[1],0.5));
temp2 = (om[2]*exp(-pow((a-mu[2]),2)/(2*xg[2])))/(pow(2*pi,0.5)*pow(xg[2],0.5));
gauss[a] = temp0+temp1+temp2;
}
//得到概率分布
probb[0] = gauss[0];
for (int b = 1; b < 256; b++){
probb[b] = probb[b-1] + gauss[b];
}
//利用随机数得到象素过程的每个点值
srand( (unsigned)time( NULL ) );
for (int c = 0; c < 12000; c++){
ran = (rand()*probb[255])/RAND_MAX;//ran是0-1之间
pixpro[c] = Judge(ran,probb);
}
//统计得到0到255的象素值的象素的个数
for (int y=0;y<256;y++){
geshu[y] = 0;
}
for (int x=0;x<12000;x++){
geshu[pixpro[x]] += 1;
}
//K-mean算法,求得带入EM的初值
double muu[3],muutemp[3];
muu[0] = 60; muu[1] = 120; muu[2] = 180;
bool kflag = false;
int leibie[256],count1=0,count2=0,count3=0;
double tem1=0,tem2=0,tem3=0,te1=0,te2=0,te3=0;
while(!kflag){
muutemp[0] = muu[0];muutemp[1] = muu[1];muutemp[2] = muu[2];
for (int w=0;w<256;w++){
leibie[w] = KJudge(w,muu[0],muu[1],muu[2]);
}
for (int v=0;v<256;v++){
if (leibie[v]==1){tem1 += v;count1 += 1;}
else{
if (leibie[v]==2){tem2 +=v;count2 += 1;}
else{
if (leibie[v]==3){tem3 +=v;count3 += 1;}
}
}
}
muu[0] = tem1/count1;muu[1] = tem2/count2;muu[2] = tem3/count3;
if (((muu[0]-muutemp[0])<=1)&&((muu[1]-muutemp[1])<=1)&&((muu[2]-muutemp[2])<=1)){
kflag = true;
}
}
for (int u=0;u<256;u++){
if (leibie[u]==1){te1 += pow((u-muu[0]),2);}
else{
if (leibie[u]==2){te2 += pow((u-muu[1]),2);}
else{
if (leibie[u]==3){te3 += pow((u-muu[2]),2);}
}
}
}
xig[0] = te1/(count1-1);xig[1] = te2/(count2-1);xig[2] = te3/(count3-1);
miu[0] = muu[0];miu[1] = muu[1];miu[2] = muu[2];
//带入EM计算,得到新的mu和xg
for (int z = 0;z < 3; z++){
ome[z] = 0.333333333333;
}
for (int d = 0;d < 3;d++){
T[d] = 0;
T2[d] = 0;
fenzi[d] = 0;
fenmu[d] = 0;
}
while (!flag){
for (int f = 0;f < 12000;f++){
EMP[f][0] = (exp(-pow((pixpro[f]-miu[0]),2)/(2*xig[0])))/((pow(2*pi,0.5))*(pow(xig[0],0.5)));
EMP[f][1] = (exp(-pow((pixpro[f]-miu[1]),2)/(2*xig[1])))/((pow(2*pi,0.5))*(pow(xig[1],0.5)));
EMP[f][2] = (exp(-pow((pixpro[f]-miu[2]),2)/(2*xig[2])))/((pow(2*pi,0.5))*(pow(xig[2],0.5)));
EML[f][0] = ome[0]*EMP[f][0];
EML[f][1] = ome[1]*EMP[f][1];
EML[f][2] = ome[2]*EMP[f][2];
EMS[f] = EML[f][0] + EML[f][1] + EML[f][2];
EMP2[f][0] = EML[f][0]/EMS[f];
EMP2[f][1] = EML[f][1]/EMS[f];
EMP2[f][2] = EML[f][2]/EMS[f];
T[0] += EMP2[f][0];
T[1] += EMP2[f][1];
T[2] += EMP2[f][2];
T2[0] += EMP2[f][0]*pixpro[f];
T2[1] += EMP2[f][1]*pixpro[f];
T2[2] += EMP2[f][2]*pixpro[f];
}
miu[0] = T2[0]/T[0];
miu[1] = T2[1]/T[1];
miu[2] = T2[2]/T[2];
for (int h = 0;h < 12000;h++){
fenzi[0] += (pow((pixpro[h]-miu[0]),2)*EMP2[h][0]);
fenzi[1] += (pow((pixpro[h]-miu[1]),2)*EMP2[h][1]);
fenzi[2] += (pow((pixpro[h]-miu[2]),2)*EMP2[h][2]);
fenmu[0] += EMP2[h][0];
fenmu[1] += EMP2[h][1];
fenmu[2] += EMP2[h][2];
}
xig[0] = fenzi[0]/fenmu[0];
xig[1] = fenzi[1]/fenmu[1];
xig[2] = fenzi[2]/fenmu[2];
for (int j = 0;j < 3;j++){
temp[j] = abs(miu[j] - miutemp[j]);
}
for (int l = 0;l < 3;l++){
if (temp[l] <= threshold[l]){flag = true;}
else {flag = false; break;}
}
//记录上一次的结果
for (int e = 0;e < 3;e++){
miutemp[e] = miu[e];
}
}
EMmu[0] = miu[0];
EMmu[1] = miu[1];
EMmu[2] = miu[2];
for (int aa = 0; aa < 256; aa++){
temp0 = (ome[0]*exp(-pow((aa-miu[0]),2)/(2*xig[0])))/(pow(2*pi,0.5)*pow(xig[0],0.5));
temp1 = (ome[1]*exp(-pow((aa-miu[1]),2)/(2*xig[1])))/(pow(2*pi,0.5)*pow(xig[1],0.5));
temp2 = (ome[2]*exp(-pow((aa-miu[2]),2)/(2*xig[2])))/(pow(2*pi,0.5)*pow(xig[2],0.5));
gauss2[aa] = temp0+temp1+temp2;
}
//置标志,显示出来
testflag = true;
//释放所有资源
}
//找出每个象素点属于哪个类别的
/*for (int g = 0;g < length;g++){
double temp0 = P2[0];
double temp1 = abs(int(pixelprocess[g]-miu[1]));
double temp2 = abs(int(pixelprocess[g]-miu[2]));
//判断最大的,中间的,最小的
if (temp0 >= temp1){
if (temp1 >= temp2) {max=0;mid=1;min=2;}
else{
if (temp0 >= temp2) {max=0;mid=2;min=1;}
else {max=2;mid=0;min=1;}
}
}
else{//temp1>temp0
if (temp0 >= temp2) {max=1;mid=0;min=2;}
else{
if (temp1 >= temp2) {max=1;mid=2;min=0;}
else {max=2;mid=1;min=0;}
}
}
xx[g][0] = max;
xx[g][1] = mid;
xx[g][2] = min;
}*/
/*
if (miu[0]>=miu[1]){
if (miu[1]>=miu[2]){max=0;mid=1;min=2;}
else{
if (miu[0]>=miu[2]){max=0;mid=2;min=1;}
else{max=2;mid=0;min=1;}
}
}
else{
if (miu[0]>=miu[2]){max=1;mid=0;min=2;}
else{
if (miu[1]>=miu[2]){max=1;mid=2;min=0;}
else{max=2;mid=1;min=0;}
}
}
*/