kmeans,FCM聚类iris和sonar数据集,以及图像分割

kmeans,FCM聚类iris和sonar数据集,以及图像分割


kmeans

问题概述
kmeans

kmeans非常好理解了,本质上其实只有三步(做可视化时候可能需要归一化我们先不说)

拿iris举例,天气太冷了,120 ( 样 本 个 数 ) _ {(样本个数)} 个小伙伴在操场上站着直哆嗦,这时,学校搬来3 ( 类 别 个 数 ) _(类别个数) ()个大火炉,我们的目的就是在同学都不动的情况下把火炉放到合适的位置,从而使得所有同学都能尽可能感受到火炉的温暖
首先,学校把火炉随机放在某个地方(当然这个地点坐标可能是二维的也可能是高维,和元素维度保持一致),即中心点初始化。
第二步,开始循环,让每个同学面向离它们最近的火炉(归类)
第三步,面向同一个火炉的同学们求出大家坐标的中心,把火炉搬到中间(更新样本中心点)
然后跳到第二步循环直到中心点啊,轮廓系数什么的收敛,或者循环次数达到某个阈值结束训练

运行效果

初始化(白色为火炉)(样本点初始化为深蓝色,颜色偏暗,可能不太容易看清楚)
在这里插入图片描述迭代一次
在这里插入图片描述在这里插入图片描述在这里插入图片描述

代码部分
结构总览

整形m用于限制算法迭代次数
bool is_iris用于切换iris和sonar数据集

int main()
{
    int m=500;
    bool is_iris=0;
    kmeans k;
    k.load_iris();
    k.load_sonar();
    k.init_kmeans(is_iris);
    while(m--)
    {
        k.sort(is_iris);
        k.reload_z(is_iris);
        cout<<k.load_sc(is_iris)<<endl;
        if(is_iris)
            k.fenxi(2,1);
        if(is_iris)    
            cv::waitKey(0);

    }
    return 0;
}
函数1载入数据load_iris(),load_sonar()

将iris和sonar数据的信息分别载入到二维数组data_iris和data_sonar中
其中每一数据的最后一维用于保存聚类后的分类信息,倒数第二维用于保存数据集原来的分类信息(用于可视化处理时作为对照)

void kmeans::load_iris()
{
    int i,m=27;
    char ch,ch_1[35];
    int high,low;
    int d[2];
    FILE *f;
    if ((f = fopen("/home/jojo/jason_cpp/iris.data", "rb+")) == NULL)
	{
		perror("fail to read");
	}
     if(f != NULL)
    {
        ch = 'a';
        while(ch != EOF)
        {
            putchar(ch);
            ch = fgetc(f);
            if(ch!='\n')ch_1[tag_a++]=ch;
            else
            {
                data_iris[tag_b++][0]=(ch_1[0]-'0')+(ch_1[2]-'0')*0.1;

                data_iris[tag_b-1][1]=(ch_1[4]-'0')+(ch_1[6]-'0')*0.1;

                data_iris[tag_b-1][2]=(ch_1[8]-'0')+(ch_1[10]-'0')*0.1;

                data_iris[tag_b-1][3]=(ch_1[12]-'0')+(ch_1[14]-'0')*0.1;
                //类别看taga(每行长度)大小
                if(tag_a==27)data_iris[tag_b-1][4]=0;
                else if(tag_a==31)data_iris[tag_b-1][4]=1;
                else data_iris[tag_b-1][4]=2;
                tag_a=0;
            }
        }
    }
    else
        printf("fail to open! \n");
    fclose(f);
    for(tag_b=0;tag_b<4;tag_b++)
    {
        yu_iris[tag_b][0]=500;
        yu_iris[tag_b][1]=-500;
    }    
    for(tag_a=0;tag_a<150;tag_a++)
    for(tag_b=0;tag_b<4;tag_b++)
    {
        if(yu_iris[tag_b][0]>data_iris[tag_a][tag_b])yu_iris[tag_b][0]=data_iris[tag_a][tag_b];
        if(yu_iris[tag_b][1]<data_iris[tag_a][tag_b])yu_iris[tag_b][1]=data_iris[tag_a][tag_b];
    }
}
void kmeans::load_sonar()
{
    int i,m=27;
    char ch,ch_1[500];
    int high,low;
    int d[2];
    FILE *f;
    	if ((f = fopen("/home/jojo/jason_cpp/sonar.txt", "rb+")) == NULL)
	{
		perror("fail to read");
	}
    char data_b[7];
     if(f != NULL)
    {
    for(tag_c=0;tag_c<208;tag_c++)
    {
        for(tag_b=0;tag_b<60;tag_b++)
        {
                data_sonar[tag_c][tag_b]=0;
                for(tag_a=0;tag_a<7;tag_a++)
                {
                    if(ch!=EOF)
                    {
                    putchar(ch);
                    ch = fgetc(f);
                    if(ch=='\n')ch = fgetc(f);
                    data_b[tag_a]=ch;
                    }
                }
                data_sonar[tag_c][tag_b]+=(data_b[0]-'0')*1;
                data_sonar[tag_c][tag_b]+=(data_b[2]-'0')*0.1;
                data_sonar[tag_c][tag_b]+=(data_b[3]-'0')*0.01;
                data_sonar[tag_c][tag_b]+=(data_b[4]-'0')*0.001;
                data_sonar[tag_c][tag_b]+=(data_b[5]-'0')*0.0001;
        }
                        putchar(ch);
                    ch = fgetc(f);
        if(ch=='R')data_sonar[tag_c][60]=0;
        else data_sonar[tag_c][60]=1;
        putchar(ch);
                    ch = fgetc(f);
    }
    }
    else
        printf("fail to open! \n");
    fclose(f);
    for(tag_b=0;tag_b<60;tag_b++)
    {
        yu_sonar[tag_b][0]=500;
        yu_sonar[tag_b][1]=-500;
    }    
    for(tag_a=0;tag_a<118;tag_a++)
    for(tag_b=0;tag_b<60;tag_b++)
    {
        if(yu_sonar[tag_b][0]>data_sonar[tag_a][tag_b])yu_sonar[tag_b][0]=data_sonar[tag_a][tag_b];
        if(yu_sonar[tag_b][1]<data_sonar[tag_a][tag_b])yu_sonar[tag_b][1]=data_sonar[tag_a][tag_b];
    }
}
函数2初始化样本中心点init_kmeans(bool is_iris)

