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

📄 patternview.cpp

📁 本人的模式识别课程VC源程序
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	}
	for(k = 0; k < iShuMu; k++)
	{
		 samplecen[k].cx = sumcencx[k]/sumnum[k];
         samplecen[k].cy = sumcency[k]/sumnum[k];
	}

	//第四步:判断迭代算法的结束
	
	for(k = 0; k < iShuMu; k++)
	{
		if(samplecen[k].cx != oldprecen[k].cx || samplecen[k].cy != oldprecen[k].cy )
		{               
			oldprecen[k] = samplecen[k];
			//初始化样本中心点是否显示
            samplecen[k].fseek = true;
			OnDraw(pDC);
			//显示文本
	        CFont MyFont;
	        MyFont.CreateFont(25,0,0,0,400,FALSE,FALSE,0,
		                       ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,
		                       DEFAULT_QUALITY,DEFAULT_PITCH|FF_SWISS,"楷体_GB2312");
	        CFont* pOldFont=pDC->SelectObject(&MyFont);
            pDC->SetBkMode(TRANSPARENT);
	        pDC->SetTextColor(RGB(255,0,255));
		     char number1[80];
             char number2[80];
           	sprintf(number1,"迭代次数:%d",n - 1);//显示" 第n - 1次迭代!";number1为要输出字符的CString对象
            sprintf(number2,"指定的聚类中心数:k=%d",iShuMu);
			pDC->TextOut(550,10,number1);
            pDC->TextOut(250,10,number2);
	        MyFont.DeleteObject();
		    //是否显示中心点
			bshowcen = true;
			Sleep(50);
		goto lab1;		
		}		 
	}
	delete [] oldprecen;
	bshowcen = false;	
	
}

