关于图像分类分割超像素python代码

都不说原理了网上一搜一大堆 关键是你要复现哇

SLIC

两个代码实现,如果你想换图只要改一下自己图片的路径就行直接跑
第一个:

import math
from skimage import io, color
import numpy as np
from tqdm import trange
#少了那个库 自己pip install 安装
class Cluster(object):
    cluster_index = 1

    def __init__(self, h, w, l=0, a=0, b=0):
        self.update(h, w, l, a, b)
        self.pixels = []
        self.no = self.cluster_index
        Cluster.cluster_index += 1

    def update(self, h, w, l, a, b):
        self.h = h
        self.w = w
        self.l = l
        self.a = a
        self.b = b

    def __str__(self):
        return "{},{}:{} {} {} ".format(self.h, self.w, self.l, self.a, self.b)

    def __repr__(self):
        return self.__str__()


class SLICProcessor(object):
    @staticmethod
    def open_image(path):
        """
        Return:
            3D array, row col [LAB]
        """
        rgb = io.imread(path)
        lab_arr = color.rgb2lab(rgb)
        return lab_arr

    @staticmethod
    def save_lab_image(path, lab_arr):
        """
        Convert the array to RBG, then save the image
        :param path:
        :param lab_arr:
        :return:
        """
        rgb_arr = color.lab2rgb(lab_arr)
        io.imsave(path, rgb_arr)

    def make_cluster(self, h, w):
        h = int(h)
        w = int(w)
        return Cluster(h, w,
                       self.data[h][w][0],
                       self.data[h][w][1],
                       self.data[h][w][2])

    def __init__(self, filename, K, M):
        self.K = K
        self.M = M

        self.data = self.open_image(filename)
        self.image_height = self.data.shape[0]
        self.image_width = self.data.shape[1]
        self.N = self.image_height * self.image_width
        self.S = int(math.sqrt(self.N / self.K))

        self.clusters = []
        self.label = {}
        self.dis = np.full((self.image_height, self.image_width), np.inf)

    def init_clusters(self):
        h = self.S / 2
        w = self.S / 2
        while h < self.image_height:
            while w < self.image_width:
                self.clusters.append(self.make_cluster(h, w))
                w += self.S
            w = self.S / 2
            h += self.S

    def get_gradient(self, h, w):
        if w + 1 >= self.image_width:
            w = self.image_width - 2
        if h + 1 >= self.image_height:
            h = self.image_height - 2

        gradient = self.data[h + 1][w + 1][0] - self.data[h][w][0] + \
                   self.data[h + 1][w + 1][1] - self.data[h][w][1] + \
                   self.data[h + 1][w + 1][2] - self.data[h][w][2]
        return gradient

    def move_clusters(self):
        for cluster in self.clusters:
            cluster_gradient = self.get_gradient(cluster.h, cluster.w)
            for dh in range(-1, 2):
                for dw in range(-1, 2):
                    _h = cluster.h + dh
                    _w = cluster.w + dw
                    new_gradient = self.get_gradient(_h, _w)
                    if new_gradient < cluster_gradient:
                        cluster.update(_h, _w, self.data[_h][_w][0], self.data[_h][_w][1], self.data[_h][_w][2])
                        cluster_gradient = new_gradient

    def assignment(self):
        for cluster in self.clusters:
            for h in range(cluster.h - 2 * self.S, cluster.h + 2 * self.S):
                if h < 0 or h >= self.image_height: continue
                for w in range(cluster.w - 2 * self.S, cluster.w + 2 * self.S):
                    if w < 0 or w >= self.image_width: continue
                    L, A, B = self.data[h][w]
                    Dc = math.sqrt(
                        math.pow(L - cluster.l, 2) +
                        math.pow(A - cluster.a, 2) +
                        math.pow(B - cluster.b, 2))
                    Ds = math.sqrt(
                        math.pow(h - cluster.h, 2) +
                        math.pow(w - cluster.w, 2))
                    D = math.sqrt(math.pow(Dc / self.M, 2) + math.pow(Ds / self.S, 2))
                    if D < self.dis[h][w]:
                        if (h, w) not in self.label:
                            self.label[(h, w)] = cluster
                            cluster.pixels.append((h, w))
                        else:
                            self.label[(h, w)].pixels.remove((h, w))
                            self.label[(h, w)] = cluster
                            cluster.pixels.append((h, w))
                        self.dis[h][w] = D

    def update_cluster(self):
        for cluster in self.clusters:
            sum_h = sum_w = number = 0
            for p in cluster.pixels:
                sum_h += p[0]
                sum_w += p[1]
                number += 1
            _h = int(sum_h / number)
            _w = int(sum_w / number)
            cluster.update(_h, _w, self.data[_h][_w][0], self.data[_h][_w][1], self.data[_h][_w][2])

    def save_current_image(self, name):
        image_arr = np.copy(self.data)
        for cluster in self.clusters:
            for p in cluster.pixels:
                image_arr[p[0]][p[1]][0] = cluster.l
                image_arr[p[0]][p[1]][1] = cluster.a
                image_arr[p[0]][p[1]][2] = cluster.b
            image_arr[cluster.h][cluster.w][0] = 0
            image_arr[cluster.h][cluster.w][1] = 0
            image_arr[cluster.h][cluster.w][2] = 0
        self.save_lab_image(name, image_arr)

    def iterate_10times(self):
        self.init_clusters()
        self.move_clusters()
        for i in trange(10):  #这个就迭代了十次每次结果都保存在当前路径下的png文件了
            self.assignment()
            self.update_cluster()
            name = 'M{m}_K{k}_loop{loop}.png'.format(loop=i, m=self.M, k=self.K)
            self.save_current_image(name)
