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

📄 cluster.cpp

📁 用VISUALC++编写的聚类分析程序,图像识别.(各种算法),具有非常大的价值.
💻 CPP
📖 第 1 页 / 共 4 页
字号:
	GetFeature();

	int		distype;//距离的形式(欧氏、余弦...)
	int		times;//max loop number
	int		i,j;

	DlgInfor mDlgInfor;
	mDlgInfor.ShowInfor(4);
	if (mDlgInfor.DoModal()==IDOK)
	{
		distype=mDlgInfor.m_DisType;
		times=mDlgInfor.m_Times;
		centernum=mDlgInfor.m_CenterNum;
	}
	else return;

	BOOL change=true;//退出标志,false时表示样品所属类别不再变化,中止计算
	int counter=0;//记录当前已经循环的次数
	double distance;//到各中心的距离
	distance=MAX;
	
	m_center=new Center[centernum];

	for ( i=0;i<patternnum;i++)
		m_pattern[i].distance=MAX;
	for ( i=0;i<centernum;i++)//初始化,前centernum个模版各自分为一类
	{
		m_pattern[i].category=i+1;
		m_pattern[i].distance=0;
		for ( j=0;j<N*N;j++)
			m_center[i].feature[j]=m_pattern[i].feature[j];
		m_center[i].index=i+1;
	}

	while (change && counter<times)
	{
		counter++;
		change=false;
		for( i=0;i<patternnum;i++)//对所有样品重新归类
		{
			//计算第i个模式到各个聚类中心的最小距离,
			int index=1;
			distance=MAX;
            
			for (int j=0;j<centernum;j++)
				if (distance>GetDistance(m_pattern[i],m_center[j],distype))
				{
					distance=GetDistance(m_pattern[i],m_center[j],distype);
					index=j;//找到最小距离,是到第index个聚类中心的距离
				}
			
			//比较原中心号与新中心号
			//相同:更新距离。
			//不同:1,新距离小,则归入新中心,更新距离,重新计算前后两个聚类中心模式
			//2,新距离大于原距离,不处理;
			//counter++
			if (m_pattern[i].category==m_center[index].index)//属于原类
			{
				m_pattern[i].distance=distance;
			}
			else//不属于原类
			{
				int tpcenter=m_pattern[i].category;//记录原类号
				m_pattern[i].category=m_center[index].index;//归入新类
				m_pattern[i].distance=distance;
				if(tpcenter!=0)
				{
					for (int k=0;k<centernum;k++)
						if (m_center[k].index==tpcenter)
					CalCenter(&m_center[k]);//计算原属类中心
				}
				CalCenter(&m_center[index]);//计算新属类中心
				change=true;
			}
		}
		
	}//end of while 
	delete []m_center;
}
/************************************************************
*函数名称		ISODATA()
*参数			void
*返回值		void
*函数功能		用ISODATA方法对全体样品进行分类
************************************************************/
void CCluster::ISODATA()
{
	GetFeature();
	
	int i,j;
	int      distype;
	int      times;//迭代的最多次数,用户输入
	int      precenternum;//当前类数
	double   T;//两类中心的最小距离,小于该阈值将合并
	double   equation;//类内方差阈值
	double   *avedistance;//avedistance[i]:第i+1类内平均距离,i=0,1,...,centernum.
	double   allavedis;//全部模式样本中心平均距离

	double minous,maxous,mincos,maxcos,minbcos,maxbcos,mintan,maxtan;

	minous=MAX; mincos=MAX; minbcos=MAX; mintan=MAX;
	maxous=0; maxcos=0; maxbcos=0; maxtan=0;
	//计算四种距离模式的参考值
	for (  i=0;i<patternnum-1;i++)
		for ( j=i+1;j<patternnum;j++)
		{
			if (minous>GetDistance(m_pattern[i],m_pattern[j],1))
				minous=GetDistance(m_pattern[i],m_pattern[j],1);
			if (maxous<GetDistance(m_pattern[i],m_pattern[j],1))
				maxous=GetDistance(m_pattern[i],m_pattern[j],1);

			if (mincos>GetDistance(m_pattern[i],m_pattern[j],2))
				mincos=GetDistance(m_pattern[i],m_pattern[j],2);
			if (maxcos<GetDistance(m_pattern[i],m_pattern[j],2))
				maxcos=GetDistance(m_pattern[i],m_pattern[j],2);

			if (minbcos>GetDistance(m_pattern[i],m_pattern[j],3))
				minbcos=GetDistance(m_pattern[i],m_pattern[j],3);
			if (maxbcos<GetDistance(m_pattern[i],m_pattern[j],3))
				maxbcos=GetDistance(m_pattern[i],m_pattern[j],3);
			
			if (mintan>GetDistance(m_pattern[i],m_pattern[j],4))
				mintan=GetDistance(m_pattern[i],m_pattern[j],4);
			if (maxtan<GetDistance(m_pattern[i],m_pattern[j],4))
				maxtan=GetDistance(m_pattern[i],m_pattern[j],4);
		}
	//求所有样品总方差
	double cen[N*N],equ[N*N];
	for (i=0; i<N*N; i++)
	{
		cen[i]=0;
		equ[i]=0;
	}
	for (i=0;i<patternnum;i++)//所有样品特征累加
		for (j=0;j<N*N;j++)
		    cen[j]+=m_pattern[i].feature[j];
	for (i=0;i<N*N;i++)//求所有样品特征均值
		cen[i]=cen[i]/(double)patternnum;
	for (i=0;i<patternnum;i++)//总方差
		for (j=0;j<N*N;j++)
			equ[j]+=(m_pattern[i].feature[j]-cen[j])*(m_pattern[i].feature[j]-cen[j]);
	for (i=0;i<N*N;i++)//均方差
		equ[i]=sqrt(equ[i]/(double)patternnum);
	double minequ=MAX;
	double maxequ=0.0;
	//求均方差中的最大最小值
	for (i=0;i<N*N;i++)
	{
		if (minequ>equ[i])
            minequ=equ[i];
		if (maxequ<equ[i])
			maxequ=equ[i];
	}

	DlgInfor    mDlgInfor;
//输出到对话框
	mDlgInfor.ShowInfor(minous,maxous,mincos,maxcos,minbcos,maxbcos,mintan,maxtan,minequ,maxequ);//OUTPUT EQUATIONOUT!!!
	if (mDlgInfor.DoModal()==IDOK)
	{
		distype=mDlgInfor.m_DisType;
		T=mDlgInfor.m_T;
		times=mDlgInfor.m_Times;
		equation=mDlgInfor.m_EquationIn;
		centernum=mDlgInfor.m_CenterNum;
	}
	else return;
    //所有样品各归一类
	precenternum=centernum;
	m_center=new Center[precenternum];
	for ( i=0;i<precenternum;i++)
	{
		m_pattern[i].category=i+1;
		for (j=0;j<N*N;j++)
			m_center[i].feature[j]=m_pattern[i].feature[j];
		m_center[i].index=i+1;
		m_center[i].patternnum=1;
	}

	int counter=0;//循环次数

	avedistance=new double[precenternum];

	while (++counter<times)
	{
		for ( i=0;i<patternnum;i++)//把所有样品重新归类
		{
			double td=MAX;
			int index=0;
			for (int j=0;j<precenternum;j++)
				if (td>GetDistance(m_pattern[i],m_center[j],distype))
				{
					td=GetDistance(m_pattern[i],m_center[j],distype);
					index=j;
				}
			m_pattern[i].category=m_center[index].index;
		}
		//修正各中心
		for (i=0;i<precenternum;i++)
			CalCenter(&m_center[i]);
		for (i=0; i<precenternum;i++)
		{
			if (m_center[i].patternnum==0)
			{
				for(j=i; j<precenternum-1; j++)
					m_center[j]=m_center[j+1];
				precenternum--;

			}
		}
		//计算各类距中心平均距离
		for (i=0;i<centernum;i++)
			avedistance[i]=0.0;//初始化

		allavedis=0;	//全部样本平均距离

		for (i=0;i<precenternum;i++)
		{
			int num=0;//类中成员个数
			double dis;
			dis=0.0;
			for ( j=0;j<patternnum;j++)
			{
				if (m_pattern[j].category==i+1)
				{
					++num;
					dis+=GetDistance(m_pattern[j],m_pattern[i],distype);
				}
			}
			allavedis+=dis;
			avedistance[i]=(double)(dis/(double)num);
		}

		allavedis/=patternnum;
	 
		if ((precenternum>=2*centernum) || ((counter%2)==0) && (precenternum>(int)(centernum/2+0.5)))//合并
		{
			//找到距离最近的两个类
			double td=MAX;
			int ti,tj;
			for( i=0;i<precenternum;i++)
				for ( j=i+1;j<precenternum;j++)
				{
					double tdin;
					tdin=GetDistance(m_center[i],m_center[j],distype);
					if (td<tdin)
					{
						td=tdin;
						ti=i;
						tj=j;
					}
				}
			//判断是否要合并
			if(td<T)//合并
			{
				for ( i=0;i<patternnum;i++)
				{
					if (m_pattern[i].category==m_center[tj].index)
						m_pattern[i].category=m_center[ti].index;
					if (m_pattern[i].category>m_center[tj].index)
						m_pattern[i].category--;
				}
				CalCenter(&m_center[ti]);
				for (i=tj;i<precenternum-1;i++)
				{
					m_center[i]=m_center[i+1];
					m_center[i].index--;
				}
				precenternum--;
			}
		}//end 合并
		else//分裂
		{
			double **mequation;//标准差
			int ti,tj;//记录最大标准差出现位置,第ti+1号类的第tj+1位。ti=0,1,...,precenternum-1.
			
			mequation= new double *[precenternum];
			for (i=0;i<precenternum;i++)
			{
				mequation[i]=new double[N*N];
				for (j=0;j<N*N;j++)
					mequation[i][j]=0.0;
			}
			//计算标准差
			for ( i=0;i<precenternum;i++)
			{
				for ( j=0;j<patternnum;j++)
					if (m_pattern[j].category==m_center[i].index)
					{
						for (int k=0;k<N*N;k++)
								mequation[i][k]+=(m_pattern[j].feature[k]-m_center[i].feature[k])*(m_pattern[j].feature[k]-m_center[i].feature[k]);
					}
					for (int k=0;k<N*N;k++)
						mequation[i][k]=sqrt(mequation[i][k]/m_center[i].patternnum);
			}
			//找最大标准差
			ti=0;
			tj=0;
			for (i=0;i<precenternum;i++)
				for ( j=0;j<N*N;j++)
					if(mequation[i][j]>mequation[ti][tj])
						{
							ti=i;tj=j;
						};
			//判断是否要分裂
			if (mequation[ti][tj]>equation)//大于给定阈值
			{
				if (avedistance[ti]>allavedis )
					//类平均距离大于总平均距离  分裂
				{
					precenternum++;
					Center *tempcenter;
					tempcenter=new Center [precenternum];

					for (i=0;i<precenternum-1;i++)
						tempcenter[i]=m_center[i];
					tempcenter[precenternum-1].index=precenternum;
					for (j=0;j<N*N;j++)
						tempcenter[precenternum-1].feature[j]=m_center[ti].feature[j];
					tempcenter[precenternum-1].feature[tj]-=0.5*mequation[ti][tj];
					tempcenter[ti].feature[tj]+=0.5*mequation[ti][tj];

					delete []m_center;
					m_center=tempcenter;
									
				}
			}
			delete []mequation;
		}//end 分裂
	}//end while(1)*/
	delete []avedistance;
	delete []m_center;
}

