Python打通FCM(二分类)

参考:

FCM算法图像分割python_Evens0118的博客-CSDN博客_python实现fcm图像分割

打通+注释:

import cv2
import numpy as np

#C,图像分割类别的数目
C = 2
#M,应用于模糊隶属度的加权指数,一般=2
M = 2
EPSILON = 0.001

# 初始模糊矩阵,就是隶属度
def get_init_fuzzy_mat(pixel_count):
    global C
    fuzzy_mat = np.zeros((C, pixel_count)) # 返回一个给定形状和类型的用0填充的数组,(C行,pixel_count列)
    for col in range(pixel_count): # range是不包括pixel_count的,从0开始
        temp_sum = 0
        randoms = np.random.rand(C - 1, 1) # (C-1行,1列)的[0,1)范围内的随机数
        for row in range(C - 1):
            fuzzy_mat[row, col] = randoms[row, 0] * (1 - temp_sum)
            temp_sum += fuzzy_mat[row, col]
        fuzzy_mat[-1, col] = 1 - temp_sum # 这里:同一列的第一行+第二行=1,二分类
    return fuzzy_mat # 这里返回的是一个两列pixel_count的随机数数组
    # 上面for这些操作难道是让他们更随机嘛,为啥不直接把fuzzy_mat第一行的所有数直接随机

# 初始聚类中心
def get_centroids(data_array, fuzzy_mat):
    global M
    class_num, pixel_count = fuzzy_mat.shape[:2] # shape返回数组的大小:多少行 多少列
    centroids = np.zeros((class_num, 1)) # (两行,1列)
    for i in range(class_num):
        fenzi = 0.
        fenmu = 0.
        for pixel in range(pixel_count):
            fenzi += np.power(fuzzy_mat[i, pixel], M) * data_array[0, pixel] # 隶属度的M次方*点的像素值,就相当于是隶属度越高的像素值,占聚类中心值的比例越高
            fenmu += np.power(fuzzy_mat[i, pixel], M) # 隶属度的M次方
        centroids[i, 0] = fenzi / fenmu
    print("聚类中心1")
    print(centroids[0, 0])
    print("聚类中心2")
    print(centroids[1, 0])
    return centroids

# 这个函数没用到
def eculidDistance(vectA, vectB):
    return np.sqrt(np.sum(np.power(vectA - vectB, 2)))


def eculid_distance(pixel_1, pixel_2):
    return np.power(pixel_1 - pixel_2, 2)

# 计算objective function
def cal_fcm_function(fuzzy_mat, centroids, data_array):
    global M
    class_num, pixel_count = fuzzy_mat.shape[:2]
    target_value = 0.0
    for c in range(class_num):
        for p in range(pixel_count):
            target_value += eculid_distance(data_array[0, p], centroids[c, 0]) * np.power(fuzzy_mat[c, p], M)
    return target_value


# 二分类,隶属度对应的哪一类高就属于哪一类,赋值0/255,变为黑白
def get_label(fuzzy_mat, data_array):
    pixel_count = data_array.shape[1]
    label = np.zeros((1, pixel_count))

    for i in range(pixel_count):
        if fuzzy_mat[0, i] > fuzzy_mat[1, i]:
            label[0, i] = 0
        else:
            label[0, i] = 255
    return label


# 重新计算隶属度
def cal_fuzzy_mat(data_array, centroids):
    global M
    pixel_count = data_array.shape[1]
    class_num = centroids.shape[0]
    new_fuzzy_mat = np.zeros((class_num, pixel_count))
    for p in range(pixel_count):
        for c in range(class_num):
            temp_sum = 0.
            Dik = eculid_distance(data_array[0, p], centroids[c, 0])
            for i in range(class_num):
                temp_sum += np.power(Dik / (eculid_distance(data_array[0, p], centroids[i, 0])), (1 / (M - 1)))
            new_fuzzy_mat[c, p] = 1 / temp_sum
    return new_fuzzy_mat


def fcm(init_fuzzy_mat, init_centroids, data_array):
    global EPSILON
    last_target_function = cal_fcm_function(init_fuzzy_mat, init_centroids, data_array)
    print("迭代次数 = 1, 目标函数值 = {}".format(last_target_function))
    fuzzy_mat = cal_fuzzy_mat(data_array, init_centroids)
    centroids = get_centroids(data_array, fuzzy_mat)
    target_function = cal_fcm_function(fuzzy_mat, centroids, data_array)
    print("迭代次数 = 2, 目标函数值 = {}".format(target_function))
    count = 3
    while count < 100:
        if abs(target_function - last_target_function) <= EPSILON:
            break
        else:
            last_target_function = target_function
            fuzzy_mat = cal_fuzzy_mat(data_array, centroids)
            centroids = get_centroids(data_array, fuzzy_mat)
            target_function = cal_fcm_function(fuzzy_mat, centroids, data_array)
            print("迭代次数 = {}, 目标函数值 = {}".format(count, target_function))
            count += 1
    return fuzzy_mat, centroids, target_function


image = cv2.imread("1test.png", cv2.IMREAD_GRAYSCALE) # 返回的是np.array类型,以灰度模式读入图片
rows, cols = image.shape[:2] # 获取彩色图片的高、宽
pixel_count = rows * cols # 总像素数
image_array = image.reshape(1, pixel_count) # reshape将图像调整为固定的尺度大小,且不产生变形,1行pixel_count列
# print(image_array[1])
# 初始模糊矩阵
init_fuzzy_mat = get_init_fuzzy_mat(pixel_count)
# 初始聚类中心
init_centroids = get_centroids(image_array, init_fuzzy_mat)
fuzzy_mat, centroids, target_function = fcm(init_fuzzy_mat, init_centroids, image_array)
label = get_label(fuzzy_mat, image_array)
new_image = label.reshape(rows, cols) # 变为原图像大小
cv2.imshow("result", new_image)
cv2.imwrite("fcm_result.jpg", new_image)
cv2.waitKey(0)
cv2.destroyAllWindows()

运行结果

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值