iris数据在载入数据过程中计算了样本范围,这里将样本中心点初始化为在样本范围内的随机数,sonar直接取值0.001和0.5

void kmeans::init_kmeans(bool is_iris)
{
    if(is_iris)
    {
        point_iris[0][0]=(yu_iris[0][1]-yu_iris[0][0])*((rand()%100)/200+0.5)+yu_iris[0][0];
        point_iris[0][1]=(yu_iris[1][1]-yu_iris[1][0])*((rand()%100)/200+0.5)+yu_iris[1][0];
        point_iris[0][2]=(yu_iris[2][1]-yu_iris[2][0])*((rand()%100)/200+0.5)+yu_iris[2][0];
        point_iris[0][3]=(yu_iris[3][1]-yu_iris[3][0])*((rand()%100)/200+0.5)+yu_iris[3][0];

        point_iris[1][0]=(yu_iris[0][1]-yu_iris[0][0])*((rand()%100)/200+0.5)+yu_iris[0][0];
        point_iris[1][1]=(yu_iris[1][1]-yu_iris[1][0])*((rand()%100)/200+0.5)+yu_iris[1][0];
        point_iris[1][2]=(yu_iris[2][1]-yu_iris[2][0])*((rand()%100)/200+0.5)+yu_iris[2][0];
        point_iris[1][3]=(yu_iris[3][1]-yu_iris[3][0])*((rand()%100)/200+0.5)+yu_iris[3][0];

        point_iris[2][0]=(yu_iris[0][1]-yu_iris[0][0])*((rand()%100)/200+0.5)+yu_iris[0][0];
        point_iris[2][1]=(yu_iris[1][1]-yu_iris[1][0])*((rand()%100)/200+0.5)+yu_iris[1][0];
        point_iris[2][2]=(yu_iris[2][1]-yu_iris[2][0])*((rand()%100)/200+0.5)+yu_iris[2][0];
        point_iris[2][3]=(yu_iris[3][1]-yu_iris[3][0])*((rand()%100)/200+0.5)+yu_iris[3][0];   
    }
    else
    {
        for(tag_a=0;tag_a<60;tag_a++)
        {
            point_sonar[0][tag_a]=0.001;
            point_sonar[1][tag_a]=0.5;
        }
    }
    
}
函数3 分类函数sort(bool is_iris)

