利用聚类技术实现纹理图像分割

  • 要求

    • 针对合成纹理图像中每一个像素提取纹理特征向量
    • 利用聚类技术(推荐用 k-均值聚类)对特征向量
      空间中的点进行聚类,类别数可根据图像中的实际纹理类数确定。最后把类
      属标签映射成图像形式显示
  • 提取纹理特征向量我使用的是灰度共生矩阵,如果有不知道这个算法意义的可以去查一下,有很多讲的非常的好,大家可以去看一下,我就不做具体的讲述了

  • KMeans聚类直接使用的sklearn工具包,里面有很多机器学习的算法,不需要自己再去手动实现了,至于KMeans的具体意义,大家自行百度即可,网上的讲解都很好且很全

  • 首先,使用滑动窗口对原始读取的图像进行提取,利用滑动窗口提取到的新的图像信息进行GLCM矩阵的求解,代码如下:

def image_patch(img, slide_window, h, w):
	# 滑动窗口
    patch = np.zeros((slide_window, slide_window, h, w), dtype=np.uint8)

    for i in range(patch.shape[2]):
        for j in range(patch.shape[3]):
            patch[:, :, i, j] = img[i: i + slide_window, j: j + slide_window]

    return patch

def calcu_glcm(img, vmin=0, vmax=255, nbit=64, slide_window=5, step=[2], angle=[0]):
    # 计算GLCM矩阵
    mi, ma = vmin, vmax
    h, w = img.shape

    bins = np.linspace(mi, ma + 1, nbit + 1)
    img = np.digitize(img, bins) - 1

    img = cv2.copyMakeBorder(img, floor(slide_window / 2), floor(slide_window / 2)
                              , floor(slide_window / 2), floor(slide_window / 2), cv2.BORDER_REPLICATE)  # 图像扩充

    patch = image_patch(img, slide_window, h, w)

    glcm = np.zeros((nbit, nbit, len(step), len(angle), h, w), dtype=np.uint8)
    for i in range(patch.shape[2]):
        for j in range(patch.shape[3]):
            glcm[:, :, :, :, i, j] = greycomatrix(patch[:, :, i, j], step, angle, levels=nbit)

    return glcm
  • 获得到GLCM矩阵后接着进行下一步,就是开始计算灰度共生矩阵的各项指标了,比如说能量,熵,相关性等等,网上也有相关指标的介绍,我也不赘述了,至于这些指标的实现,我有手动实现的一部分,也有使用工具包自带的,最后我还是选择了工具包的,因为有一部分的指标手动实在是不知道怎么实现了,下面就是我手动实现的一部分指标
def calcu_glcm_Auto_correlation(glcm, nbit=64):
    Auto_correlation = np.zeros((glcm.shape[2], glcm.shape[3]), dtype=np.float32)
    for i in range(nbit):
        for j in range(nbit):
            Auto_correlation += glcm[i, j] * i * j

    return Auto_correlation


def calcu_glcm_mean(glcm, nbit=64):
    mean = np.zeros((glcm.shape[2], glcm.shape[3]), dtype=np.float32)
    for i in range(nbit):
        for j in range(nbit):
            mean += glcm[i, j] * i / (nbit) ** 2

    return mean


def calcu_glcm_con(glcm, nbit=64):
    con = np.zeros((glcm.shape[2], glcm.shape[3]), dtype=np.float32)
    for i in range(nbit):
        for j in range(nbit):
            con += ((i - j) ** 2) * glcm[i, j]
    return con


def calcu_glcm_entropy(glcm, nbit=64):
    eps = 0.00001
    entropy = np.zeros((glcm.shape[2], glcm.shape[3]), dtype=np.float32)
    for i in range(nbit):
        for j in range(nbit):
            entropy -= glcm[i, j] * np.log10(glcm[i, j] + eps)

    return entropy


def calcu_glcm_asm(glcm, nbit=64):
    asm = np.zeros((glcm.shape[2], glcm.shape[3]), dtype=np.float32)
    for i in range(nbit):
        for j in range(nbit):
            asm += glcm[i, i] ** 2

    return asm


def calcu_glcm_h(glcm, nbit=64):
    h = np.zeros((glcm.shape[2], glcm.shape[3]), dtype=np.float32)
    for i in range(nbit):
        for j in range(nbit):
            h += glcm[i, j] / (1 + (i - j) ** 2)

    return h


def calcu_glcm_correlation(glcm, nbit=64):
    mean = np.zeros((glcm.shape[2], glcm.shape[3]), dtype=np.float32)
    for i in range(nbit):
        for j in range(nbit):
            mean += glcm[i, j] * i / (nbit) ** 2

    variance = np.zeros((glcm.shape[2], glcm.shape[3]), dtype=np.float32)
    for i in range(nbit):
        for j in range(nbit):
            variance += glcm[i, j] * (i - mean) ** 2

    correlation = np.zeros((glcm.shape[2], glcm.shape[3]), dtype=np.float32)
    for i in range(nbit):
        for j in range(nbit):
            correlation += ((i - mean) * (j - mean) * (glcm[i, j] ** 2)) / variance

    return correlation

  • 上面的代码是我手动计算的,可能有些不对的地方,我最后整合的时候使用的是工具包实现的,所以最后代码中可以看到工具包如何实现的。
  • 计算完指标后,我们下面就进行聚类了,大家一定好奇为什么要计算这些指标呢,这些指标计算出来又有什么意义呢,其实很简单,这些指标当做我们聚类的特征,而我们图像大小为168168,图像是由一个个的像素点组成的,所以我们可以理解为像素点为我们的数据,而计算指标为我们的特征信息,我们现在有168168条数据,一条数据对应5个特征属性,这样是不是就感觉有点那个意思了,其实我也不确定我解释的对不对,只能说有助于你接下来对kmeans聚类过程代码的理解
