背景提取的CodeBook码本方法-----所遇到的问题

最近在研究Kim写的codebook码本方法来对背景进行建模,其思想实际上是很简单的,就是对视频中每一帧的所对应的像素的建立一个码本,每一个码本又对应一个或多个码字,我是按照那个kim那边文章来进行编程实现的,但是检测的结果不好,不知道为什么?就高手帮忙解答。。。。代码如下:

// TestCodeBookEx2.cpp : Defines the entry point for the console application.
//






/************************************************************************/
/* A few more thoughts on codebook models
In general, the codebook method works quite well across a wide number of conditions, 
and it is relatively quick to train and to run. It doesn’t deal well with varying patterns of 
light — such as morning, noon, and evening sunshine — or with someone turning lights 
on or off indoors. This type of global variability can be taken into account by using 
several different codebook models, one for each condition, and then allowing the condition 
to control which model is active.                                */
/************************************************************************/


#include "stdafx.h"
#include <cv.h>
#include <highgui.h>
#include <stdio.h>
#include <windows.h>
#include<stdlib.h>


#define RGB_CHANNEL 3
typedef struct  
{
float rgb[RGB_CHANNEL];
float fMinBright;
float fMaxBright;
long lFrequency;
long lFirstAccessTime;
long lLastAccessTime;
long lMnrl;
}CodeWord;


typedef struct
{
CodeWord **ppCodeWord;
long codeWordNum;
}CodeBook;


#define UNDEFINEDCOLOR -1


float ColorDist(float *pRgbCodeWord,BYTE *pRgb)
{
float xt=pRgb[0]*pRgb[0]+pRgb[1]*pRgb[1]+pRgb[2]*pRgb[2];
float vi=pRgbCodeWord[0]*pRgbCodeWord[0]+pRgbCodeWord[1]*pRgbCodeWord[1]+
pRgbCodeWord[2]*pRgbCodeWord[2];
float xv=pRgbCodeWord[0]*pRgb[0]+pRgbCodeWord[1]*pRgb[1]+pRgbCodeWord[2]*pRgb[2];
xv*=xv;


if (vi==0)
{
return sqrt(xt);
}
float p=xv/vi;


float fResult=sqrt(xt-p);
return fResult;
}


bool Brightness(BYTE *pRgb,CodeWord cw)
{

float fBright=sqrt(pRgb[0]*pRgb[0]+pRgb[1]*pRgb[1]+pRgb[2]*pRgb[2]);


float aLearnRate=0.4;
float bLearnRate=1.5;
float temp1,temp2;


temp1=cw.fMinBright;
temp2=cw.fMaxBright*aLearnRate;


float fLowBright=temp1;


if (temp1>temp2)
{
fLowBright=temp2;
}


  temp1=bLearnRate*cw.fMaxBright;
temp2=cw.fMinBright/aLearnRate;


float fHighBright=temp1;
//-------------这地方的>改为了<
if (temp1 < temp2)
{
fHighBright=temp2;
}

if (fLowBright==fHighBright && fLowBright==0)
{
fHighBright=10;
}


if (fLowBright<5)
{
fLowBright=0;
}


if (fBright >= fLowBright && fBright <=fHighBright)
{
return true;
}
return false;

}