计算数据和各类中心点point_iris或point_sonars的距离,进而将数据进行归类(iris给数据第6维赋值,sonar给数据第62维赋值)
其中dis(double a[],double b[],int add_a,int add_b,int deep_a,int num)
函数用于计算a数组的第add_a行和b数组的第add_b行的前num列元素的二范数,deep_a是a数组每行拥有的列数

void kmeans::sort(bool is_iris)
{
    if(is_iris)
    {
        double(*p)[6]=data_iris;
        double(*p_1)[4]=point_iris;
        for(tag_a=0;tag_a<150;tag_a++)
        {
            if(dis(*p,*p_1,tag_a,0,6,4)<=dis(*p,*p_1,tag_a,1,6,4)&&dis(*p,*p_1,tag_a,0,6,4)<=dis(*p,*p_1,tag_a,2,6,4))
            data_iris[tag_a][5]=0;
            else if(dis(*p,*p_1,tag_a,1,6,4)<=dis(*p,*p_1,tag_a,0,6,4)&&dis(*p,*p_1,tag_a,1,6,4)<=dis(*p,*p_1,tag_a,2,6,4))
            data_iris[tag_a][5]=1;
            else data_iris[tag_a][5]=2;
        }
    }
    else
    {
        double(*p)[62]=data_sonar;
        double(*p_1)[60]=point_sonar;
        for(tag_a=0;tag_a<208;tag_a++)
        {
            //double a=dis(*p,*p_1,tag_a,0,62,60);
            //double b=dis(*p,*p_1,tag_a,1,62,60);
            if(dis(*p,*p_1,tag_a,0,62,60)>=dis(*p,*p_1,tag_a,1,62,60))
            data_sonar[tag_a][61]=0;
            else data_sonar[tag_a][61]=1;
        }

    }
    
}
函数4 更新样本中心点 reload_z(bool is_iris)

kmeans方法采用求各类均值的方式进行中心点的更新中心分别存放在数组point_iris和point_sonar中

void kmeans::reload_z(bool is_iris)
{
    if(is_iris)
    {
        //各类总数
        int number[3]={0,0,0};
        double cent[3][4]={0,0,0,0,0,0,0,0,0,0,0,0};
        for(tag_a=0;tag_a<120;tag_a++)
        {
            for(tag_b=0;tag_b<4;tag_b++)
            cent[int(data_iris[tag_a][5])][tag_b]+=data_iris[tag_a][tag_b];
            number[int(data_iris[tag_a][5])]++;   
        }
        for(tag_a=0;tag_a<3;tag_a++)
        for(tag_b=0;tag_b<4;tag_b++)
            if(number[tag_a]!=0)
            point_iris[tag_a][tag_b]=cent[tag_a][tag_b]/number[tag_a];
        
        
    }
    else
    {
                int number[2]={0,0};
        double cent[2][60];
        for(tag_a=0;tag_a<60;tag_a++)
        for(tag_b=0;tag_b<2;tag_b++)
        cent[tag_b][tag_a]=0;
        for(tag_a=0;tag_a<208;tag_a++)
        {
            for(tag_b=0;tag_b<60;tag_b++)
            cent[int(data_sonar[tag_a][61])][tag_b]+=data_sonar[tag_a][tag_b];
            number[int(data_sonar[tag_a][61])]++;   
        }
        for(tag_a=0;tag_a<2;tag_a++)
        for(tag_b=0;tag_b<60;tag_b++)
        point_sonar[tag_a][tag_b]=cent[tag_a][tag_b]/number[tag_a];
    }
    
}
函数5 计算轮廓系数

轮廓系数公式:
S ( i ) = b ( i ) − a ( i ) m a x ( b ( i ) , a ( i ) ) S_{(i)}=\frac{b_{(i)}-a_{(i)}}{max(b_{(i)},a_{(i)})} S(i)=max(b(i),a(i))b(i)a(i)
其中
a ( i ) a_{(i)} a(i) = average(i向量到所有它属于的簇中其它点的距离)
b ( i ) b_{(i)} b(i) = min (i向量到与它相邻最近的一簇内的所有点的平均距离)

