www.pudn.com > 人体步态跟踪识别bate版.rar > TrackMotion.cpp


// TrackMotion.cpp: implementation of the CTrackMotion class. 
// 
////////////////////////////////////////////////////////////////////// 
 
#include "stdafx.h" 
#include "humantrack.h" 
#include "TrackMotion.h" 
 
#ifdef _DEBUG 
#undef THIS_FILE 
static char THIS_FILE[]=__FILE__; 
#define new DEBUG_NEW 
#endif 
 
////////////////////////////////////////////////////////////////////// 
// Construction/Destruction 
////////////////////////////////////////////////////////////////////// 
 
CTrackMotion::CTrackMotion() 
{ 
	m_hDIB = NULL; 
	m_palDIB = NULL; 
	for(int i=0;i<7;i++) 
		if (m_JointP[i].GetSize()!=0) 
		{ 
			m_JointP[i].RemoveAll(); 
		} 
 
} 
 
CTrackMotion::~CTrackMotion() 
{ 
 
} 
/************************************************************************* 
 * \函数名称:  GetFileName() 
 * \输入参数: 
 *   CString	strFilePathName		- 图象的文件名  
 *   int		nCurFrameNum		- 当前帧的图象文件名 
 * \返回值: 
 *   CString			- 返回给定帧数的图象文件名 
 * 
 * \说明: 
 *   该函数根据指定文件路径名和当前图象序列的帧数获取图象文件名 
 *   该函数中需要注意的是,只能读取0-999帧图象,图象为bmp格式,且按照 
 *   帧数数字进行存储,例如第一帧图象文件名为×××001.bmp,第33帧图象 
 *   的文件名为×××033.bmp。如果不是bmp文件,则返回"NULL"。 
 * 
 ************************************************************************* 
 */ 
 
CString CTrackMotion::GetFileName(CString strFilePathName, int nCurFrameNum) 
{ 
	//文件的路径名 
	CString strTempFileName; 
 
	int nNumPos=strFilePathName.Find("."); 
	if(nNumPos==-1) 
	{ 
		AfxMessageBox("Please choose a bmp file"); 
		return "NULL"; 
	} 
 
	//表示去掉了扩展名和数字标号的路径名,在这里,限定帧数为0~999,所以采用三位来表示 
	CString strFileNameNoExtNoNum=strFilePathName.Left(nNumPos-3); 
 
	//表示标号的字符串 
	CString strTempNum; 
 
	if(nCurFrameNum<10){ 
		strTempNum.Format("_0%d",nCurFrameNum); 
	} 
	else { 
		if(nCurFrameNum<100 &&nCurFrameNum>=10){ 
			strTempNum.Format("_%d",nCurFrameNum); 
		} 
		else{ 
			strTempNum.Format("_%d",nCurFrameNum); 
		} 
	} 
	 
	// 得到图象文件名 
	strTempFileName=strFileNameNoExtNoNum+strTempNum+".bmp"; 
	 
	// 返回 
	return strTempFileName; 
} 
 
/************************************************************************* 
 * 
 * \函数名称: 
 *   LoadDibSeq() 
 * 
 * \输入参数: 
 *   CString		strFilePath		- 第一帧图象的文件名  
 *   int		nCurFrameNum		- 当前帧的图象文件名 
 *   int		nTotalFrameNum		- 进行检测的图象帧数 
 *   CDib*		pDib			- 指向返回CDib类的指针 
 * 
 * \返回值: 
 *   BOOL			- 成功则返回TRUE,否则返回FALSE 
 * 
 * \说明: 
 *   该函数根据指定文件路径名和当前图象序列的帧数读取图象数据道pDib中 
 *   该函数中需要注意的是,只能读取0-999帧图象,图象为bmp格式,且按照 
 *   帧数数字进行存储,例如第一帧图象文件名为×××001.bmp,第33帧图象 
 *   的文件名为×××033.bmp。 
 * 
 ************************************************************************* 
 */ 
 
