//模糊C聚类(Mahalanobis距离)的程序实现
//1、屏幕输入项为RULE_NUM Max_ITE FU_GRADE BAND 图像行列数ROW COL图像文件i512_6band.raw
//2、输出项:聚类结果图:clusterResult.raw;聚类中心:Cluster_center.raw.txt
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#define RULE_NUM 4
#define Max_ITE 200
#define FU_GRADE 2
#define error 0.00001
#define BAND 4
double Random(double f)
{
double r;
r=(f*rand())/RAND_MAX;
if(r>=f) r=f;
return r;
}
void main()
{
long i,j,k,l,IT;
long NumPatterns,ROW,COL;//样本数
long ID_center[RULE_NUM];//记录聚类中心所属的类
long *I;//聚类中心或规则中心所对应的样本编号,-1表示无样本与其对应
long *Labclass;//存入分类结果
unsigned char *A;
float **band,**NumData,*result_image,lastv,f_temp;
double err,U_SUM,ZI,Dij,Dik,Dequ,best,dist;
double **OLD_U;//OLD_U[NumPatterns][RULE_NUM];旧的模糊隶属度
double **U;//U[NumPatterns][RULE_NUM];模糊隶属度subjection
double **Rule_Center;//Rule_Center[RULE_NUM][BAND];存放聚类中心的位置
FILE *fp,*cluster_center,*fresult_class;
printf("屏幕输入图像行列数:\n");
scanf("%d%d",&ROW,&COL);//屏幕输入图像行列数;
NumPatterns=ROW*COL;
for(i=0;i<RULE_NUM;i++)
ID_center[i]=-1;//初始化类别信息
A=new unsigned char[RULE_NUM];
for(i=0;i<RULE_NUM;i++)
A[i]=0;
I=new long[RULE_NUM];
for(i=0;i<RULE_NUM;i++)
I[i]=0;
band=new float*[BAND];
for(i=0;i<BAND;i++)
band[i]=new float[NumPatterns];
NumData=new float*[NumPatterns];
for(i=0;i<NumPatterns;i++)
NumData[i]=new float[BAND];
Labclass=new long[NumPatterns];// 空间大小等于样本数,开辟空间记录神经元所属类别
for(i=0;i<NumPatterns;i++)
Labclass[i]=-1;
result_image=new float[NumPatterns];
for(i=0;i<NumPatterns;i++)
result_image[i]=0;
//往通道输入数据
fp=fopen("i512_6band.raw","rb");
if(fp==NULL)
{
printf("无此i512_6band.raw文件!\n");
return;
}
printf("文件打开成功\n");
for(i=0;i<BAND-1;i++)
{
fread(band[i],4,NumPatterns,fp);
fseek(fp,NumPatterns*4*(i+1),SEEK_SET);
}
fread(band[BAND-1],4,NumPatterns,fp);
fclose(fp);
for(j=0;j<BAND;j++)//NumData中输入全部样本
for(i=0;i<NumPatterns;i++)
NumData[i][j]=band[j][i];
OLD_U=new double*[NumPatterns];
for(i=0;i<NumPatterns;i++)
OLD_U[i]=new double[RULE_NUM];
U=new double*[NumPatterns];//模糊规则对样本适合度数组
for(i=0;i<NumPatterns;i++)
U[i]=new double[RULE_NUM];
Rule_Center=new double*[RULE_NUM];//模糊规则中心向量数据
for(i=0;i<RULE_NUM;i++)
Rule_Center[i]=new double[BAND];
//初始化隶属度矩阵
for(i=0;i<NumPatterns;i++)//遍历全部样本
{
U_SUM=0.0;
for(j=0;j<RULE_NUM-1;j++)//遍历全部规则
{
U[i][j]=Random(1000-1000*U_SUM)/1000.0;//初始化模糊规则对每个训练样本的隶属度
OLD_U[i][j]=U[i][j];
U_SUM=U_SUM+U[i][j];//每一行减1个的隶属度相加
}
U[i][j]=1-U_SUM;
OLD_U[i][j]=U[i][j];
}
//求模糊规则的RULE_NUM个中心,其维数为BAND
IT=0;//循环变量
lastv=0;
do
{
for(k=0;k<RULE_NUM;k++)
{
f_temp=0;
for(i=0;i<BAND;i++)//遍历样本维数
{
ZI=0.0;//记录分母部分
Rule_Center[k][i]=0.0;
for(j=0;j<NumPatterns;j++)//遍历全部样本
{
Rule_Center[k][i]=Rule_Center[k][i]+NumData[j][i]*pow(U[j][k],FU_GRADE);//pow函数的两个参量是实数
ZI=ZI+pow(U[j][k],FU_GRADE);
}
Rule_Center[k][i]=Rule_Center[k][i]/ZI;//聚类中心或聚类原型
}
}
// 将样本划分到各个类
for(i=0;i<RULE_NUM;i++)
//求I[k]:{i|1<=i<=C,Dik=0}
{
I[i]=-1;//初始默认值是-1
Dequ=0.0;
for(k=0;k<NumPatterns;k++)
{
for(j=0;j<BAND;j++)
Dequ=Dequ+pow(Rule_Center[i][j]-NumData[k][j],2);//记录误差平方
if(Dequ<error)
{
I[i]=k;
//printf("这里有一个I[%d]=%d",i,k);
}
}
}
//计算新的隶属度矩阵
float J=0.0;
for(i=0;i<NumPatterns;i++)
for(j=0;j<RULE_NUM;j++)
{
if(I[j]==-1)//没有样本与聚类中心对应,多数情况
{
//Uij,i是样本数,j是聚类个数
for(k=0;k<RULE_NUM;k++)
{
Dij=0;
Dik=0;
for(l=0;l<BAND;l++)
{
Dij=Dij+(NumData[i][l]-Rule_Center[j][l])*(NumData[i][l]-Rule_Center[j][l]);
Dik=Dik+(NumData[i][l]-Rule_Center[k][l])*(NumData[i][l]-Rule_Center[k][l]);
}
U[i][j]=U[i][j]+pow(Dij/Dik,1/(FU_GRADE-1));
}
U[i][j]=1/U[i][j];
//计算Uij结束
}
else if(I[j]==i)
U[i][j]=1.0;
else U[i][j]=0.0;
}
for(i=0;i<NumPatterns;i++)
{
for(j=0;j<RULE_NUM;j++)
{
for(l=0;l<BAND;l++)
{
f_temp+=pow(U[i][j],FU_GRADE)*pow(NumData[i][l]-Rule_Center[j][l],2);
}
}
}
err=fabs(f_temp-lastv);
lastv=f_temp;
IT++;
} while((IT++<Max_ITE)&&(err>error));//循环终止条件
/* //加入聚类中心所属类别信息,然后按类别1,2,3,4的顺序输出
for(i=0;i<NumPatterns;i++)//计算最小距离
{
best=1.0e99;
for(k=0;k<RULE_NUM;k++)
{
dist=0;
for(j=0;j<BAND;j++)
dist+=(band[j][i]-Rule_Center[k][j])*(band[j][i]-Rule_Center[k][j]);
if(best>dist)
{
best=dist;
Labclass[i]=k;//这里有最小距离的为所属的类,加距离阈值后产生不可分的类别
}
}
}*/
for(i=0;i<RULE_NUM;i++)
{
for(j=0;j<NumPatterns;j++)
{
result_image[j]=U[j][i];
}
}
fresult_class=fopen("clusterResult.raw","wb");
fwrite(result_image,4,NumPatterns,fresult_class);
fclose(fresult_class);
/* //输出聚类中心
cluster_center=fopen("cluster_center.txt","wb");
if(cluster_center==NULL)exit(1);
for(k=0;k<RULE_NUM;k++)
{
for(i=0;i<BAND;i++)
{
fprintf(cluster_center,"%1f",Rule_Center[k][j]);
}
fprintf(cluster_center,"\n");
}
fclose(cluster_center);*/
for(i=0;i<NumPatterns;i++)
delete[]NumData[i];
delete[]NumData;
for(i=0;i<BAND;i++)
delete[]band[i];
delete[]band;
delete[]Labclass;
for(i=0;i<RULE_NUM;i++)
delete[]OLD_U[i];
delete[]OLD_U;
for(i=0;i<RULE_NUM;i++)
delete[]U[i];
delete[]U;
for(i=0;i<RULE_NUM;i++)
delete[]Rule_Center[i];
delete[]Rule_Center;
delete[]result_image;
delete[]A;
delete[]I;
}