double kmeans::load_sc(bool is_iris)
{
    if(is_iris)
    {
        int b_num=0,a_num=0;
        double data[120][3],dataa;
        for(tag_a=0;tag_a<120;tag_a++)
        for(tag_b=0;tag_b<3;tag_b++)
        data[tag_a][tag_b]=0;

        for(tag_a=0;tag_a<120;tag_a++)
        for(tag_b=0;tag_b<120;tag_b++)
        {
            if(tag_b==0)b_num=0;
            if(tag_b==0)a_num=0;
            if(data_iris[tag_a][5]==data_iris[tag_b][5])
            {
                a_num++;
                dataa=0;
                for(tag_c=0;tag_c<3;tag_c++)
                dataa+=pow((data_iris[tag_a][tag_c]-data_iris[tag_b][tag_c]),2);
                data[tag_a][0]+=pow(dataa,0.5);
            }
            else
            {
                b_num++;
                dataa=0;
                for(tag_c=0;tag_c<3;tag_c++)
                dataa+=pow((data_iris[tag_a][tag_c]-data_iris[tag_b][tag_c]),2);
                data[tag_a][1]+=pow(dataa,0.5);
            }
            if(tag_b==119)
            {
                data[tag_a][0]/=a_num;
                data[tag_a][1]/=b_num;            
            }
        }
        for(tag_a=0;tag_a<120;tag_a++)
        {
            if(data[tag_a][1]>data[tag_a][0])
            data[tag_a][2]=(data[tag_a][1]-data[tag_a][0])/data[tag_a][1];
            else
            data[tag_a][2]=(data[tag_a][1]-data[tag_a][0])/data[tag_a][0];
        }
            dataa=0;
            for(tag_a=0;tag_a<120;tag_a++)
            dataa+=data[tag_a][2];
            return dataa/120;
    }
    else
    {
        int b_num=0,a_num=0;
        double data[208][3],dataa;
        for(tag_a=0;tag_a<208;tag_a++)
        for(tag_b=0;tag_b<3;tag_b++)
        data[tag_a][tag_b]=0;

        for(tag_a=0;tag_a<208;tag_a++)
        for(tag_b=0;tag_b<208;tag_b++)
        {
            if(tag_b==0)b_num=0;
            if(tag_b==0)a_num=0;
            if(data_sonar[tag_a][61]==data_sonar[tag_b][61])
            {
                a_num++;
                dataa=0;
                for(tag_c=0;tag_c<60;tag_c++)
                dataa+=pow((data_sonar[tag_a][tag_c]-data_sonar[tag_b][tag_c]),2);
                data[tag_a][0]+=pow(dataa,0.5);
            }
            else
            {
                b_num++;
                dataa=0;
                for(tag_c=0;tag_c<60;tag_c++)
                dataa+=pow((data_sonar[tag_a][tag_c]-data_sonar[tag_b][tag_c]),2);
                data[tag_a][1]+=pow(dataa,0.5);
            }
            if(tag_b==207)
            {
                if(a_num!=0)
                data[tag_a][0]/=a_num;
                if(b_num!=0)
                data[tag_a][1]/=b_num;            
            }
            
            
        }

        for(tag_a=0;tag_a<208;tag_a++)
        {
            if(data[tag_a][1]>data[tag_a][0])
            data[tag_a][2]=(data[tag_a][1]-data[tag_a][0])/data[tag_a][1];
            else
            data[tag_a][2]=(data[tag_a][1]-data[tag_a][0])/data[tag_a][0];
        }
            dataa=0;
            for(tag_a=0;tag_a<208;tag_a++)
            dataa+=data[tag_a][2];

            return dataa/208;
    }
       
}
dis函数
double kmeans::dis(double a[],double b[],int add_a,int add_b,int deep_a,int num)
{
    double num_all=0;
    for(int tag_a=0;tag_a<num;tag_a++)
    {
        num_all+=(a[add_a*deep_a+tag_a]-b[add_b*num+tag_a])*(a[add_a*deep_a+tag_a]-b[add_b*num+tag_a]);
    }
    return pow(num_all,0.5);
}

FCM

问题概况

问题同kmeans,步骤如下:
step1: 对隶属度矩阵U使用(0,1)之间的随机数进行初始化,使其满足约束:

KaTeX parse error: Can't use function '$' in math mode at position 25: …1}^c{u_{ij}}=1,$̲ $\forall$i=1,.…

