⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 detectandtrackdlg.cpp

📁 基于背景差分算法和C均值聚类算法的车辆检测与跟踪
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	float fYCoordinate; //Y坐标	

	for (int i=0;i<m_nCountOfGroup;i++)
	{
		fXCoordinate=0.0f;
		fYCoordinate=0.0f;
		for (int j=0;j<m_VectorOfPoints.size();j++)   //遍历像素点
		{
			if (m_VectorOfPoints[j].m_nNumOfClass==i) //与中心进行匹配
			{
				fXCoordinate+=m_VectorOfPoints[j].m_nXCoordinate*1.0f/m_VectorOfGroup[i].m_nCount;
				fYCoordinate+=m_VectorOfPoints[j].m_nYCoordinate*1.0f/m_VectorOfGroup[i].m_nCount;
			}
		}
		m_VectorOfGroup[i].m_obNewCenter.m_nXCoordinate=(int)(fXCoordinate+0.5f); //取得新中心
		m_VectorOfGroup[i].m_obNewCenter.m_nYCoordinate=(int)(fYCoordinate+0.5f);
	}
}

//聚类中心距离
float CDetectAndTrackDlg::Distance()
{
	float fDistance=0.0f;

	for (int i=0;i<m_nCountOfGroup;i++)
	{
		fDistance+=Distance(m_VectorOfGroup[i].m_obOldCenter,m_VectorOfGroup[i].m_obNewCenter);
	}
	
	return fDistance;	
}

//更改聚类中心
void CDetectAndTrackDlg::ChangeCenter()
{
	for (int i=0;i<m_nCountOfGroup;i++)
	{
		m_VectorOfGroup[i].m_obOldCenter=m_VectorOfGroup[i].m_obNewCenter;  //将新的聚类中心赋给旧的聚类中心
	}
}

//判断聚类中心似乎接近
BOOL CDetectAndTrackDlg::IsCloserCenter()
{
	const float cfCenterDistance=50.0f;  //允许的误差
	float fDistance=0.0f;
	BOOL bResult=FALSE;  //返回值

	fDistance+=Distance(m_VectorOfGroup[0].m_obOldCenter,m_VectorOfGroup[1].m_obOldCenter);
	fDistance+=Distance(m_VectorOfGroup[1].m_obOldCenter,m_VectorOfGroup[2].m_obOldCenter);
	fDistance+=Distance(m_VectorOfGroup[2].m_obOldCenter,m_VectorOfGroup[0].m_obOldCenter);
	if (fDistance<=cfCenterDistance)  //判断聚类中心的距离似乎很接近
	{
		bResult=TRUE;
	}
	return bResult;

}
/************************************************************************/
/*                     主要的响应函数                                   */
/************************************************************************/

//打开背景图像
void CDetectAndTrackDlg::OnOpenBackground() 
{
	// TODO: Add your command handler code here
	CFile File=0;
	//创建“打开”对话框
	CFileDialog dlg(TRUE,0,0,OFN_HIDEREADONLY," 位图文件|*.bmp| 所有文件|*.*||",this);
	if (dlg.DoModal()==IDOK)    //判断是否选择好图片
	{
		m_strFileName=dlg.GetPathName(); //获取选中文件的类型名
		if (!File.Open(m_strFileName,CFile::modeRead)) return;  //文件打开失败,返回
		// TODO: add loading code here
		if (m_pbtBitmap) //判断是否已经有位图打开,若有则清空
		{
			delete m_pbtBitmap;	
			Invalidate(TRUE);
		} 
		m_nLen=File.GetLength();         //获取文件长度
		m_pbtBitmap=new BYTE[m_nLen];    //开辟内存空间,用于读取位图文件
		File.Read(m_pbtBitmap,m_nLen);   //读取位图文件,并存入m_pbtBitmap
		LoadBitmap();                    //加载位图
		if (m_pbtBitmap)   //判断空间时候已开辟
		{
			if (m_pbtBitsOfBackGround)
			{				
				delete m_pbtBitsOfBackGround;
			}
			m_pbtBitsOfBackGround=new BYTE[m_nWidth*m_nHeight];
			GetPoints(m_nWidth,m_nHeight,m_pbtBits,m_pbtBitsOfBackGround);  //获取像素值数据
			m_IWBackGround.SetImage(m_nWidth,m_nHeight,m_pbtBits); //显示图像
		}
	}

	//打开新图像后数据清零
	UpdateData(TRUE);
	m_strGroupResult.Empty();
	m_nCountOfObjects=0;
	UpdateData(FALSE);
	if (m_pbtBitsOfDifference)
	{
		delete [] m_pbtBitsOfDifference;
		m_pbtBitsOfDifference=NULL;		
	}
}