data = np.array([mean, con, asm, ent, h,  dis]).transpose((1, 2, 0))
data = data.reshape((-1, 6))
min_max_sc=MinMaxScaler()
data=min_max_sc.fit_transform(data)
kmeans = KMeans(n_clusters=5,max_iter=100)
kmeans.fit(data)
labels = kmeans.predict(data)
labels = labels.reshape((168, 168))
plt.imshow(labels, cmap='gray')
plt.show()
  • 以上的代码就是我们如何利用得到的特征信息进行聚类的操作,我上面用了六个特征,其实你可以把所有的特征全放里面,但是别忘了修改reshape中第二维的值,这个值对应的是你的特征数量
  • 如果想看一下每一个指标后得到的效果的话,可以直接打印展示出来,我就不做具体的解释了,直接放整体代码
# -*- coding: utf-8 -*-
# @Time    : 2021/12/1 10:17
# @contact : puppet_life@163.com
# @Author  : puppet
# @Details :
# @File    : homework2.py
# @Software: PyCharm


from math import floor
from sklearn.preprocessing import MinMaxScaler
import cv2
import matplotlib.pyplot as plt
import numpy as np
from PIL import Image
from skimage.feature import greycomatrix, greycoprops
from sklearn.cluster import KMeans

if __name__ == '__main__':
    img = np.array(Image.open('Texture_mosaic_data/Texture_mosaic_2.jpg'))
    img = np.uint8(255.0 * (img - np.min(img)) / (np.max(img) - np.min(img)))
    h, w = img.shape
    glcm = calcu_glcm(img, slide_window=9)
    for i in range(glcm.shape[2]):
        for j in range(glcm.shape[3]):
            glcm_cut = glcm[:, :, i, j, :, :]

            # 获取性能评价指标 shape(168,168)
            mean = calcu_glcm_mean(glcm_cut)
            # con = calcu_glcm_con(glcm_cut)
            con = greycoprops(glcm_cut, 'contrast')
            # asm = calcu_glcm_asm(glcm_cut)
            asm = greycoprops(glcm_cut, 'ASM')
            # ent = calcu_glcm_entropy(glcm_cut)
            ent = greycoprops(glcm_cut, 'energy')
            # h = calcu_glcm_h(glcm_cut)
            h = greycoprops(glcm_cut, 'homogeneity')
            # corr = calcu_glcm_correlation(glcm_cut)
            corr = greycoprops(glcm_cut, 'correlation')
            dis = greycoprops(glcm_cut, 'dissimilarity')

    '''
    plt.subplot(2,4,1)
    plt.imshow(img)
    plt.title('original')
    plt.axis('off')

    plt.subplot(2, 4, 2)
    plt.imshow(mean,cmap='gray')
    plt.title('mean')
    plt.axis('off')

    plt.subplot(2, 4, 3)
    plt.imshow(con,cmap='gray')
    plt.title('contrast')
    plt.axis('off')

    plt.subplot(2, 4, 4)
    plt.imshow(asm, cmap='gray')
    plt.title('ASM')
    plt.axis('off')

    plt.subplot(2, 4, 5)
    plt.imshow(ent, cmap='gray')
    plt.title('energy')
    plt.axis('off')

    plt.subplot(2, 4, 6)
    plt.imshow(h, cmap='gray')
    plt.title('homogeneity')
    plt.axis('off')

    plt.subplot(2, 4, 7)
    plt.imshow(corr, cmap='gray')
    plt.title('correlation')
    plt.axis('off')

    plt.subplot(2, 4, 8)
    plt.imshow(dis, cmap='gray')
    plt.title('dissimilarity')
    plt.axis('off')
    plt.show()
'''

    data = np.array([mean, con, asm, ent, h,  dis]).transpose((1, 2, 0))
    data = data.reshape((-1, 6))
    min_max_sc=MinMaxScaler()
    data=min_max_sc.fit_transform(data)
    kmeans = KMeans(n_clusters=3,max_iter=100)
    kmeans.fit(data)
    labels = kmeans.predict(data)
    labels = labels.reshape((168, 168))
    plt.imshow(labels, cmap='gray')
    plt.show()

  • 上述代码中,我注释掉的是我手动实现的性能评价指标,感觉可能会有问题就全部改成了工具包实现的评价指标,下面注释的一部分也就是对每一部分的特征指标的表现效果的输出,可以删掉注释符跑一下

  • 基本上就这些内容,可以跑一下试试,基本上可以实现目标的需求,最后说一句,滑动窗口的大小可以随意调换,可以试一下(3,5,7,9,11,13,15,17,19,21等),经过测试,15,17大小的滑动窗口得到的图像分割效果更好,下面是跑的图像结果,就放一个三类的图像分割效果吧,其实都一样的,第一张图是滑动窗口为9聚合出的效果,第二张是滑动窗口为17聚合出的效果
    在这里插入图片描述

    在这里插入图片描述

以上内容,部分代码参考了其他博主的代码,在此感谢

  • 4
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

锋年

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值