step2: 计算c个聚类中心,j=1,…,c
z j = ∑ i = 1 m u i j α x i ∑ i = 1 m u i j α z_j=\frac{\sum^m_{i=1}u_{ij}^\alpha x_i}{\sum_{i=1}^mu_{ij}^\alpha} zj=i=1muijαi=1muijαxi

step3: 计算代价函数。如果他小于某个阈值,或者它与上一次迭代的代价函数值的变化小于某个阈值,则算法停止。
J ( U , z 1 , . . . , z c ) = ∑ j = 1 c J j = ∑ j = 1 c ∑ i = 1 m u i j α d i j 2 J(U,z_1,...,z_c)=\sum^c_{j=1}J_j=\sum^c_{j=1}\sum^m_{i=1}u^\alpha_{ij}d^2_{ij} J(U,z1,...,zc)=j=1cJj=j=1ci=1muijαdij2
step4: 计算新的U矩阵。返回step2
u i j = 1 ∑ k = 1 c ( d i j / d i k ) 2 / ( α − 1 ) u_{ij}=\frac{1}{\sum^c_{k=1}(d_{ij}/d_{ik})^{2/(\alpha-1)}} uij=k=1c(dij/dik)2/(α1)1

代码
结构总览
int main()
{
    FCM f;
    int m=30;//用于计数
    bool is_iris=0;//切换数据集
    f.load_iris();//载入数据
    f.load_sonar();//载入数据
    f.init_u(is_iris);//初始化u矩阵
    while(m--)
    {
        f.reload_z(is_iris);//更新z矩阵
        f.reload_u(is_iris);//更新u矩阵
        f.sort(is_iris);//归类
        if(is_iris)
        f.fenxi(1,2);//可视化iris数据
        cout<<"cs:"<<f.load_sc(is_iris)<<endl;//输出轮廓系数
        if(is_iris)
        waitKey(0);
    }
    return 0;
}
函数6 FCM更新中心点 f.reload_z(is_iris);

根据FCM公式更新样本中心点(step2)

sum[3]用来存放分母 ∑ i = 1 m u i j α ( j = 1 , . . . , c ) \sum^m_{i=1}u_{ij}^\alpha(j=1,...,c) i=1muijα(j=1,...,c)

point_iris用来存放聚类中心

z j = ∑ i = 1 m u i j α x i ∑ i = 1 m u i j α z_j=\frac{\sum^m_{i=1}u_{ij}^\alpha x_i}{\sum_{i=1}^mu_{ij}^\alpha} zj=i=1muijαi=1muijαxi

void FCM::reload_z(bool is_iris)
{
    if(is_iris)
    {
        for(tag_b=0;tag_b<4;tag_b++)
        for(tag_c=0;tag_c<3;tag_c++)
        point_iris[tag_b][tag_c]=0;
        double sum[3];
        for(tag_a=0;tag_a<3;tag_a++)
        sum[tag_a]=0;
        for(tag_a=0;tag_a<120;tag_a++)
        for(tag_b=0;tag_b<3;tag_b++)
        sum[tag_b]+=pow(u_iris[tag_a][tag_b],alpha);
        for(tag_a=0;tag_a<120;tag_a++)
        for(tag_b=0;tag_b<4;tag_b++)
        for(tag_c=0;tag_c<3;tag_c++)
        point_iris[tag_c][tag_b]+=pow(u_iris[tag_a][tag_c],alpha)*data_iris[tag_a][tag_b];
        for(tag_c=0;tag_c<3;tag_c++)
        for(tag_b=0;tag_b<4;tag_b++)
        point_iris[tag_c][tag_b]/=sum[tag_c];
    }
    else
    {
        for(tag_b=0;tag_b<2;tag_b++)
        for(tag_c=0;tag_c<60;tag_c++)
        point_sonar[tag_b][tag_c]=0;
        double sum[2];
        for(tag_a=0;tag_a<2;tag_a++)
        sum[tag_a]=0;
        for(tag_a=0;tag_a<208;tag_a++)
        for(tag_b=0;tag_b<2;tag_b++)
        sum[tag_b]+=pow(u_sonar[tag_a][tag_b],alpha);
        for(tag_a=0;tag_a<208;tag_a++)
        for(tag_b=0;tag_b<60;tag_b++)
        for(tag_c=0;tag_c<2;tag_c++)
        point_sonar[tag_c][tag_b]+=pow(u_sonar[tag_a][tag_c],alpha)*data_sonar[tag_a][tag_b];
        for(tag_c=0;tag_c<2;tag_c++)
        for(tag_b=0;tag_b<60;tag_b++)
        point_sonar[tag_c][tag_b]/=sum[tag_c];
    }
}
函数7 更新隶属度矩阵u函数 reload_u(bool is_iris)step4