p = SLICProcessor('路径', 200, 40)
p.iterate_10times()

在这里插入图片描述

第二个方法
这个 是python自带的库写的,需要改什么参数可以自己百度slic函数查询

from skimage.segmentation import slic,mark_boundaries
from skimage import io
import matplotlib.pyplot as plt

img = io.imread("图片路径X01_1_0000000250.jpg")

segments = slic(img, n_segments=60, compactness=10)
out=mark_boundaries(img,segments)
plt.title("n_segments=60")
plt.imshow(out)
plt.show()

我结果 我在jupyter notebook 跑的
在这里插入图片描述
在这里插入图片描述
FCM

import random

import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False
#from sklearn import datasets

m=2



class FCM:
    def __init__(self, data, clust_num,iter_num=10):
        self.data = data
        self.cnum = clust_num
        self.sample_num=data.shape[0]
        self.dim = data.shape[-1]  # 数据最后一维度数
        Jlist=[]   # 存储目标函数计算值的矩阵

        U = self.Initial_U(self.sample_num, self.cnum)
        for i in range(0, iter_num): # 迭代次数默认为10
            C = self.Cen_Iter(self.data, U, self.cnum)
            U = self.U_Iter(U, C)
            print("第%d次迭代" %(i+1) ,end="")
            print("聚类中心",C)
            J = self.J_calcu(self.data, U, C)  # 计算目标函数
            Jlist = np.append(Jlist, J)
        self.label = np.argmax(U, axis=0)  # 所有样本的分类标签
        self.Clast = C    # 最后的类中心矩阵
        self.Jlist = Jlist  # 存储目标函数计算值的矩阵

    # 初始化隶属度矩阵U
    def Initial_U(self, sample_num, cluster_n):
        U = np.random.rand(sample_num, cluster_n)  # sample_num为样本个数, cluster_n为分类数
        row_sum = np.sum(U, axis=1)  # 按行求和 row_sum: sample_num*1
        row_sum = 1 / row_sum    # 该矩阵每个数取倒数
        U = np.multiply(U.T, row_sum)  # 确保U的每列和为1 (cluster_n*sample_num).*(sample_num*1)
        return U   # cluster_n*sample_num

    # 计算类中心
    def Cen_Iter(self, data, U, cluster_n):
        c_new = np.empty(shape=[0, self.dim])  # self.dim为样本矩阵的最后一维度
        for i in range(0, cluster_n):          # 如散点的dim为2,图片像素值的dim为1
            u_ij_m = U[i, :] ** m  # (sample_num,)
            sum_u = np.sum(u_ij_m)
            ux = np.dot(u_ij_m, data)  # (dim,)
            ux = np.reshape(ux, (1, self.dim))  # (1,dim)
            c_new = np.append(c_new, ux / sum_u, axis=0)   # 按列的方向添加类中心到类中心矩阵
        return c_new  # cluster_num*dim

    # 隶属度矩阵迭代
    def U_Iter(self, U, c):
        for i in range(0, self.cnum):
            for j in range(0, self.sample_num):
                sum = 0
                for k in range(0, self.cnum):
                    temp = (np.linalg.norm(self.data[j, :] - c[i, :]) /
                            np.linalg.norm(self.data[j, :] - c[k, :])) ** (
                                2 / (m - 1))
                    sum = temp + sum
                U[i, j] = 1 / sum

        return U

    # 计算目标函数值
    def J_calcu(self, data, U, c):
        temp1 = np.zeros(U.shape)
        for i in range(0, U.shape[0]):
            for j in range(0, U.shape[1]):
                temp1[i, j] = (np.linalg.norm(data[j, :] - c[i, :])) ** 2 * U[i, j] ** m

        J = np.sum(np.sum(temp1))
        print("目标函数值:%.2f" %J)
        return J


    # 打印聚类结果图
    def plot(self):

        mark = ['or', 'ob', 'og', 'om', 'oy', 'oc']  # 聚类点的颜色及形状

        if self.dim == 2:
            #第一张图
            plt.subplot(221)
            plt.plot(self.data[:, 0], self.data[:, 1],'ob',markersize=2)
            plt.title('未聚类前散点图')

            #第二张图
            plt.subplot(222)
            j = 0
            for i in self.label:
                plt.plot(self.data[j:j + 1, 0], self.data[j:j + 1, 1], mark[i],
                         markersize=2)
                j += 1

            plt.plot(self.Clast[:, 0], self.Clast[:, 1], 'k*', markersize=7)
            plt.title("聚类后结果")

            # 第三张图
            plt.subplot(212)
            plt.plot(self.Jlist, 'g-', )
            plt.title("目标函数变化图",)

            plt.show()
        elif self.dim==1:

            plt.subplot(221)
            plt.title("聚类前散点图")
            for j in range(0, self.data.shape[0]):
                plt.plot(self.data[j, 0], 'ob',markersize=3)  # 打印散点图

            plt.subplot(222)
            j = 0
            for i in self.label:
                plt.plot(self.data[j:j + 1, 0], mark[i], markersize=3)
                j += 1

            plt.plot([0]*self.Clast.shape[0],self.Clast[:, 0], 'k*',label='聚类中心',zorder=2)
            plt.title("聚类后结果图")
            plt.legend()
            # 第三张图
            plt.subplot(212)
            plt.plot(self.Jlist, 'g-', )
            plt.title("目标函数变化图", )
            plt.show()

        elif self.dim==3:
            # 第一张图
            fig = plt.figure()
            ax1 = fig.add_subplot(221, projection='3d')
            ax1.scatter(self.data[:, 0], self.data[:, 1],self.data[:,2], "b")
            ax1.set_xlabel("X 轴")
            ax1.set_ylabel("Y 轴")
            ax1.set_zlabel("Z 轴")
            plt.title("未聚类前的图")

            # 第二张图
            ax2 = fig.add_subplot(222, projection='3d')

            j = 0

            for i in self.label:
                ax2.plot(self.data[j:j+1, 0], self.data[j:j+1, 1],self.data[j:j+1,2], mark[i],markersize=5)
                j += 1
            ax2.plot(self.Clast[:, 0], self.Clast[:, 1], self.Clast[:, 2], 'k*', label='聚类中心', markersize=8)

            plt.legend()


            ax2.set_xlabel("X 轴")
            ax2.set_ylabel("Y 轴")
            ax2.set_zlabel("Z 轴")
            plt.title("聚类后结果")
            # # 第三张图
            plt.subplot(212)
            plt.plot(self.Jlist, 'g-', )
            plt.title("目标函数变化图", )
            plt.show()



