📄 detectandtrackdlg.cpp
字号:
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 + -