void UpdateCodeWord(BYTE *pRgb,CodeWord *pCW,long curFrameNum)
{
float fBright=sqrt(pRgb[0]*pRgb[0]+pRgb[1]*pRgb[1]+pRgb[2]*pRgb[2]);
float fTemp=pCW->lFrequency + 1;


for (int i=0;i<RGB_CHANNEL;i++)
{
pCW->rgb[i]=(pCW->lFrequency*pCW->rgb[i]+pRgb[i])/fTemp;
}


if (pCW->fMinBright>fBright)
{
pCW->fMinBright=fBright;
}


if (pCW->fMaxBright<fBright)
{
pCW->fMaxBright=fBright;
}


pCW->lFrequency++;





long lTemp=curFrameNum-pCW->lLastAccessTime;


if (pCW->lMnrl<lTemp)
{
pCW->lMnrl=lTemp;
}


pCW->lLastAccessTime=curFrameNum;
}
//pCB-------->对应一个像素的码本
void CreateNewCodeWord(CodeBook *pCB,BYTE *pRgb,long curFrameNum)
{
pCB->codeWordNum++;


if (pCB->codeWordNum==1)//说明刚开始是空集时
{
pCB->ppCodeWord=new CodeWord*[pCB->codeWordNum];
}else //非空集的时候
{
CodeWord **ppTempCW=new CodeWord*[pCB->codeWordNum];


memcpy(ppTempCW,pCB->ppCodeWord,sizeof(CodeWord *)*(pCB->codeWordNum-1));
delete []pCB->ppCodeWord;


pCB->ppCodeWord=ppTempCW;
}


CodeWord *pNewCW=new CodeWord;


pNewCW->rgb[0]=(float)pRgb[0];
pNewCW->rgb[1]=(float)pRgb[1];
pNewCW->rgb[2]=(float)pRgb[2];
// memcpy(pNewCW->rgb,pRgb,sizeof(float)*RGB_CHANNEL);
float fBright=sqrt(pRgb[0]*pRgb[0]+pRgb[1]*pRgb[1]+pRgb[2]*pRgb[2]);
pNewCW->fMinBright=fBright;
pNewCW->fMaxBright=fBright;
pNewCW->lFrequency=1;
pNewCW->lMnrl=curFrameNum-1;
pNewCW->lFirstAccessTime=curFrameNum;
pNewCW->lLastAccessTime=curFrameNum;


pCB->ppCodeWord[pCB->codeWordNum-1]=pNewCW;
}
//pCB---->对应一个像素的码本
void ConstructOnePixelCodeWord(BYTE *pRgb,CodeBook *pCB,long curFrameNum)
{
int i;
float fBright=sqrt(pRgb[0]*pRgb[0]+pRgb[1]*pRgb[1]+pRgb[2]*pRgb[2]);


float fThreshold=6.f;//=10.f;


for (i=0;i<pCB->codeWordNum;i++)
{
if (ColorDist(pCB->ppCodeWord[i]->rgb,pRgb)<fThreshold &&
Brightness(pRgb,*(pCB->ppCodeWord[i])))
{
//说明匹配,则更新
UpdateCodeWord(pRgb,pCB->ppCodeWord[i],curFrameNum+1);
return;
}
}


if (pCB->codeWordNum==0 || i==pCB->codeWordNum)
{
//创建一个新的码本
CreateNewCodeWord(pCB,pRgb,curFrameNum+1);
}
}


void InitialConstructCodeBook(CodeBook *pCB,int imageHeight,int imageWidth,char *pImageData,long curFrameNum)
{
int i,j;


BYTE rgb[RGB_CHANNEL];

//码本的构造


for (i=0;i<imageHeight;i++)
{
for (j=0;j<imageWidth;j++)
{
if (i==40 && j==349)
{
int xxxx=3;//用于测试
}
rgb[0]=pImageData[(i*imageWidth+j)*3];
rgb[1]=pImageData[(i*imageWidth+j)*3+1];
rgb[2]=pImageData[(i*imageWidth+j)*3+2];

ConstructOnePixelCodeWord(rgb,&pCB[i*imageWidth+j],curFrameNum);
}
}


}