//打开待检测图像
void CDetectAndTrackDlg::OnOpenDetect() 
{
	// TODO: Add your command handler code here
	CFile File=0;
	//创建“打开”对话框
	CFileDialog dlg(TRUE,0,0,OFN_HIDEREADONLY," 位图文件|*.bmp| 所有文件|*.*||",this);
	if (dlg.DoModal()==IDOK)    //判断是否选择好图片
	{
		m_strFileName=dlg.GetPathName(); //获取选中文件的类型名
		if (!File.Open(m_strFileName,CFile::modeRead)) return;  //文件打开失败,返回
		// TODO: add loading code here
		if (m_pbtBitmap) //判断是否已经有位图打开,若有则清空
		{
			delete m_pbtBitmap;	
			Invalidate(TRUE);
		} 
		m_nLen=File.GetLength();         //获取文件长度
		m_pbtBitmap=new BYTE[m_nLen];    //开辟内存空间,用于读取位图文件
		File.Read(m_pbtBitmap,m_nLen);   //读取位图文件,并存入lpBitmap
		LoadBitmap();                    //加载位图
		if (m_pbtBitmap) 
		{
			if (m_pbtBitsOfDetect)
			{
				delete m_pbtBitsOfDetect;
			}
			m_pbtBitsOfDetect=new BYTE[m_nWidth*m_nHeight];
			GetPoints(m_nWidth,m_nHeight,m_pbtBits,m_pbtBitsOfDetect);
			m_IWDetect.SetImage(m_nWidth,m_nHeight,m_pbtBits); //显示图像
		}
	}	
	//打开新图像后数据清零
	UpdateData(TRUE);
	m_strGroupResult.Empty();
	m_nCountOfObjects=0;
	if (m_pbtBitsOfDifference)
	{
		delete [] m_pbtBitsOfDifference;
		m_pbtBitsOfDifference=NULL;		
	}
	UpdateData(FALSE);
}

//做差分处理
void CDetectAndTrackDlg::OnDoDifference() 
{
	// TODO: Add your command handler code here
	if (m_pbtBitsOfBackGround==NULL||m_pbtBitsOfDetect==NULL)  //背景图片或者待检测图片没有打开
	{
		AfxMessageBox("背景图或待检测图没有打开!!");
		return;
	}	
	int i,j; //循环变量
	CSetLimit dlg;
	if (dlg.DoModal()==IDOK)   //阈值设定成功
	{
		m_nLimit=dlg.m_nLimit;  //获取设置的阈值		
	}	
	if (m_pbtBitsOfDifference)
	{
		delete [] m_pbtBitsOfDifference;
	}
    m_pbtBitsOfDifference=new BYTE[m_nHeight*m_nWidth]; //开辟空间用以存储差分数据
	
	//开辟空间用以输出差分图像
	int nByteWidth=m_nWidth*3;
	if (nByteWidth%4) 
	{
		nByteWidth+=4-(nByteWidth%4);	
	}
    BYTE *pbtOutput=new BYTE[nByteWidth*m_nHeight];	

	//遍历背景图像和待检测图像,进行差分处理
	for (i=0;i<m_nHeight;i++)  
	{
		for (j=0;j<m_nWidth;j++)
		{
			if (abs(m_pbtBitsOfDetect[i*m_nWidth+j] - m_pbtBitsOfBackGround[i*m_nWidth+j]) > m_nLimit)
			{
				m_pbtBitsOfDifference[i*m_nWidth+j]=255;   //目标
			}
			else
			{
				m_pbtBitsOfDifference[i*m_nWidth+j]=0;    //背景
			}
		}
	}
	
	PutPoints(m_nWidth,m_nHeight,pbtOutput,m_pbtBitsOfDifference);
	m_IWDifference.SetImage(m_nWidth,m_nHeight,pbtOutput);  //显示差分图像
	
	//一次差分完成后可以统计
	(CFrameWnd*)AfxGetMainWnd()->GetMenu()->EnableMenuItem(IDM_COUNT_OBJECTS,MF_ENABLED);
	delete [] pbtOutput;	//释放空间
	m_nCountOfObjects=0;
	m_strGroupResult.Empty();
	UpdateData(FALSE);
}