/************************************************************
*函数名称		Mohujulei()
*参数			void
*返回值		    void
*函数功能		用模糊聚类方法对全体样品进行分类
************************************************************/
void CCluster::FuzzyCluster()
{
	GetFeature();//获得所有样品特征

	double	*dis, *tempdis;
	double	dismax;
	int		i,j;
	int		distype;
	dismax=0;

	dis=new double [patternnum*patternnum];//模糊系数矩阵
	tempdis=new double [patternnum*patternnum];
	DlgFuzzyDistance  dfd;
	if (dfd.DoModal()==IDOK)
	{
		distype=dfd.mfuzzydistance;
	}
	else 
		return;
    //得到初始模糊距离
	for ( i=0; i<patternnum; i++)
		for (j=0; j<patternnum; j++)
	{
		dis[i*patternnum+j]=GetFuzzyDistance(m_pattern[i],m_pattern[j],distype);//distype
	}

   //构造等价类
	bool flag;
	flag=true;
	while (flag)
	{
		flag=false;
		for ( i=0; i<patternnum; i++)
			for ( j=0; j<patternnum; j++)
				if (i==j)//对角线为1
					tempdis[i*patternnum+j]=1;
				else
					tempdis[i*patternnum+j]=GetDistance(dis,i,j);
		for ( i=0; i<patternnum; i++)
		{
			for ( j=0; j<patternnum; j++)
				if ((tempdis[i*patternnum+j]-dis[i*patternnum+j])*(tempdis[i*patternnum+j]-dis[i*patternnum+j])>0.000001)//(tdis[i][j]!=dis[i][j])
				{
					flag=true;
					break;
				}
			if (flag)
				break;
		}
	
		for ( i=0; i<patternnum*patternnum; i++)
				dis[i]=tempdis[i];
	}
	//输出模糊矩阵
	CString ts,sout;
	//第一行标号1,2,。。。,patternnum。
	sout.Insert(sout.GetLength(),"   \t");
	for (i=1; i<=patternnum; i++)
	{
		ts.Format("%d   \t",i);
		sout.Insert(sout.GetLength(),ts);
	}
	sout.Insert(sout.GetLength(),"\n\n");

	for (i=0; i<patternnum; i++)
	{
		//每列开头标号
		ts.Format("%d   \t",i+1);
		sout.Insert(sout.GetLength(),ts);
		//输出模糊系数矩阵
		for(j=0; j<patternnum; j++)
		{
			ts.Format("%0.3f\t",dis[i*patternnum+j]);
			sout.Insert(sout.GetLength(),ts);
			if ((j+1)%patternnum==0)
				sout.Insert(sout.GetLength(),"\n\n\n");

		}
	}
	MessageBox(NULL,sout,"模糊矩阵",MB_OK);

	delete []tempdis;

	double *xishu=new double [patternnum*patternnum];
	for(i=0; i<patternnum*patternnum; i++)
		xishu[i]=-1;

	int pointer=0;
	//记录模糊系数矩阵中不同的系数
	for ( i=0; i<patternnum; i++)
		for ( j=i; j<patternnum; j++)
		{
			bool done=false;
			for (int k=0; k<pointer; k++)
			{
				if ((xishu[k]-dis[i*patternnum+j])*(xishu[k]-dis[i*patternnum+j])<0.000001)
				{
					done=true;
					break;
				}
			}
			if (!done)
			{
				xishu[pointer]=dis[i*patternnum+j];
				pointer++;
			}
		}
	
	for(i=0; i<pointer-1; i++)//对阈值由小到大排序
		for (j=0; j<pointer-i-1; j++)
		{
			if (xishu[j]>xishu[j+1])
			{
				double	temp=xishu[j];
				xishu[j]=xishu[j+1];
				xishu[j+1]=temp;
			}
		}
	CString s,str;
	for (i=0; i<pointer; i++)
	{
		s.Format("%0.4f  ",xishu[i]);
		str.Insert(str.GetLength(),s);
	}
	delete   []xishu;
	//用户输入聚类阈值
	double    yz;
	DlgMohu		mohu;
	mohu.m_Mohuxishu=str;
	if (mohu.DoModal()==IDOK)
	{
		yz=mohu.m_Mohuyuzhi;	
	}
	else return;
	
	int *result;
	//根据阈值输出聚类结果
	result=new int [patternnum*patternnum];
	for (i=0; i<patternnum*patternnum; i++)
		if (dis[i]>=yz)
			result[i]=1;
		else 
			result[i]=0;

		//分类后输出

	//第一行标号
	sout="";
	sout.Insert(-1,"每行中\"1\"对应的列为同一类");
	sout.Insert(sout.GetLength(),"\n\n");
	sout.Insert(sout.GetLength(),"   \t");
	for (i=1; i<=patternnum; i++)
	{
		ts.Format("%d   \t",i);
		sout.Insert(sout.GetLength(),ts);
	}
	sout.Insert(sout.GetLength(),"\n\n");
		

	for (i=0; i<patternnum; i++)
	{
		//每列开头标号
		ts.Format("%d   \t",i+1);
		sout.Insert(sout.GetLength(),ts);
		for(j=0; j<patternnum; j++)//首行为原模糊系数
		{
			ts.Format("%0.3f\t",dis[i*patternnum+j]);
			sout.Insert(sout.GetLength(),ts);
			if ((j+1)%patternnum==0)
				sout.Insert(sout.GetLength(),"\n");
		}
		sout.Insert(sout.GetLength(),"   \t");
		for(j=0; j<patternnum; j++)//次行为根据阈值修改后的系数“1”或“0”
		{
			ts.Format("%d\t",result[i*patternnum+j]);
			sout.Insert(sout.GetLength(),ts);
			if ((j+1)%patternnum==0)
				sout.Insert(sout.GetLength(),"\n\n");
		}
	}
	MessageBox(NULL,sout,"分类前后的矩阵对照",MB_OK);

	centernum=0;

	for (i=0; i<patternnum; i++)//按照阈值分类
		for (j=i; j<patternnum; j++)
		{
			if (result[i*patternnum+j]==1)
			{
				if (m_pattern[i].category!=0)
					m_pattern[j].category=m_pattern[i].category;
				else if (m_pattern[j].category!=0)
					m_pattern[i].category=m_pattern[j].category;
				else
				{
					centernum++;
					m_pattern[j].category=centernum;
					m_pattern[i].category=centernum;
				}
			}
		}
	delete []dis;
	delete []result;
}




⌨️ 快捷键说明

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