void ChangeMNRLAndFilter(CodeBook *pCB,int imageHeight,int imageWidth,int InitialConstructNum)
{
int i,j,k;
long lTemp=0;
CodeBook *pCBTemp=NULL;
    CodeWord **ppTempCW=NULL;


int nDelCnt=0;
int *pDelIndex=NULL;
int index=0;


for (i=0;i<imageHeight;i++)
{
for(j=0;j<imageWidth;j++)
{
nDelCnt=0;
pCBTemp=&pCB[i*imageWidth+j];


pDelIndex=new int[pCBTemp->codeWordNum];
memset(pDelIndex,-1,sizeof(int)*pCBTemp->codeWordNum);

if (i==24 && j==280)
{
int xxxxxxxx=2;//用于测试
}
for (k=0;k<pCBTemp->codeWordNum;k++)
{
lTemp = InitialConstructNum - pCBTemp->ppCodeWord[k]->lLastAccessTime +
pCBTemp->ppCodeWord[k]->lFirstAccessTime - 1;
if (lTemp > pCBTemp->ppCodeWord[k]->lMnrl)
{
pCBTemp->ppCodeWord[k]->lMnrl = lTemp;
}

if ( pCBTemp->ppCodeWord[k]->lMnrl > InitialConstructNum/2)
{
// delete pCBTemp->ppCodeWord[k];
// pCBTemp->ppCodeWord[k]=NULL;
pDelIndex[k]=1;
nDelCnt++;
}
}
if (pCBTemp->codeWordNum == nDelCnt)
{
// pCBTemp=NULL;
continue;
}
if (nDelCnt==0)
{
continue;
}
ppTempCW=new CodeWord*[pCBTemp->codeWordNum - nDelCnt];
index=0;
for (k = 0; k < pCBTemp->codeWordNum; k++)
{
if (pDelIndex[k]==-1)
{
ppTempCW[index++]=pCBTemp->ppCodeWord[k];
}else
{
delete pCBTemp->ppCodeWord[k];
}
}
pCBTemp->codeWordNum-=nDelCnt;


delete []pCBTemp->ppCodeWord;


pCBTemp->ppCodeWord=ppTempCW;


delete []pDelIndex;
}
}


}



void BackgroundSubtract(CodeBook *pCB,int imageHeight,
int imageWidth,char *pImageData, 
long curFrameNum,char *pMoveObjectData,
CodeBook *pCacheCB)
{
int i,j,k;
float fBright;


BYTE rgbTemp[RGB_CHANNEL];


float fThreshold=25.f;


memset(pMoveObjectData,0,sizeof(char)*imageHeight*imageWidth);


for (i = 0;i < imageHeight; i++)
{
for (j = 0; j < imageWidth; j++)
{
if (i==37 && j==151)
{
int xxx=3;//用于测试
}
rgbTemp[0]=pImageData[(i*imageWidth+j)*3];
rgbTemp[1]=pImageData[(i*imageWidth+j)*3+1];
rgbTemp[2]=pImageData[(i*imageWidth+j)*3+2];
for (k=0;k<pCB[i*imageWidth+j].codeWordNum;k++)
{
if (ColorDist(pCB[i*imageWidth+j].ppCodeWord[k]->rgb,rgbTemp) < fThreshold &&
Brightness(rgbTemp,*(pCB[i*imageWidth+j].ppCodeWord[k])))
{
UpdateCodeWord(rgbTemp,pCB[i*imageWidth+j].ppCodeWord[k],curFrameNum);
break;
}
}


if (k==pCB[i*imageWidth+j].codeWordNum)//说明没有匹配
{
pMoveObjectData[i*imageWidth+j]=255;

}

}
}


}


//释放码本申请的空间
void FreeCodeBookMem(CodeBook *pCB,int imageHeight,int imageWidth)
{
int i,j,k;


for (i=0;i<imageHeight;i++)
{
for (j=0;j<imageWidth;j++)
{
for (k=0;k<pCB[i*imageWidth+j].codeWordNum;k++)
{
if (pCB[i*imageWidth+j].ppCodeWord[k] != NULL)
{
delete pCB[i*imageWidth+j].ppCodeWord[k];
}
}
}
}


if (pCB!=NULL)
{
delete []pCB;
}
}


