www.pudn.com > backmode824.rar > ImageProcess.cpp
// ImageProcess.cpp: implementation of the CImageProcess class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "backmodel.h"
#include "Blob.h"
#include "TrackObject.h"
#include "ImageProcess.h"
#include "Dibapi.h"
#include "math.h"
#include "GaussianModel.h"
#include "cv.h"
#include "highgui.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#define NUM_COLORS 1 /* 0 */
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CImageProcess::CImageProcess()
{
m_lpMapHeader=NULL;
m_lpImage=NULL;
m_lpBackImage=NULL;
m_lpHMap=NULL;
m_lpDMap=NULL;
m_lpSMap=NULL;
m_lpBitmap=NULL;
m_lpPalette=NULL;
bgm=NULL;
srand( (unsigned)time( NULL ) );
}
CImageProcess::~CImageProcess()
{
if(bgm!=NULL)
{
delete bgm;
bgm=NULL;
}
}
BOOL CImageProcess::InitData(CMemory *lpmemory)
{
if(lpmemory==NULL) return FALSE;
if(lpmemory->m_bInitialized==FALSE) return FALSE;
m_lpMapHeader=lpmemory->m_lpMapHeader;
m_lpImage=lpmemory->m_lpImage;
m_lpBackImage=lpmemory->m_lpBackImage;
m_lpMask=lpmemory->m_lpMask; //new add
m_lpGrayMask=lpmemory->m_lpGrayMask; //new add809
m_lpDMap=lpmemory->m_lpDMap;
m_lpSMap=lpmemory->m_lpSMap;
m_lpHMap=lpmemory->m_lpHMap;
m_lpNewEdgeChain=lpmemory->m_lpNewEdgeChain;
m_lpOldEdgeChain=lpmemory->m_lpOldEdgeChain;
return TRUE;
}
//装入位图
//输入:CFile类指针,图象数据指针
//输出:成功 TRUE,失败 FALSE
BOOL CImageProcess::LoadImage(CFile* pFile,LPBYTE lpimage)
{
SetCursor(LoadCursor(NULL,IDC_WAIT));
DWORD dwSize;
TRY
{
// read DIB file header
BITMAPFILEHEADER bmfHdr;
pFile->Read(&bmfHdr,sizeof(BITMAPFILEHEADER));
// is DIB file?
if (bmfHdr.bfType!=0x4d42)
{
SetCursor(LoadCursor(NULL,IDC_ARROW));
return FALSE;
}
DWORD dwLength=pFile->GetLength();
if (bmfHdr.bfSize!=dwLength) bmfHdr.bfSize=dwLength;
// read DIB buffer
dwSize=bmfHdr.bfSize - sizeof(BITMAPFILEHEADER);
if(!m_lpMapHeader) return FALSE;
pFile->Read((LPBYTE)m_lpMapHeader,sizeof(BITMAPINFOHEADER));
if (m_lpMapHeader->biSize!= sizeof(BITMAPINFOHEADER))
{ SetCursor(LoadCursor(NULL,IDC_WAIT));return FALSE;}
int nNumColors=(UINT)m_lpMapHeader->biClrUsed;
if (nNumColors == 0)
{
//no color table for 24-bit, default size otherwise
if (m_lpMapHeader->biBitCount!=24)
nNumColors=1<biBitCount; // standard size table
}
// fill in some default values if they are zero
if(m_lpMapHeader->biClrUsed == 0)
m_lpMapHeader->biClrUsed=nNumColors;
if(m_lpMapHeader->biSizeImage == 0)
m_lpMapHeader->biSizeImage=((((m_lpMapHeader->biWidth*(DWORD)m_lpMapHeader->biBitCount)
+31)&~31)>>3)*m_lpMapHeader->biHeight;
pFile->Read((LPBYTE)m_lpMapHeader+m_lpMapHeader->biSize,nNumColors*sizeof(RGBQUAD));
WORD offBits=(WORD)m_lpMapHeader->biSize+nNumColors*sizeof(RGBQUAD);
if(bmfHdr.bfOffBits!=0L)
pFile->Seek(bmfHdr.bfOffBits,CFile::begin);
DWORD dwCount=pFile->ReadHuge(lpimage,m_lpMapHeader->biSizeImage);
if(dwCount!=m_lpMapHeader->biSizeImage)
{
SetCursor(LoadCursor(NULL,IDC_ARROW));
return FALSE;
}
}
CATCH (CException, e)
{
SetCursor(LoadCursor(NULL,IDC_ARROW));
return FALSE;
}
END_CATCH
//create CDib with DIB buffer
SetCursor(LoadCursor(NULL,IDC_ARROW));
BuildPalette();
return BuildBitmap(lpimage);
}
//创建调色板
//输入:
//输出:成功 TRUE、失败 FALSE
BOOL CImageProcess::BuildPalette()
{
if(m_lpPalette!=NULL)
{
delete m_lpPalette;
m_lpPalette=NULL;
}
if(!m_lpMapHeader) return FALSE;
HPALETTE hPalette=CreateDIBPalette((LPBYTE)m_lpMapHeader);
if(hPalette==NULL) return FALSE;
m_lpPalette=new CPalette;
m_lpPalette->Attach(hPalette);
return TRUE;
}
//创建调色板
//输入:图象数据句柄
//输出:成功 TRUE、失败 FALSE
BOOL CImageProcess::BuildBitmap(LPBYTE lpimage)
{
HBITMAP hBitmap;
if(m_lpBitmap!=NULL)
{
delete m_lpBitmap;
m_lpBitmap=NULL;
hBitmap=NULL;
}
if(!m_lpMapHeader) return FALSE;
HPALETTE hPal=CreateDIBPalette((LPBYTE)m_lpMapHeader);
HDC hDC;
HPALETTE hOldPal=NULL;
hDC=GetDC(NULL);
if(!hDC) return 0;
if(hPal)
{
hOldPal=SelectPalette(hDC,hPal,FALSE);
RealizePalette(hDC);
}
hBitmap=CreateDIBitmap(hDC,
(LPBITMAPINFOHEADER)m_lpMapHeader,
CBM_INIT,
lpimage,
(LPBITMAPINFO)m_lpMapHeader,
DIB_RGB_COLORS);
if(hOldPal)
SelectPalette(hDC,hOldPal,FALSE);
ReleaseDC(NULL,hDC);
if(hBitmap==NULL) return FALSE;
m_lpBitmap=new CBitmap;
m_lpBitmap->Attach(hBitmap);
return TRUE;
}
//缩放显示位图
//输入:设备句柄,目标区域,源区域,光栅操作模式
//输出:成功 TRUE、失败 FALSE
BOOL CImageProcess::Display(CDC* pDC,CRect rcDest,CRect rcSrc,DWORD dwRop)
{
CDC MemDC;
MemDC.CreateCompatibleDC(pDC);
CBitmap* lpOldBmp=MemDC.SelectObject(m_lpBitmap);
CPalette* lpOldPal=pDC->SelectPalette(m_lpPalette,TRUE);
pDC->RealizePalette ();
BOOL bSuccess=pDC->StretchBlt(rcDest.left,rcDest.top,
rcDest.Width(),
rcDest.Height(),
&MemDC,
rcSrc.left, rcSrc.top,
rcSrc.Width(),
rcSrc.Height(),
dwRop);
MemDC.SelectObject(lpOldBmp);
pDC->SelectPalette(lpOldPal,TRUE);
return bSuccess;
}
void CImageProcess::simpleFrameDiff()
{
int w,h;
w=m_lpMapHeader->biWidth;
h=m_lpMapHeader->biHeight;
float hisO;
float hisB;
if(m_lpMapHeader->biBitCount==24)
{
for(int i=0;i<3*h;i+=3)//
for(int j=0;j<3*w;j+=3)
{
hisO=0.3*(*(m_lpImage+(i*w)+j+0))+
0.59*(*(m_lpImage+(i*w)+j+1))
+0.11*(*(m_lpImage+(i*w)+j+2));
hisB=0.3*(*(m_lpBackImage+(i*w)+j+0))+
0.59*(*(m_lpBackImage+(i*w)+j+1))
+0.11*(*(m_lpBackImage+(i*w)+j+2));
//aa=*(m_ImageProcess.m_lpImage+(i*w)+j+0)-*(m_ImageProcess_back.m_lpImage+(i*w)+j+0);
if(fabs(hisB-hisO)>m_iThreshold)
{
*(m_lpDMap+(i*w)+j+0)=255;
*(m_lpDMap+(i*w)+j+1)=255;
*(m_lpDMap+(i*w)+j+2)=255;
/*
*(m_lpDMap+(i*w)+j+0)=255;
*(m_lpDMap+(i*w)+j+1)=0;
*(m_lpDMap+(i*w)+j+2)=197; //粉色*/
}
else
{
/*
*(m_lpDMap+(i*w)+j+0)=*(m_lpImage+(i*w)+j+0);//0;
*(m_lpDMap+(i*w)+j+1)=*(m_lpImage+(i*w)+j+1);//0;
*(m_lpDMap+(i*w)+j+2)=*(m_lpImage+(i*w)+j+2);//0;*/
*(m_lpDMap+(i*w)+j+0)=0;//0;
*(m_lpDMap+(i*w)+j+1)=0;//0;
*(m_lpDMap+(i*w)+j+2)=0;//0;
}
}
}
else if(m_lpMapHeader->biBitCount==8) //灰度图
{
for(int i=0;im_iThreshold)
{
*(m_lpDMap+(i*w)+j+0)=255;
//*(m_lpDMap+(i*w)+j+1)=0;
//*(m_lpDMap+(i*w)+j+2)=197; //粉色
}
else
{
*(m_lpDMap+(i*w)+j+0)=0;
//*(m_lpDMap+(i*w)+j+1)=*(m_lpImage+(i*w)+j+1);//0;
//*(m_lpDMap+(i*w)+j+2)=*(m_lpImage+(i*w)+j+2);//0;
}
}
}
/*
for(int i=0;i0)
{
*(m_lpImage+(i*w+j))=255;
*(m_lpImage+(i*w+j)+1)=255;
*(m_lpImage+(i*w+j)+2)=255;
}
else
{
*(m_lpImage+(i*w+j))=0;
*(m_lpImage+(i*w+j)+1)=0;
*(m_lpImage+(i*w+j)+2)=0;
}
}*/
}
/************************************************
* 函数:KCluster()
* 参数:
* int type 1:HS空间聚类;其它RGB空间聚类
* double *lpMeanValue //聚类中心指针
* int ClusterNum //聚类中心数量
* int IterativeNum //聚类迭代次数
* double error //聚类中心值变化允许偏差
* 返回值: TRUE or FALSE
*************************************************/
bool CImageProcess::KCluster(int type,
double *lpMeanValue,
int ClusterNum,
int IterativeNum,
double error)
{
bool b;
SetCursor(LoadCursor(NULL,IDC_WAIT));
ZeroDMemory();
m_lpKCluster=new CKCluster;
//m_lpBackImage
//m_lpKCluster->InitData(m_lpMapHeader,m_lpImage,m_lpDMap,m_lpHMap,m_lpSMap);
m_lpKCluster->InitData(m_lpMapHeader,m_lpDMap,m_lpBackImage,m_lpHMap,m_lpSMap);
if(type==1)
b=m_lpKCluster->KClusterHS(lpMeanValue,ClusterNum,IterativeNum,error);
else
b=m_lpKCluster->KClusterRGB(lpMeanValue,ClusterNum,IterativeNum,error);
SetCursor(LoadCursor(NULL,IDC_ARROW));
delete m_lpKCluster;
return b;
}
///////////////////////////////////////////////////////////
BOOL CImageProcess::ZeroDMemory()
{
ZeroMemory(m_lpDMap,1024*1024*2);
ZeroMemory(m_lpNewEdgeChain,1024*1024*2);
ZeroMemory(m_lpOldEdgeChain,1024*1024*2);
//ZeroMemory(m_lpVMap,1024*1024);
// ZeroMemory(m_lpSHighPassMap,1024*1024);
return TRUE;
}
bool CImageProcess::creatBackModel(LPBYTE pFInitial) //创建背景模型
//以第一幅图像每点的像素值作为均值的初始化
{
if(bgm!=NULL)
return true;
bgm=new CBGModel(m_lpMapHeader->biWidth,m_lpMapHeader->biHeight);
bgm->ProcessFirst(pFInitial);
return true;
}
//============================================
bool CImageProcess::doGaussSub(LPBYTE m_lpImage,int Num)
{
int i,j;//判断是否是第一幅图像
i=Num;
IplImage* image = NULL;
IplImage* image1 = NULL;
IplImage* image2[3] ;
IplImage* image3 = NULL;
int minSize = 50;//确定无效区域的大小
int nBlobs=0;
int nTobs=0;
for( j = 0; jbiWidth,m_lpMapHeader->biHeight),8,3);
image1=cvCreateImage(cvSize(m_lpMapHeader->biWidth,m_lpMapHeader->biHeight),8,1);
image2[0]=cvCreateImage(cvSize(m_lpMapHeader->biWidth,m_lpMapHeader->biHeight),32,1);
image3=cvCreateImage(cvSize(m_lpMapHeader->biWidth,m_lpMapHeader->biHeight),8,3);
image->origin = 1;
image1->origin = 1;
// image2->origin = 1;
image3->origin = 1;
if((creatBackModel(m_lpBackImage))&&(i==0))
//第一次初始化背景
{
//判断是前景还是背景
bgm->Process(m_lpImage,m_lpMask,i);//m_lpBackImage);//,m_lpMask);
i++;
return true;
}else
{
if(i>=1)
//累积多次背景更新之后进行处理
{
//判断是前景还是背景
bgm->Process(m_lpImage,m_lpMask,i);//m_lpBackImage);//,m_lpMask);
//LPBYTE转换为IplImage
cvSetData(image,m_lpMask,image->width*3);
//LPBYTE转换为IplImage
cvSetData(image3,m_lpImage,image3->width*3);
//rgbtogray
cvCvtColor(image, image1, CV_RGB2GRAY);
//高斯平滑
cvSmooth(image1,image1,CV_GAUSSIAN,3,0,0);
//二值化前景图
cvThreshold(image1, image1, 60, 255.0, CV_THRESH_BINARY);
//进行形态学滤波,去掉噪音
cvErode(image1, image1, 0, 1);
cvDilate(image1, image1, 0, 1);
//进行形态学滤波,去掉噪音
//cvErode(image1, image1, 0, 1);
//cvDilate(image1, image1, 0, 1);
//找到二值图像的连接区域
if(FindConnectedComponents(image1->imageDataOrigin,image2[0]->imageDataOrigin))
{
// now extract blobs
FindBlobs(image2[0], blobs, &nBlobs, minSize);
MatchBlobsTobs(blobs, nBlobs, tobs, &nTobs);
for(int i=0; iid % NUM_COLORS]);
blobs[i]->RenderBB(image3, CV_RGB(0, 128, 200));
}
}
/*//提取目标轮廓
cvFindContours(image1, storage, &contours, sizeof(CvContour),
CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE , cvPoint(0,0) );
count = contours->total;
PointArray = (CvPoint *)malloc(count * sizeof(CvPoint));//数组
Array=new int[count*2];
for(j=0;jh_next!=NULL)
{
cvCvtSeqToArray(contours, PointArray, CV_WHOLE_SEQ);//contour转换成数组
*(Array+j)=PointArray->x;
*(Array+j+1)=PointArray->y;
contours=contours->h_next;
}
}
//去除背景消减之后的噪声小区域,根据面积大小
//确定物体位置
//if(bgm->DivideSmallArea(image1->imageDataOrigin,m_lpGrayMask))*/
cvNamedWindow( "ObjectTracking", 1 );
cvNamedWindow("Raw Video",1);
cvShowImage("ObjectTracking", image1);
cvShowImage("Raw Video",image3);
cvWaitKey(1);
cvReleaseImage(&image);
cvReleaseImage(&image1);
cvReleaseImage(&image2[0]);
image3->imageData=NULL;
cvReleaseImage(&image3);
//delete [] Array;
return true;
}else
//先选择前五十幅图像进行背景重建
//进行多次背景更新
{
//判断是前景还是背景
bgm->Process(m_lpImage,m_lpMask,i);//m_lpBackImage);//,m_lpMask);
i++;
return true;
}
}
return false;
}
//===============================================
//进行背景建模后,进行连接
//===============================================
//////////////////////////////////////////////////////////////////////
/*
Finds connected components in binary image pMask (8x1) using a 2-pass
method. Stores resulting labels in pLabels (32x1) such that every pixel in
a blob has the same label and each blob has a unique label.
*/
bool CImageProcess::FindConnectedComponents(LPBYTE pMask, LPBYTE pLabels)
{
if (!pMask || !pLabels) return false;
BYTE *mask=pMask;
int *id = (int*)pLabels;
int x, y, i, j, k, nextId;
int ids[4];
int vw=bgm->vw;
int vh=bgm->vh;
int nPixels=vw*vh;
int idOfs[4] = { -vw-1, -vw, -vw+1, -1 };
// to start, every id value maps to itself
nextId = 1;
for( i = 0; i 0)
{
*id = j;
}
else
{
*id = nextId++;
}
}
else
{
*id = 0;
}
mask++;
id++;
}
// scan rest of rows
for(y=1; yi)
{
i = j;
}
if (i>0)
{
*id = i;
}
else
{
*id = nextId++;
}
}
else
{
*id = 0;
}
mask++;
id++;
// now check the 'middle' of the row
for(x=1; x j) j = ids[i];
}
if (j > 0)
{
for( i = 0; i<4; i++)
{
if (ids[i]==0 || ids[i]==j) continue;
for(k=1; ki) i = j;
j = *(id - 1);
if (j>i) i = j;
if (i>0)
{
*id = i;
}
else
{
*id = nextId++;
}
}
else
{
*id = 0;
}
mask++;
id++;
if (nextId >= MAX_CC_IDS)
{
CString s;
s.Format("Error - not enough connected component ids (%d)\n", MAX_CC_IDS);
//MessageBox(s);
return false;
}
}
// pass 2 - update ids in label image according to equiv map
id = (int*)pLabels;
for( i = 0; i 0) *id = map[*id];
id++;
}
return true;
}
//////////////////////////////////////////////////////////////////////
/*
Extracts blob info from labelled connected component image
pLabels - 32x1 labelled image
blobs - pointer to MAX_NUM_BLOBS blob object pointers
nBlobs - pointer to int that will store number of valid blobs found
minSize - minimum size for a blob to be valid
*/
//////////////////////////////////////////////////////////////////////
bool CImageProcess::FindBlobs(IplImage *pLabels, Blob **blobs, int *nBlobs, int minSize)
{
if (!pLabels || !blobs || !nBlobs) return false;
int *id = (int*)pLabels->imageData;
int x, y, i, j, n;
int vw=bgm->vw;
int vh=bgm->vh;
int nPixels=vw*vh;
*nBlobs = 0;
for( i = 0; iuser will serve a dual purpose:
// 1) flag to say whether the blob 'grew' due to the last row
// 2) index into map array that references this blob
for( i = 0; iuser = 0;
for(x=0; x 0)
{
if (map[j] < 0)
{
if (n >= MAX_NUM_BLOBS)
{
CString s;
s.Format("error: too many blobs (%d)\n", n);
*nBlobs = 0;
return false;
}
else
{
// this is a new blob
map[j] = n;
blobs[n]->mass = 1;
blobs[n]->nHull = 0;
blobs[n]->centroid.x = x;
blobs[n]->centroid.y = y;
blobs[n]->bbBottomRight.x = x;
blobs[n]->bbBottomRight.y = y;
blobs[n]->bbTopLeft.x = x;
blobs[n]->bbTopLeft.y = y;
blobs[n]->id = j;
blobs[n]->user = j;
n++;
}
}
else
{
// this blob already exists
blobs[map[j]]->user = j;
j = map[j];
blobs[j]->mass++;
blobs[j]->centroid.x += x;
blobs[j]->centroid.y += y;
if (x > blobs[j]->bbBottomRight.x) blobs[j]->bbBottomRight.x = x;
else if (x < blobs[j]->bbTopLeft.x) blobs[j]->bbTopLeft.x = x;
if (y > blobs[j]->bbBottomRight.y) blobs[j]->bbBottomRight.y = y;
else if (y < blobs[j]->bbTopLeft.y) blobs[j]->bbTopLeft.y = y;
}
}
id++;
}
// check for finished blobs
for( i = 0; iuser == 0) && (blobs[i]->mass < minSize))
{
// kill this blob by moving it to the end of the list and
// decrement the list size
n--;
// we have to do a proper swap
Blob *tblob = blobs[i];
blobs[i] = blobs[n];
blobs[n] = tblob;
// we also have to update the map
map[blobs[i]->user] = i;
// since we changed the blob at position we want to reprocess
// it next time through the loop
i--;
}
}
}
// do some per blob post-processing
for( i = 0; icentroid.x /= blobs[i]->mass;
blobs[i]->centroid.y /= blobs[i]->mass;
}
*nBlobs = n;
return true;
}
//////////////////////////////////////////////////////////////////////
bool CImageProcess::ColorTob(IplImage *pImg, IplImage *pLabels,
TrackObject *tob, BYTE *color)
{
if (!pImg || !tob) return false;
BYTE *pi = (BYTE*)pImg->imageData;
int *id = (int*)pLabels->imageData;
int w, h, x, y, x3, pitch;
int vw=bgm->vw;
int vh=bgm->vh;
int nPixels=vw*vh;
Blob *blob = tob->blob;
w = blob->bbBottomRight.x - blob->bbTopLeft.x;
h = blob->bbBottomRight.y - blob->bbTopLeft.y;
x = blob->bbTopLeft.y * vw + blob->bbTopLeft.x;
pi += x*3;
id += x;
pitch = vw*3;
for(y=0; yid == *(id + x))
{
*(pi + x3) = color[2];
*(pi + x3 + 1) = color[1];
*(pi + x3 + 2) = color[0];
}
x3 += 3;
}
pi += pitch;
id += vw;
}
return true;
}
//////////////////////////////////////////////////////////////////////
bool CImageProcess::MatchBlobsTobs(Blob **blobs, int nBlobs,
TrackObject **tobs, int *nTobs)
{
if (!blobs || !tobs || !nTobs) return false;
int i;
int n = nBlobs;
if (n > MAX_NUM_TOBS) n = MAX_NUM_TOBS;
for( i = 0; iblob = blobs[i];
}
*nTobs = n;
return true;
}