BOOL CTrackMotion::LoadDibSeq() 
{ 
	//一般来讲,程序在处理的过程中需要装载的帧号应该是由外界指定的 
	//当指定的帧号不合法时,就装载当前帧作为默认值 
 
	// 获得当前帧的图象文件名 
	CString strTempFileName; 
	strTempFileName=GetFileName(m_FileName, m_nCurrentFrame); 
	 
	CFile fileOpen; 
     
	fileOpen.Open(_T(strTempFileName),CFile::modeRead); 
 
	m_hDIB = ::ReadDIBFile(fileOpen); 
	 
	LPSTR pDIB = (LPSTR) ::GlobalLock((HGLOBAL) m_hDIB); 
	 
	InitDIBData(); 
 
	// 图象的宽度 
	m_ImageWidth= ::DIBWidth(pDIB);	 
	 
	// 图象的高度 
	m_ImageHeight= ::DIBHeight(pDIB); 
 
	return TRUE; 
} 
//得到文件的路径名 
void CTrackMotion::SetFileName(CString StrFilePathName) 
{ 
	m_FileName=StrFilePathName; 
} 
//得到当前帧 
void CTrackMotion::SetCurrentFrame(int nCurrentFrame) 
{ 
	m_nCurrentFrame=nCurrentFrame; 
	m_nBeginFrame=nCurrentFrame; 
} 
 
void CTrackMotion::InitDIBData() 
{ 
	if (m_palDIB != NULL) 
	{ 
		delete m_palDIB; 
		m_palDIB = NULL; 
	} 
	if (m_hDIB == NULL) 
	{ 
		return; 
	} 
	//创建文档尺寸 
	LPSTR lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) m_hDIB); 
	if (::DIBWidth(lpDIB) > INT_MAX ||::DIBHeight(lpDIB) > INT_MAX) 
	{ 
		::GlobalUnlock((HGLOBAL) m_hDIB); 
		::GlobalFree((HGLOBAL) m_hDIB); 
		m_hDIB = NULL; 
		CString strMsg; 
		AfxMessageBox("文件太大,不能打开"); 
		return; 
	} 
	::GlobalUnlock((HGLOBAL) m_hDIB); 
	//创建拷贝调色板 
	m_palDIB = new CPalette; 
	if (m_palDIB == NULL) 
	{ 
		// 释放内存 
		::GlobalFree((HGLOBAL) m_hDIB); 
		m_hDIB = NULL; 
		return; 
	} 
	if (::CreateDIBPalette(m_hDIB, m_palDIB) == NULL) 
	{ 
		delete m_palDIB; 
		m_palDIB = NULL; 
		return; 
	} 
} 
 
void CTrackMotion::ReplaceHDIB(HDIB hDIB) 
{ 
	if (m_hDIB != NULL) 
	{ 
		::GlobalFree((HGLOBAL) m_hDIB); 
	} 
	m_hDIB = hDIB; 
} 
 