u i j = 1 ∑ k = 1 c ( d i j / d i k ) 2 / ( α − 1 ) u_{ij}=\frac{1}{\sum^c_{k=1}(d_{ij}/d_{ik})^{2/(\alpha-1)}} uij=k=1c(dij/dik)2/(α1)1

这里的d_iris(int a,int b),d_sonar函数用来求数据集中第a组数据和第b组数据的欧式距离

void FCM::reload_u(bool is_iris)
{

    if(is_iris)
    {
        for(tag_a=0;tag_a<120;tag_a++)
        for(tag_b=0;tag_b<3;tag_b++)
        {
                    for(tag_c=0;tag_c<3;tag_c++)
                    {
                        u_iris[tag_a][tag_b]+=pow(d_iris(tag_a,tag_b)/d_iris(tag_a,tag_c),2/(alpha-1));
                    }
                    u_iris[tag_a][tag_b]=1/u_iris[tag_a][tag_b];
        }

    }
    else
    {
        for(tag_a=0;tag_a<208;tag_a++)
        for(tag_b=0;tag_b<2;tag_b++)
        {
                    for(tag_c=0;tag_c<2;tag_c++)
                    {
                        u_sonar[tag_a][tag_b]+=pow(d_sonar(tag_a,tag_b)/d_sonar(tag_a,tag_c),2/(alpha-1));
                    }
                    u_sonar[tag_a][tag_b]=1/u_sonar[tag_a][tag_b];
        }
    }
}
函数8 根据隶属度的归类函数 sort(bool is_iris)
void FCM::sort(bool is_iris)
{
    double(*p)[3]=u_iris;
    double(*p1)[2]=u_sonar;
    
    if(is_iris)
    {
        for(tag_a=0;tag_a<120;tag_a++)
        data_iris[tag_a][5]=max(*p,tag_a,3);
    }
    else
    {
        for(tag_a=0;tag_a<208;tag_a++)
        data_sonar[tag_a][61]=max(*p1,tag_a,2);
    }
    
}
d_iris和d_sonar函数
double FCM::d_iris(int a,int b)
{
    double fin=0;
    for(int tag=0;tag<4;tag++)
    fin+=(data_iris[a][tag]-point_iris[b][tag])*(data_iris[a][tag]-point_iris[b][tag]);
    return sqrt(fin);
}
double FCM::d_sonar(int a,int b)
{
    double fin=0;
    for(int tag=0;tag<60;tag++)
    fin+=(data_sonar[a][tag]-point_sonar[b][tag])*(data_sonar[a][tag]-point_sonar[b][tag]);
    return sqrt(fin);
}
iris图片显示函数
void kmeans::fenxi(int a,int b)
{
    cv::Mat fra=cv::Mat(cv::Size(800,800), CV_8UC3);
    cv::Mat fra_new=cv::Mat(cv::Size(800,800), CV_8UC3);
        for(tag_a=0;tag_a<800;tag_a++)
            for(tag_b=0;tag_b<800;tag_b++)
            {
                fra.at<cv::Vec3b>(tag_a,tag_b)[0]=0;
                fra.at<cv::Vec3b>(tag_a,tag_b)[1]=0;
                fra.at<cv::Vec3b>(tag_a,tag_b)[2]=0;
                fra_new.at<cv::Vec3b>(tag_a,tag_b)[0]=0;
                fra_new.at<cv::Vec3b>(tag_a,tag_b)[1]=0;
                fra_new.at<cv::Vec3b>(tag_a,tag_b)[2]=0;
                
            }
            
    for(tag_a=0;tag_a<120;tag_a++)
    {
        fra.at<cv::Vec3b>(data_iris[tag_a][a]*100,data_iris[tag_a][b]*100-1)[data_iris[tag_a][4]]=255;
        fra.at<cv::Vec3b>(data_iris[tag_a][a]*100,data_iris[tag_a][b]*100+1)[data_iris[tag_a][4]]=255;
        fra.at<cv::Vec3b>(data_iris[tag_a][a]*100,data_iris[tag_a][b]*100)[data_iris[tag_a][4]]=255;
        fra.at<cv::Vec3b>(data_iris[tag_a][a]*100-1,data_iris[tag_a][b]*100)[data_iris[tag_a][4]]=255;
        fra.at<cv::Vec3b>(data_iris[tag_a][a]*100+1,data_iris[tag_a][b]*100)[data_iris[tag_a][4]]=255;
        fra_new.at<cv::Vec3b>(data_iris[tag_a][a]*100,data_iris[tag_a][b]*100-1)[data_iris[tag_a][5]]=255;
        fra_new.at<cv::Vec3b>(data_iris[tag_a][a]*100,data_iris[tag_a][b]*100+1)[data_iris[tag_a][5]]=255;
        fra_new.at<cv::Vec3b>(data_iris[tag_a][a]*100,data_iris[tag_a][b]*100)[data_iris[tag_a][5]]=255;
        fra_new.at<cv::Vec3b>(data_iris[tag_a][a]*100-1,data_iris[tag_a][b]*100)[data_iris[tag_a][5]]=255;
        fra_new.at<cv::Vec3b>(data_iris[tag_a][a]*100+1,data_iris[tag_a][b]*100)[data_iris[tag_a][5]]=255;
    
    }
    for(tag_a=0;tag_a<3;tag_a++)
    for(tag_c=0;tag_c<3;tag_c++)
    for(tag_b=-2;tag_b<3;tag_b++)
    for(int tag=-2;tag<3;tag++)
    fra_new.at<cv::Vec3b>(point_iris[tag_a][a]*100+tag,point_iris[tag_a][b]*100+tag_b)[tag_c]=255;
    
    char m[1];
    m[0]=a+'0';
    cv::imshow(m,fra);
        m[0]=a+'3';
    cv::imshow(m,fra_new);
}