/************************************************************************/
/*                       对差分后图像进行处理                           */
/************************************************************************/
//预处理——腐蚀
#define Points(i,j) m_pbtBitsOfDifference[(i)*m_nWidth+(j)]

void CDetectAndTrackDlg::OnPretreatmentDilate() 
{
	// TODO: Add your command handler code here
		if (m_pbtBitsOfDifference==NULL)
	{
		AfxMessageBox("请先进行差分处理!");
		return;
	}
	BYTE *pbtPoints=new BYTE[m_nWidth*m_nHeight];   //用来做腐蚀处理
	memset(pbtPoints,255,m_nWidth*m_nHeight);       //初始化腐蚀模板
	int nByteWidth=m_nWidth*3;
	if (nByteWidth%4)
	{
		nByteWidth+=4-(nByteWidth%4);
	}
	BYTE *pbtOutput=new BYTE[nByteWidth*m_nHeight];
	//做腐蚀操作
	for (int i=1;i<m_nHeight-1;i++)
	{
		for (int j=1;j<m_nWidth-1;j++)
		{
			if ((Points(i-1,j-1)==0 && Points(i,j-1)==0 && Points(i+1,j-1)==0)&&
				(Points(i-1,j)==0   && Points(i,j)==0   && Points(i+1,j)==0)  &&
				(Points(i-1,j+1)==0 && Points(i,j+1)==0 && Points(i+1,j+1)==0))
			{
				pbtPoints[i*m_nWidth+j]=0;
			}
		}
	}
	memcpy(m_pbtBitsOfDifference,pbtPoints,m_nWidth*m_nHeight);
	PutPoints(m_nWidth,m_nHeight,pbtOutput,m_pbtBitsOfDifference);
	m_IWDifference.SetImage(m_nWidth,m_nHeight,pbtOutput);  //显示腐蚀后的图像
	Invalidate(TRUE);
	//释放空间
	delete [] pbtOutput;
	delete [] pbtPoints;
	//可以统计
	(CFrameWnd*)AfxGetMainWnd()->GetMenu()->EnableMenuItem(IDM_COUNT_OBJECTS,MF_ENABLED);
	
	
}

void CDetectAndTrackDlg::OnPretreatmentErodt() 
{
	// TODO: Add your command handler code here
	if (m_pbtBitsOfDifference==NULL)
	{
		AfxMessageBox("请先进行差分处理!");
		return;
	}
	BYTE *pbtPoints=new BYTE[m_nWidth*m_nHeight];   //用来做腐蚀处理
	memset(pbtPoints,0,m_nWidth*m_nHeight);         //初始化膨胀模板
	int nByteWidth=m_nWidth*3;
	if (nByteWidth%4)
	{
		nByteWidth+=4-(nByteWidth%4);
	}
	BYTE *pbtOutput=new BYTE[nByteWidth*m_nHeight];
	//做膨胀操作
	for (int i=1;i<m_nHeight-1;i++)
	{
		for (int j=1;j<m_nWidth-1;j++)
		{
			if ((Points(i-1,j-1)==255 && Points(i,j-1)==255 && Points(i+1,j-1)==255)&&
				(Points(i-1,j)==255   && Points(i,j)==255   && Points(i+1,j)==255)  &&
				(Points(i-1,j+1)==255 && Points(i,j+1)==255 && Points(i+1,j+1)==255))
			{
				pbtPoints[i*m_nWidth+j]=255;
			}
		}
	}
	memcpy(m_pbtBitsOfDifference,pbtPoints,m_nWidth*m_nHeight);
	PutPoints(m_nWidth,m_nHeight,pbtOutput,m_pbtBitsOfDifference);
	m_IWDifference.SetImage(m_nWidth,m_nHeight,pbtOutput);  //显示膨胀后的图像
	Invalidate(TRUE);
	//释放空间
	delete [] pbtOutput;
	delete [] pbtPoints;
	//可以统计
	(CFrameWnd*)AfxGetMainWnd()->GetMenu()->EnableMenuItem(IDM_COUNT_OBJECTS,MF_ENABLED);	
}

