美文网首页
Python:模糊C均值聚类(FCM)的图像分割

Python:模糊C均值聚类(FCM)的图像分割

作者: 大龙10 | 来源:发表于2023-12-05 05:09 被阅读0次

    一、FCM

    1、定义

    • FCM算法是基于对目标函数的优化基础上的一种数据聚类方法。
      聚类结果是每一个数据点对聚类中心的隶属程度,该隶属程度用一个数值来表示。该算法允许同一数据属于多个不同的类。

    2、优缺点

    • FCM算法是一种无监督的模糊聚类方法,在算法实现过程中不需要人为的干预。
      这种算法的不足之处:
      首先,算法中需要设定一些参数,若参数的初始化选取的不合适,可能影响聚类结果的正确性;
      其次,当数据样本集合较大并且特征数目较多时,算法的实时性不太好。

    3、HCM与FCM区别

    • K-means也叫硬C均值聚类(HCM),而FCM是模糊C均值聚类,它是HCM的延伸与拓展,HCM与FCM最大的区别在于隶属函数(划分矩阵)的取值不同,HCM的隶属函数只取两个值:0和1,而FCM的隶属函数可以取[0,1]之间的任何数。
      K-means和FCM都需要事先给定聚类的类别数,而FCM还需要选取恰当的加权指数α,α的选取对结果有一定的影响,α属于[0,+∞)。

    二、模糊

    • “模糊”:
      一个元素可以不同程度的属于某几个子集,也就是说元素对于集合的隶属度可以在[0,1]上取连续值。

    三、FCM算法

    C是聚类数,N是样本个数。U是隶属度矩阵,V是聚类中心。

    • 目标函数:


      目标函数
    • 更新公式:



    • 算法


    • S1:初始化参数:加权指数m,簇心数目C,以及迭代停止阈值ε。
      S2:随机初始化隶属度矩阵U,注意满足式(目标函数)。
      S3:式(2)更新簇心Vk。
      S4:式(1)更新隶属度矩阵U
      S5:如果隶属度矩阵U满足式(5)则返回U并结束算法,否则转到S2

    四、流程图

    五、程序

    import numpy as np
    import matplotlib.pyplot as plt
    import time
    star = time.time()  # 计时
    img = plt.imread('d:\\OpenCVpic\\Happyfish.jpg')  # 读取图片信息,存储在一个三维数组中
    row = img.shape[0]
    col = img.shape[1]
    plt.figure(1)
    plt.subplot(221)
    plt.imshow(img)
     
     
    def fcm(data, threshold, k, m):
        # 0.初始化
        data = data.reshape(-1, 3)
        cluster_center = np.zeros([k, 3])  # 簇心
        distance = np.zeros([k, row*col])  # 欧氏距离
        times = 0  # 迭代次数
        goal_j = np.array([])  # 迭代终止条件:目标函数
        goal_u = np.array([])  # 迭代终止条件:隶属度矩阵元素最大变化量
        # 1.初始化U
        u = np.random.dirichlet(np.ones(k), row*col).T  # 形状(k, col*rol),任意一列元素和=1
        #  for s in range(50):
        while 1:
            times += 1
            print('循环:', times)
            # 2.簇心update
            for i in range(k):
                cluster_center[i] = np.sum((np.tile(u[i] ** m, (3, 1))).T * data, axis=0) / np.sum(u[i] ** m)
            # 3.U update
            # 3.1欧拉距离
            for i in range(k):
                distance[i] = np.sqrt(np.sum((data - np.tile(cluster_center[i], (row * col, 1))) ** 2, axis=1))
            # 3.2目标函数
            goal_j = np.append(goal_j, np.sum((u**m)*distance**2))
            # 3.3 更新隶属度矩阵
            oldu = u.copy()  # 记录上一次隶属度矩阵
            u = np.zeros([k, row * col])
            for i in range(k):
                for j in range(k):
                    u[i] += (distance[i] / distance[j]) ** (2 / (m - 1))
                u[i] = 1/u[i]
            goal_u = np.append(goal_u, np.max(u - oldu))  # 隶属度元素最大变化量
            print('隶属度元素最大变化量', np.max(u - oldu), '目标函数', np.sum((u**m)*distance**2))
            # 4.判断:隶属度矩阵元素最大变化量是否小于阈值
            if np.max(u - oldu) <= threshold:
                break
        return u, goal_j, goal_u
     
     
    if __name__ == '__main__':
     
        img_show, goal1_j, goal2_u = fcm(img, 1e-09, 5, 2)
        img_show = np.argmax(img_show, axis=0)
        # plt.figure(2)
        plt.subplot(223)
        plt.plot(goal1_j)
        plt.rcParams['font.sans-serif'] = ['SimHei']
        plt.rcParams['axes.unicode_minus'] = False
        plt.title('目标函数变化曲线')
        plt.xlabel('迭代次数')
        plt.ylabel('目标函数')
        # plt.figure(3)
        plt.subplot(224)
        plt.plot(goal2_u)
        plt.title('隶属度矩阵相邻两次迭代的元素最大变化量变化曲线')
        plt.xlabel('迭代次数')
        plt.ylabel('隶属度矩阵相邻两次迭代的元素最大变化量')
        # plt.figure(1)
        plt.subplot(222)
        plt.imshow(img_show.reshape([row, col]))
        end = time.time()
        print('用时:', end - star)
        plt.show()
    
    
    运行结果

    七、资料

    1、「[凯鲁嘎吉]的博客:聚类——认识FCM算法
    https://www.cnblogs.com/kailugaji/
    2、「毕业回老家」的博客:基于K-means的图像分割
    https://blog.csdn.net/marujie123/article/details/125721608
    3、「毕业回老家」的博客:基于模糊C均值聚类(FCM)的图像分割原理
    https://blog.csdn.net/marujie123/article/details/125722953
    
    

    相关文章

      网友评论

          本文标题:Python:模糊C均值聚类(FCM)的图像分割

          本文链接:https://www.haomeiwen.com/subject/cvokgdtx.html