def example0():
    N=1000
    C=[[N/4,N/2,0,N/2],[N/2,N,0,N/2],[N/4,N/2,N/2,N],[N/2,N,N/2,N]]
    data=[]
    for i in range(4):
        center_datanum=random.randint(20,50)
        for j in range(center_datanum):
            change=random.randint(20,100)
            x=random.randint(C[i][0]+change,C[i][1]-change)
            y=random.randint(C[i][2]+change,C[i][3]-change)
            data.append([x,y])
    data=np.mat(data)
    a=FCM(data,4,20)
    a.plot()
def example1():
    x1 = np.zeros((10, 1))
    x2 = np.zeros((10, 1))
    for i in range(0, 10):
        x1[i] = np.random.rand() * 5
        x2[i] = np.random.rand() * 5 + 5
        x = np.append(x1, x2, axis=0)


    a = FCM(x, 2,20)
    a.plot()
def example2():
    x1 = np.zeros((10, 1))
    y1 = np.zeros((10, 1))
    x2 = np.zeros((10, 1))
    y2 = np.zeros((10, 1))
    x3 = np.zeros((10, 1))
    y3 = np.zeros((10, 1))
    for i in range(0, 10):
        x1[i] = np.random.rand() * 5
        y1[i] = np.random.rand() * 5
        x2[i] = np.random.rand() * 5 + 5
        y2[i] = np.random.rand() * 5 + 5
        x3[i] = np.random.rand() * 0.5 + 1
        y3[i] = np.random.rand() * 0.5 + 1
    x = np.append(x1, x2, axis=0)
    x = np.append(x, x3, axis=0)
    y = np.append(y1, y2, axis=0)
    y = np.append(y, y3, axis=0)
    data = np.append(x, y, axis=1)

    a = FCM(data, 3,20)  # 将数据分为三类
    a.plot()    # 打印结果图