//以C均值算法进行聚类并给出统计结果
void CDetectAndTrackDlg::OnCountObjects() 
{
	// TODO: Add your command handler code here
	UpdateData(TRUE);
	const float fEpsilon=0.0001f; //允许的误差
	
	FilterPoints();                 //筛选出目标点
	if (m_VectorOfPoints.empty()||m_VectorOfPoints.size()<m_nCountOfObjects)   //判断是否有目标
	{
		AfxMessageBox("背景图像与待检测图像相同,请检查!");
		return;
	}
	
	InitCenter();                   //初始化聚类中心
	for(int i=0;;i++)               //循环
	{
		Allocate();                 //以聚类中心进行分类
		ReviseCenter();	            //修正聚类中心值			
		if (Distance()<fEpsilon)    //判断误差是否在允许范围内
		{
			break;                  //误差在允许范围内,循环结束         
		}
		else
		{
			ChangeCenter();	        //误差超出允许范围,改变聚类中心				
		}				
	}

    //C均值算法结束,对聚类结果进行分析,给出统计结果
	CString str;
	int *npCountOfObjects=new int[m_nCountOfGroup];  //开辟空间
	m_strGroupResult.Empty();           //文本清零
	for (i=0;i<m_nCountOfGroup;i++)
	{
		npCountOfObjects[i]=m_VectorOfGroup[i].m_nCount;
		str.Format("C%d: %d\r\n",i+1,m_VectorOfGroup[i].m_nCount);  //给出每个聚类中的像素点数目
		m_strGroupResult+=str;
	}

    //结果分析
	m_nCountOfObjects=m_nCountOfGroup;  //默认目标数目为聚类数目
	sort(npCountOfObjects,npCountOfObjects+m_nCountOfGroup);  //对像素点数进行排序		
	if (npCountOfObjects[m_nCountOfGroup-1]/npCountOfObjects[0]>6)
	{
		/*如果聚类中最多的像素点数比最少的多十倍以上,判定目标数减少一*/    
		m_nCountOfObjects--;
	}
	else
	{	/*否则判定最多与次多像素点倍数,四舍五入,增加目标数*/
		if (IsCloserCenter())
		{
			m_nCountOfObjects=1;
		}
		else
		{
			int nAddCount=(int)(npCountOfObjects[m_nCountOfGroup-1]*1.0f/npCountOfObjects[m_nCountOfGroup-2]+0.5f);
			m_nCountOfObjects+=(nAddCount-1);
		}
	}
	UpdateData(FALSE);

    //一次统计完成后,禁用统计功能
	(CFrameWnd*)AfxGetMainWnd()->GetMenu()->EnableMenuItem(IDM_COUNT_OBJECTS,MF_GRAYED);
	//释放空间
	delete [] npCountOfObjects;
}

/************************************************************************/
/*                             其余响应函数                             */
/************************************************************************/
//退出系统
void CDetectAndTrackDlg::OnExit() 
{
	// TODO: Add your command handler code here
	CDialog::OnCancel();
}

//关于对话框
void CDetectAndTrackDlg::OnAbout() 
{
	// TODO: Add your command handler code here
	CAboutDlg dlg;
	dlg.DoModal();
}
//Ok
void CDetectAndTrackDlg::OnOK() 
{
	// TODO: Add extra validation here	
}
//Cancel
void CDetectAndTrackDlg::OnCancel() 
{
	// TODO: Add extra cleanup here	
	CDialog::OnCancel();
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -