4.4.3 模糊聚类

编程实现

[1] 在类CCluster中添加函数FuzzyCluster(),进行有关图像的模糊聚类。具体实现代码如代码4-4所示。

代码4-4 FuzzyCluster()函数

        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];
            return;
            distype=julizl; //此处为声明模糊距离的总类
            //得到初始模糊距离
            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;
            DLGmohu1 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;
        }
        void CCluster::huasz(int p,int q,int t)
        {
            int tmp;tmp=p;   p=q;q=tmp;///////////////////////////////////////////////
            int i,j;
            for(i=0;i<16;i++)
                for(j=0;j<16;j++)
                        *(m_pData+(height-(i+p))*wide+j+q)=sz[t][(15-i)*16+j]*255;
        }

[2] 上述代码中,GetDistance ()函数用于返回模糊距离数组中第i行第j列的模糊积,该函数的实现代码如代码4-5所示。

代码4-5 GetDistance ()函数

        double CCluster::GetDistance(double *dis, int i, int j)
        {
            double result;
            result=0;
            for(int t=0;t<patternnum;t++)
            {
                double td=dis[i*patternnum+t]<dis[t*patternnum+j]? dis[i*patternnum+t]:dis[t*patternnum+j];
                if (result<td)
                    result=td;
            }
            return result;
        }