void CTrackMotion::SetEndFrame(int nEndFrame) 
{ 
	m_nEndFrame=nEndFrame; 
} 
void CTrackMotion::MotionTrack(int CurrentFrame) 
{ 
	int nImageWidth=m_ImageWidth; 
	int nImageHeight=m_ImageHeight; 
 
	unsigned char* pdata=new unsigned char[nImageWidth*nImageHeight]; 
	 
    m_nCurrentFrame=CurrentFrame; 
	if(!LoadDibSeq()){return ;} 
	LPSTR    lpDIBHdr;            // 指向BITMAPINFOHEADER的指针 
	LPSTR    lpDIBBits;           // 指向一个DIB位 
	//检查DIB句柄是否有效 
	if (m_hDIB == NULL)return ; 
	//锁住DIB,取得一个起始指针 
	lpDIBHdr  = (LPSTR) ::GlobalLock((HGLOBAL) m_hDIB); 
	lpDIBBits = ::FindDIBBits(lpDIBHdr); 
	// 然后将数据取出,存放在pUnchTemp1中 
	memcpy(pdata,lpDIBBits,nImageWidth*nImageHeight*sizeof(unsigned char));	 
	::GlobalUnlock((HGLOBAL) m_hDIB); 
     
    //寻找头的坐标点 
    int SearchLineBegin=sh.m_head.Point.y; 
	int SearchLineEnd=sh.m_neck.Point.y; 
	int SearchcolBegin=0; 
	int SearchcolEnd=0; 
    unsigned char tmp; 
	for(int i=SearchLineBegin;iSelectObject(&pen); 
	for(int i=0;i<57;i++) 
	{ 
	Pos=m_JointP[0].GetAt(i); 
	Pos.Offset(-4,-82); 
	pDC->MoveTo(Pos); 
	 
    Pos=m_JointP[0].GetAt(i); 
	Pos.Offset(-4,-61); 
	pDC->LineTo(Pos); 
 
	Pos=m_JointP[0].GetAt(i); 
	Pos.Offset(0,-55); 
	pDC->LineTo(Pos); 
 
	pDC->LineTo(m_JointP[0].GetAt(i)); 
	 
	pDC->LineTo(m_JointP[1].GetAt(i)); 
	pDC->LineTo(m_JointP[2].GetAt(i)); 
	pDC->LineTo(m_JointP[3].GetAt(i)); 
	 
	 
	pDC->MoveTo(m_JointP[0].GetAt(i)); 
	pDC->LineTo(m_JointP[4].GetAt(i)); 
	pDC->LineTo(m_JointP[5].GetAt(i)); 
	pDC->LineTo(m_JointP[6].GetAt(i)); 
	 
	CPen pen1(PS_SOLID,4,RGB(0,255,0)); 
	pDC->SelectObject(&pen1); 
	} 
} 
 
/************************************************************************* 
 * 
 * 函数名称: 
 *   HprojectDIB() 
 * 
 * 参数: 
 *   LPSTR lpDIBBits    - 指向源DIB图像指针 
 *   LONG  lWidth       - 源图像宽度(象素数) 
 *   LONG  lHeight      - 源图像高度(象素数) 
 * 
 * 返回值: 
 *   BOOL               - 运算成功返回TRUE,否则返回FALSE。 
 * 
 * 说明: 
 * 该函数用于对两幅图像进行水平投影运算。 
 *  
 * 要求目标图像为只有0和255两个灰度值的灰度图像。 
 ************************************************************************/ 
 
BOOL CTrackMotion::HprojectDIB(LPSTR lpDIBBits,LONG lWidth, LONG lHeight) 
{ 
	 
	// 指向源图像的指针 
	LPSTR	lpSrc; 
	 
	// 指向缓存图像的指针 
	LPSTR	lpDst; 
	 
	// 指向缓存DIB图像的指针 
	LPSTR	lpNewDIBBits; 
	HLOCAL	hNewDIBBits; 
 
	//循环变量 
	long i; 
	long j; 
 
	//图像中每行内的黑点个数 
	long lBlackNumber; 
 
	//像素值 
	unsigned char pixel; 
 
	// 图像每行的字节数 
	LONG lLineBytes; 
 
	// 暂时分配内存,以保存新图像 
	hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight); 
 
	if (hNewDIBBits == NULL) 
	{ 
		// 分配内存失败 
		return FALSE; 
	} 
	 
	// 锁定内存 
	lpNewDIBBits = (char * )LocalLock(hNewDIBBits); 
 
	// 初始化新分配的内存,设定初始值为255 
	lpDst = (char *)lpNewDIBBits; 
	memset(lpDst, (BYTE)255, lWidth * lHeight); 
 
	// 计算图像每行的字节数 
	lLineBytes = WIDTHBYTES(lWidth * 8); 
 
	for (j = 0;j < lHeight ;j++) 
	{ 
		lBlackNumber = 0; 
		for(i = 0;i < lWidth ;i++) 
		{ 
			// 指向源图像倒数第j行,第i个象素的指针			 
			lpSrc = (char *)lpDIBBits + lLineBytes * j + i; 
	 
			pixel = (unsigned char)*lpSrc; 
 
			if (pixel != 255 && pixel != 0) 
			{ 
				return false; 
			} 
			if(pixel == 0) 
			{ 
				lBlackNumber++; 
			} 
		} 
		for(i = 0;i < lBlackNumber ;i++) 
		{	 
			// 指向目标图像倒数第j行,第i个象素的指针			 
			lpDst = (char *)lpNewDIBBits + lLineBytes * j + i; 
 
			*lpDst = (unsigned char)0; 
		}		 
	} 
 
			 
	// 复制投影图像 
	memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight); 
 
	// 释放内存 
	LocalUnlock(hNewDIBBits); 
	LocalFree(hNewDIBBits); 
 
	// 返回 
	return TRUE; 
} 
 