def example3():
    x1 = np.zeros((10, 1))
    y1 = np.zeros((10, 1))
    z1=  np.zeros((10, 1))
    x2 = np.zeros((10, 1))
    y2 = np.zeros((10, 1))
    z2 = np.zeros((10, 1))
    x3 = np.zeros((10, 1))
    y3 = np.zeros((10, 1))
    z3 = np.zeros((10, 1))
    for i in range(0, 10):
        x1[i] = np.random.rand() * 5
        y1[i] = np.random.rand() * 5
        z3[i] = np.random.rand() * 5
        x2[i] = np.random.rand() * 5 + 5
        y2[i] = np.random.rand() * 5 + 5
        z2[i] = np.random.rand() * 5+5
        x3[i] = np.random.rand() * 0.5 + 1
        y3[i] = np.random.rand() * 0.5 + 1
        z3[i] = np.random.rand() * 0.5 + 3

    x = np.append(x1, x2, axis=0)
    x = np.append(x, x3, axis=0)
    y = np.append(y1, y2, axis=0)
    y = np.append(y, y3, axis=0)
    z = np.append(z1, z2, axis=0)
    z = np.append(z, z3, axis=0)
    data = np.append(x, y, axis=1)
    print(data.shape)
    data=np.append(data,z,axis=1)

    a = FCM(data, 3,20)  # 将数据分为三类
    a.plot()  # 打印结果图


if __name__ == '__main__':
    example0()
    #example1()
    #example2()
    #example3()



import matplotlib.pyplot as plt
import cv2
from FCMTEST import FCM
import numpy as np


def FCM_pic_cut0(img_path,gray=False,clustercenternum,iternum):
#def FCM_pic_cut0(img_path,gray=False,clustercenternum=5,iternum=10):
    if gray:
        img=cv2.imread(img_path,0)  #灰度图
        data=img.reshape(img.shape[0]*img.shape[1],1) #将图片拉成一列

    else:
        img=cv2.imread(img_path)
        img=cv2.cvtColor(img,cv2.COLOR_BGR2RGB) #转化为RGB,不然plt时图片会怪怪的
        data=img.reshape(-1,3)  # 将三维降成二维

    print("开始聚类")
    test=FCM(data,clustercenternum,iternum)
    cluster=test.label  # 聚类结果
    center=test.Clast # 聚类中心

    print("聚类完成,开始生成图片")
    new_img=center[cluster] # 根据聚类结果和聚类中心构建新图像
    new_img=np.reshape(new_img,img.shape) #矩阵转成原来图片的形状
    new_img=new_img.astype('uint8')  # 要变成图像得数据得转换成uint8
    if gray:
        plt.subplot(121), plt.imshow(img, cmap="gray"), plt.title("原图") # plt默认显示三通道,灰度图要加个cmap="gray",不然图片绿绿的。。
        plt.subplot(122), plt.imshow(new_img, cmap="gray"), plt.title("FCM,%d个聚类中心"%clustercenternum)
    else :
        plt.subplot(121), plt.imshow(img), plt.title("原图")
        plt.subplot(122), plt.imshow(new_img), plt.title("FCM,%d个聚类中心"%clustercenternum)
    plt.show()
    #plt.imsave("cutgray.jpg",new_img) # 保存图片

if __name__ == '__main__':
    FCM_pic_cut0("地址",gray=False,clustercenternum=15)

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值