ps kmeans类,FCM类

class kmeans
{
private:
//计数用
int tag_a,tag_b,tag_c;
//数据阈值(初始化中心时用到)
double yu_iris[4][2],yu_sonar[60][2];
//载入数据
double data_iris[120][6],data_sonar[208][62];
//数据中心z
//double point_iris[3][4],point_sonar[2][60];
public:
double dis(double a[],double b[],int add_a,int add_b,int deep_a,int num);
public:
double point_iris[3][4],point_sonar[2][60];
//载入数据
void load_iris();
void load_sonar();
void init_kmeans(bool is_iris);
void sort(bool is_iris);
void reload_z(bool is_iris);
void show();
void fenxi(int a,int b);
double load_sc(bool is_iris);
};

FCM

class FCM
{
private:
//计数用0
int tag_a,tag_b,tag_c;
double alpha=2;
//数据阈值(初始化中心时用到)
double yu_iris[4][2],yu_sonar[60][2];
//载入数据
double data_iris[120][6],data_sonar[208][62];
double u_iris[120][3]={
    0.2,0.4,0.4,0.2,
    0.4,0.2,0.4,0.2,
    0.4,0.4,0.2,0.6,
};
double u_sonar[208][2];
//数据中心z
//double point_iris[3][4],point_sonar[2][60];
public:
double d_iris(int a,int b);
double dis(double a[],double b[],int add_a,int add_b,int deep_a,int num);
public:
double point_iris[3][4],point_sonar[2][60];
//载入数据
void load_iris();
void load_sonar();
void init_u(bool is_iris);
void sort(bool is_iris);
void reload_z(bool is_iris);
void reload_u(bool is_iris);
int max(double a[],int num,int wide);
void show();
void fenxi(int a,int b);
double load_sc(bool is_iris);
double d_sonar(int a,int b);
};

FCM进行图片特征提取

代码只需将图片信息载入到data[m][4]即可(m是图片像素数,第四维存放分类信息):

void FCM::load_pic()
{
Mat a=imread("2.bmp",1);
imshow("src",a);
int tag=0;
for(tag_a=0;tag_a<a.cols;tag_a++)
for(tag_b=0;tag_b<a.rows;tag_b++)
{
    for(tag_c=0;tag_c<3;tag_c++)
    {
        data[tag][tag_c]=a.at<Vec3b>(tag_b,tag_a)[tag_c];
    }
    tag++;
}
}


后面的同上

效果:

在这里插入图片描述

结语

作者水平有限,若发现问题还望慷慨指正

  • 6
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值