/************************************************************************* 
 * 
 * 函数名称: 
 *   VprojectDIB() 
 * 
 * 参数: 
 *   LPSTR lpDIBBits    - 指向源DIB图像指针 
 *   LONG  lWidth       - 源图像宽度(象素数) 
 *   LONG  lHeight      - 源图像高度(象素数) 
 * 
 * 返回值: 
 *   BOOL               - 运算成功返回TRUE,否则返回FALSE。 
 * 
 * 说明: 
 * 该函数用于对两幅图像进行垂直投影运算。 
 *  
 * 要求目标图像为只有0和255两个灰度值的灰度图像。 
 ************************************************************************/ 
 
BOOL CTrackMotion::VprojectDIB(LPSTR lpDIBBits,LONG lWidth, LONG lHeight) 
{ 
	 
	// 指向源图像的指针 
	LPSTR	lpSrc; 
	 
	// 指向缓存图像的指针 
	LPSTR	lpDst; 
	 
	// 指向缓存DIB图像的指针 
	LPSTR	lpNewDIBBits; 
	HLOCAL	hNewDIBBits; 
 
	//循环变量 
	long i; 
	long j; 
 
	//图像中每行内的黑点个数 
	long lBlackNumber; 
 
	//像素值 
	unsigned char pixel; 
 
	// 图像每行的字节数 
	LONG lLineBytes; 
 
	// 暂时分配内存,以保存新图像 
	hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight); 
 
	if (hNewDIBBits == NULL) 
	{ 
		// 分配内存失败 
		return FALSE; 
	} 
	 
	// 锁定内存 
	lpNewDIBBits = (char * )LocalLock(hNewDIBBits); 
 
	// 初始化新分配的内存,设定初始值为255 
	lpDst = (char *)lpNewDIBBits; 
	memset(lpDst, (BYTE)255, lWidth * lHeight); 
 
	// 计算图像每行的字节数 
	lLineBytes = WIDTHBYTES(lWidth * 8); 
 
	for (i = 0;i < lWidth ;i++) 
	{ 
		lBlackNumber = 0; 
		for(j = 0;j < lHeight ;j++) 
		{ 
			// 指向源图像倒数第j行,第i个象素的指针			 
			lpSrc = (char *)lpDIBBits + lLineBytes * j + i; 
	 
			pixel = (unsigned char)*lpSrc; 
 
			if (pixel != 255 && pixel != 0) 
			{ 
				return false; 
			} 
			if(pixel == 0) 
			{ 
				lBlackNumber++; 
			} 
		} 
		for(j = 0;j < lBlackNumber ;j++) 
		{	 
			// 指向目标图像倒数第j行,第i个象素的指针			 
			lpDst = (char *)lpNewDIBBits + lLineBytes * j + i; 
 
			*lpDst = (unsigned char)0; 
		}		 
	} 
 
			 
	// 复制投影图像 
	memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight); 
 
	// 释放内存 
	LocalUnlock(hNewDIBBits); 
	LocalFree(hNewDIBBits); 
 
	// 返回 
	return TRUE; 
}