void WriteCodeBookToFile(CodeBook *pCB,int imageHeight,int imageWidth,char *cFileName)
{
int i,j,k;


FILE *fp=fopen(cFileName,"w");


fprintf(fp,"码本的位置(x,y)\t码本中的第几个码字\t码字的RGB\t最大亮度\t最小亮度\t频率\tMNRL\tFirstTime\tLastTime\n");


for (i=0;i<imageHeight;i++)
{
for (j=0;j<imageWidth;j++)
{
for (k=0;k<pCB[i*imageWidth+j].codeWordNum;k++)
{
fprintf(fp,"(%d,%d)\t%d\t%f-%f-%f\t%f\t%f\t%ld\t%ld\t%ld\t%ld\n",
i,j,k,pCB[i*imageWidth+j].ppCodeWord[k]->rgb[0],pCB[i*imageWidth+j].ppCodeWord[k]->rgb[1],
pCB[i*imageWidth+j].ppCodeWord[k]->rgb[2],pCB[i*imageWidth+j].ppCodeWord[k]->fMaxBright,
pCB[i*imageWidth+j].ppCodeWord[k]->fMinBright,pCB[i*imageWidth+j].ppCodeWord[k]->lFrequency,
pCB[i*imageWidth+j].ppCodeWord[k]->lMnrl,pCB[i*imageWidth+j].ppCodeWord[k]->lFirstAccessTime,
pCB[i*imageWidth+j].ppCodeWord[k]->lLastAccessTime);
}
}
}


fclose(fp);
}




int main()
{
///
// 需要使用的变量
CvCapture* capture;
IplImage* rawImage;
IplImage* pFrImg = NULL;


int imageWidth,imageHeight;
CodeBook *pCB=NULL;


CodeBook *pCacheCB=NULL;


int i,j,k;

int initialConstructNum=30;//初始化构造码本所用的帧数


//
// 初始化各变量
cvNamedWindow("Raw");
cvNamedWindow("CodeBook");


//打开视频文件,F:\\实验室任务\\视频浓缩\\测试视频\\镜头切换比较少的视频.avi
//F:\\实验室任务\\视频浓缩\\视频摘要在写字楼的应用.avi
if( !(capture = cvCaptureFromFile("F:\\实验室任务\\视频浓缩\\视频摘要在写字楼的应用.avi")))
{
fprintf(stderr, "Can not open video file %s\n");
return -2;
}


rawImage = cvQueryFrame(capture);

imageWidth=rawImage->width;
imageHeight=rawImage->height;


pFrImg = cvCreateImage(cvSize(rawImage->width, rawImage->height), IPL_DEPTH_8U,1);


pCB = new CodeBook[imageWidth*imageHeight];
pCacheCB = new CodeBook[imageHeight*imageWidth];


for (i=0;i<imageHeight;i++)
{
for (j=0;j<imageWidth;j++)
{
pCB[i*imageWidth+j].codeWordNum=0;
pCacheCB[i*imageWidth+j].codeWordNum=0;
pCB[i*imageWidth+j].ppCodeWord=NULL;
pCacheCB[i*imageWidth+j].ppCodeWord=NULL;
}
}


//码本的构造
for (k=0;k<initialConstructNum;k++)
{
printf("frame=%d\n",k);
cvShowImage("CodeBook", rawImage);
if( cvWaitKey(2) >= 0 )
         break;  
InitialConstructCodeBook(pCB,imageHeight,imageWidth,rawImage->imageData,k);
// WriteCodeBookToFile(pCB,imageHeight,imageWidth,"beforeFilter.txt");
rawImage=cvQueryFrame(capture);
}




WriteCodeBookToFile(pCB,imageHeight,imageWidth,"beforeFilter.txt");
//改变MNRL的值以及进行filter
ChangeMNRLAndFilter(pCB,imageHeight,imageWidth,initialConstructNum);




WriteCodeBookToFile(pCB,imageHeight,imageWidth,"afterFilter.txt");




long curFrameNum=initialConstructNum;
//BGS
while ((rawImage=cvQueryFrame(capture))!=NULL)
{
printf("frame=%ld\n",curFrameNum);
BackgroundSubtract(pCB,imageHeight,imageWidth,rawImage->imageData,
curFrameNum,pFrImg->imageData,pCacheCB);
curFrameNum++;

cvSaveImage("background.bmp",pFrImg);
cvSaveImage("moveObj.bmp",rawImage);


if (curFrameNum==241)
{
int xxxx=2;
}
cvShowImage("Raw", pFrImg);
        cvShowImage("CodeBook", rawImage);


if( cvWaitKey(2) >= 0 )
         break;   
}



FreeCodeBookMem(pCB,imageHeight,imageWidth);
cvDestroyWindow("Raw");
    cvDestroyWindow("CodeBook");
return 0;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值