void CPatternView::OnIsodata() 
{
	// TODO: Add your command handler code here
    bshowcen = true;
	CDC* pDC;
	pDC=GetDC();
	//局部变量
	int i, j ,k;
	SampleDot *oldprecen;
	oldprecen = new SampleDot[15];

	//初始化所有样本点的颜色
	for(i=0;i < iShuMu;i++)   
	{
		for(j=0;j < iDianShu;j++)
		{
			samplenum[i*iDianShu+j].colorvalue = RGB(255,0,0);
		}
	}
	//初始化样本中心点是否显示
    for(i=0;i < 10;i++)
	{
		samplecen[i].fseek = true;
	}
	
	//////////////////////////////////////////////////////////
	//第一步:初始化预选参数
	int iK, iL, iI ,iSetaN;
	float fSetaS, fSetaC;
	// 创建对话框
	CDlgIsodata dlgPara;		
	// 显示对话框,提示用户设定用户参数
	if (dlgPara.DoModal() != IDOK)
	{
		// 返回
		return;
	}
	iK = dlgPara.m_iK;
	iSetaN = dlgPara.m_iSetaN;
    fSetaS = dlgPara.m_fSetaS;
	fSetaC = dlgPara.m_fSetaC;
	iL = dlgPara.m_iL;
	iI = dlgPara.m_iI;   
	//迭代次数的记录值
	int iterativenum = -1;
	//记录中心点数规定值
	int iknum = iK;
	// 删除对话框
	delete dlgPara;	
	//初始化前iK个中心点
	for(i=0;i < iK;i++)
	{
		oldprecen[i] = samplenum[i];
	}
	//////////////////////////////////////////////////////////
	//第二步:分配样本点(将所有样本点分配给最近的iK个聚类)	
step2:
	//迭代次数的累计
	iterativenum++;	
	float olddis , newdis;
/////////////////////////////////////////////////////////////////////////////////////////////////
	//开始搜索,初始化所有未归类的样本点
	for(i=0;i<iShuMu;i++)   
	{
		for(j=0;j<iDianShu;j++)
		{
			samplenum[i*iDianShu+j].fseek = true;
		}
	}
/////////////////////////////////////////////////////////////////////////////////////////////////////
    for(i=0;i<iShuMu * iDianShu;i++)//将所有的点按最小距离分成iK类
	{        
		   olddis = 2000;
		   for(j=0;j < iK;j++)
		   {			
			newdis = sqrt((samplenum[i].cx - oldprecen[j].cx) * (samplenum[i].cx - oldprecen[j].cx) 
			            + (samplenum[i].cy - oldprecen[j].cy) * (samplenum[i].cy - oldprecen[j].cy));
			if(newdis < olddis)
				{
			    	olddis = newdis;
			        samplenum[i].k = j;
				    samplenum[i].colorvalue = RGB(255*3/(j+1)%255,255*14/(j+1)%255,255*21/(j+1)%255);
                    
				}  
            
		}
  
	}
	OnDraw(pDC);
	CFont MyFont;
	MyFont.CreateFont(30,0,0,0,400,FALSE,FALSE,0,
	                   ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,
	                   DEFAULT_QUALITY,DEFAULT_PITCH|FF_SWISS,"楷体_GB2312");
	CFont* pOldFont=pDC->SelectObject(&MyFont);
    pDC->SetBkMode(TRANSPARENT);
	pDC->SetTextColor(RGB(255,0,255));
	char number[80];   
	sprintf(number,"迭代次数:%d",iterativenum);  
	pDC->TextOut(600,20,number);   
	MyFont.DeleteObject();
	//是否显示中心点
	bshowcen = true;
	Sleep(20); 
	///////////////////////////////////////////////////////////////
//	第三、四步:修正各聚类中心值并放置于oldprecen[i]及
//	判断iK个聚类中的每一聚类样本数是否小于iSetaN,否则iK-1,取消该样本子集
	int   sumnum[10] = {0,0,0,0,0,0,0,0,0,0};
	float sumcencx[10] = {0,0,0,0,0,0,0,0,0,0};
	float sumcency[10] = {0,0,0,0,0,0,0,0,0,0};	
    float L;
	for(i = 0; i < iShuMu*iDianShu; i++)
	{
		for(k = 0; k < iK; k++)
		{
			if(samplenum[i].k == k)
			{
				sumcencx[k] = samplenum[i].cx + sumcencx[k];
			    sumcency[k] = samplenum[i].cy + sumcency[k];
				sumnum[k]++;
			}		
		}
	}
    for(k = 0; k < iK; k++)
	{
		 samplecen[k].cx = sumcencx[k]/sumnum[k];
         samplecen[k].cy = sumcency[k]/sumnum[k];
	}
	
    //赋值   
	for(i=0;i < iK;i++)
	{
		oldprecen[i] = samplecen[i];
	}
//第三步:判断iK聚类中的样本数是否小于iSetaN,否则iK-1
	SampleDot*tempnum;
	tempnum = new SampleDot[16];
   	int   oldclass[10] = {0,0,0,0,0,0,0,0,0,0};
	int iNewK = -1;     
    //判断类内样本数是否小于iSetaN
	for(k = 0; k < iK; k++)
	{
		if(sumnum[k] < iSetaN)//取消该样本子集
		{       
				
			for(i = 0; i < iShuMu*iDianShu; i++)
			{
				if(samplenum[i].k == k)
				{
					samplenum[i].colorvalue = RGB(255,0,0);
                    samplenum[i].fseek = false;
				}
			}
		}
		else
          iNewK++;
          tempnum[iNewK] =oldprecen[k]; // tempnum[iNewK]用于放置新的聚类的中心点从0到 iNewK  
          oldclass[k]=iNewK;//oldclass[k]用于放置原本是第K类现在变成第iNewK类

	}
  for(i = 0; i < iShuMu*iDianShu; i++)//重新将样本点归类从从0到 iNewK进行归类
	{
		if(samplenum[i].fseek = true)//类内样本数大于iSetaN的聚类
		{
			samplenum[i].k = oldclass[k];//samplenum[i].k为NewK的值(NewK最大为iK)
		}
	}
 
	//修正各聚类中心值(0到iK-1为新的聚类数)
       iK=iNewK+1;   
	   for(i=0;i < iK;i++)		 
	   {
		   oldprecen[i] =tempnum[i];// tempnum[i]用于放置新的聚类的中心点从0到 iNewK  
	   }

	//判断显示的中心点
    for(i = 0; i < iK; i++)
	{
		samplecen[i] = oldprecen[i];
		samplecen[i].fseek = true;
	}
	for(i = iK; i < iShuMu; i++)
	{
		samplecen[i].fseek = false;
	}
    
	//OnDraw(pDC);//会导致字体无法显示
	////////////////////////////////////////////////////////////////
	//第五步:计算各聚类域中样本离聚类中心的平均距离
	float cenkdis[15];
	float  cenkavdis[15];
	for(k = 0; k < iK; k++)
	{
		sumnum[k] = 0;
		cenkdis[k] = 0;
	}	
	for(i = 0;i < iShuMu * iDianShu;i++)
	{
       if(samplenum[i].fseek = true)
		{for(k = 0;k < iK;k++)
		   {
			if(samplenum[i].k == k)
			{	olddis = sqrt((samplenum[i].cx - oldprecen[k].cx) * (samplenum[i].cx - oldprecen[k].cx) 
			            + (samplenum[i].cy - oldprecen[k].cy) * (samplenum[i].cy - oldprecen[k].cy));
                cenkdis[k] = olddis + cenkdis[k];
				sumnum[k]++;	
			 }	    	
			}			
		}
	}
	for(k = 0;k < iK;k++)
    {
		cenkavdis[k]=cenkdis[k]/sumnum[k];
	}
	//////////////////////////////////////////////////////////////////////
	//第六步:计算全部样本对相应聚类中心之间的平均距离
	float cenavdis = 0;
    int totalnum=0;
    for(k = 0; k < iK; k++)
	{
		totalnum= sumnum[k] + totalnum ; 
	}

	for(k = 0; k < iK; k++)
	{
		cenavdis = cenkdis[k] + cenavdis ; 
	}
    cenavdis = cenavdis / totalnum;
	//////////////////////////////////////////////////////////////////////
	//第七步:判断下一步作分裂,合并及迭代运算等步骤
	//判断迭代运算是否已达到规定值
	if(iterativenum == iI)
	{
		fSetaC = 0;
		goto step11;
	}
	//判断预测中心点数是否小于规定值的一半	//记录中心点数规定值
	//int iknum = iK即iknum放置预期的聚类中心数目;
    if(iK <= iknum/2)
		goto step8;
	//判断预测中心点数是否大于规定值的两倍
 
	if(iterativenum%2==0 || iK >= 2 * iknum)
		goto step11;
    //////////////////////////////////////////////////////////////////////////
	//第八步:计算每个聚类中样本距离的标准差向量(二维)
step8://分裂处理:
	float totalx[15],totaly[15];//二维空间
	float maxstand[15];
	for(i = 0;i < iK;i++)
	{
		totalx[i] = 0.0;
		totaly[i] = 0.0;
		maxstand[i] = 0.0;
	}
	for(k = 0; k < iK; k++)
	{
		sumnum[k] = 0;		
	}
	for(i = 0;i < iShuMu * iDianShu;i++)
	{
      if(samplenum[i].fseek = true)
	  {
		totalx[samplenum[i].k]+=(samplenum[i].cx-samplecen[samplenum[i].k].cx)*(samplenum[i].cx-samplecen[samplenum[i].k].cx);
		totaly[samplenum[i].k]+=(samplenum[i].cy-samplecen[samplenum[i].k].cy)*(samplenum[i].cy-samplecen[samplenum[i].k].cy);
	    sumnum[samplenum[i].k]++;
	  }//
	}
	////////////////////////////////////////////////////////////////////////
	//第九步:求每个标准差向量中的最大值
	
	for(i = 0;i < iK;i++)
	{
		totalx[i] = sqrt(totalx[i]/sumnum[i]);
		totaly[i] = sqrt(totaly[i]/sumnum[i]);
		if(totalx[i] >= totaly[i])
			maxstand[i] = totalx[i];
		else 
		    maxstand[i] = totaly[i];
	}
	////////////////////////////////////////////////////////////////////////////
	//第十步:分裂运算
	for(i = 0;i < iK;i++)
	{
		if(maxstand[i] > fSetaS)
		{
			if(((cenkavdis[i] > cenavdis) && (sumnum[i] > 2 * (iSetaN + 1)))||(iK <= iknum/2))
			{
				samplecen[i].cx = samplecen[i].cx - 0.8 * maxstand[i];
				//samplecen[i].cy = samplecen[i].cy - 0.8 * maxstand[i];
				oldprecen[i] = samplecen[i];
				samplecen[iK].cx = samplecen[iK].cx + 0.8 * maxstand[i];
				//samplecen[iK].cy = samplecen[iK].cy + 0.8 * maxstand[i];
                oldprecen[iK] = samplecen[iK];
				samplecen[iK].fseek = true;                
				iK++;
		        goto step2;
			}
		}
	}	
	////////////////////////////////////////////////////////////////////////////
	//第十一步:计算各聚类中心距离
step11:
	float cenredis[20][20];
	for(i = 0;i <iK ;i++)//0到iK-1
	{
		for(j = i + 1;j < iK+1;j++)//i + 1到iK
		{	
			cenredis[i][j] = (oldprecen[i].cx-oldprecen[j].cx)*(oldprecen[i].cx-oldprecen[j].cx)+(oldprecen[i].cy-oldprecen[j].cy)*(oldprecen[i].cy-oldprecen[j].cy);
		}
	}
	////////////////////////////////////////////////////////////////////////////////
	//第十二步和第十三步:比较类间距离,进行合并
	int tempiK = iK;
	for(i = 0;i < tempiK ;i++)
	{
		for(j = i + 1;j < tempiK+1;j++)
		{	
			if(cenredis[i][j] < fSetaC)
			{
				samplecen[i].cx = (samplecen[i].cx * sumnum[i] + samplecen[j].cx * sumnum[j])/(sumnum[i] + sumnum[j]);
				samplecen[i].cy = (samplecen[i].cy * sumnum[i] + samplecen[j].cy * sumnum[j])/(sumnum[i] + sumnum[j]);
                oldprecen[i] = samplecen[i];
				samplecen[j].fseek = false;
				iK--;
			goto step2;
			}
		}
	}
	////////////////////////////////////////////////////////////////////////////////////
    //第十四步:判断是否迭代结束
    //判断是否找到中心点
	
	if(iterativenum < iI)
	{
		goto step2;
	}

   /* for(k = 0; k < iK; k++)
	{
		if(samplecen[k].cx == oldprecen[k].cx && samplecen[k].cy == oldprecen[k].cy)
			goto endloop;
	} 	
endloop:*/
    delete [] oldprecen;
	bshowcen = false;
	
}

⌨️ 快捷键说明

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