【基于Kmeans、Kmeans++和二分K均值算法的图像分割】数据挖掘实验三

文章目录

  • Ⅰ、项目任务要求
    • 任务描述:
    • 主要任务要求:
  • II、实现过程
    • 数据集描述
    • 实现描述
    • 具体实现过程
  • III、完整代码
    • 代码①
    • 代码②


Ⅰ、项目任务要求

任务描述:

  • 图像分割是图像处理和计算机视觉中重要的一环,在实际生活中得到了广泛的应用。例如,在医学上,用于测量医学图像中组织体积、三维重建、手术模拟等;在遥感图像中,分割合成孔径雷达图像中的目标、提取遥感云图中不同云系与背景等、定位卫星图像中的道路和森林等。图像分割也可作为预处理将最初的图像转化为若干个更加抽象、更便于计算机处理的形式,既保留了图像中的重要特征信息,又有效减少了图像中的无用数据、提高了后续图像处理的准确率和效率。例如,在通信方面,可事先提取目标的轮廓结构、区域内容等,保证不失有用信息的同时,有针对性地压缩图像,以提高网络传输效率;在交通领域可用来对车辆进行轮廓提取、识别或跟踪,行人检测等。总的来说,凡是与目标的检测、提取和识别等相关的内容,都需要利用到图像分割技术。因此,无论是从图像分割的技术和算法,还是从对图像处理、计算机视觉的影响以及实际应用等各个方面来深入研究和探讨图像分割,都具有十分重要的意义。
  • 聚类技术是图像分割技术中重要组成部分,其中特征空间聚类法,如Kmeans算法及其相应变体是划分聚类方法中的典范。利用特征空间聚类法进行图像分割是将图像空间中的像素用对应的特征空间点表示,根据它们在特征空间的聚集对特征空间进行分割,然后将它们映射回原图像空间,得到分割结果。
  • 本次实验利用图像的灰度、颜色、纹理、形状等特征,把图像分成若干个互不重叠的区域,并使这些特征在同一区域内呈现相似性,在不同的区域之间存在明显的差异性。然后就可以将分割的图像中具有独特性质的区域提取出来用于不同的研究。
  • 实验内容:分别用Kmeans、Kmeans++和二分K均值三种聚类方法对图片进行图像分割,并写出实验结果分析。

主要任务要求:

  • 简述三种算法思想和实现原理。
  • 小组每人准备一张自己喜欢的图片(图片种类多样化)
  • 写出实验结果分析:
    • 实验运行环境描述。如开发平台、编程语言、调参情况等。
    • 不同初始簇数下三种方法对图片的分割效果对比、分析。
      • 对比表样式如下所示,可将分割效果图分别粘贴到对应位置;
      • 采用轮廓系数(或其它评价指标)评估三种方法的聚类效果(见参考资料网址);
      • 结合对比表(表样如下)结果和评估结果对实验结果进行分析说明。
        【基于Kmeans、Kmeans++和二分K均值算法的图像分割】数据挖掘实验三_第1张图片

II、实现过程

数据集描述

实现描述

具体实现过程


III、完整代码

代码①

import numpy as np
import PIL.Image as image
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score
import matplotlib.pyplot as plt


# Todo: 准备数据集 ------------------------------------------------------------
# 定义函数loadData来处理图片
def loadData(filePath):
    f = open(filePath, 'rb')  # 以二进制方式打开文件
    data = []
    img = image.open(f)  # 以列表形式返回图片像素值
    m, n = img.size  # 图片的大小
    for i in range(m):
        for j in range(n):  # 将每个像素点的RGB颜色处理到0-1范围内并存放到data中
            x, y, z = img.getpixel((i, j))
            data.append([x / 256.0, y / 256.0, z / 256.0])
    f.close()
    return np.asarray(data), m, n


imgData1, row, col = loadData("1.jpg")
imgData2, row, col = loadData("1.jpg")
imgData3, row, col = loadData("1.jpg")
imgData4, row, col = loadData("1.jpg")

# Todo: KMeans聚类 ------------------------------------------------------------
print("# Todo: KMeans聚类 ------------------------------------------------------------")


def KMeansModel(n_clusters, img):
    imgData = img
    # 设置聚类中心数为3
    label = KMeans(n_clusters=n_clusters, init='random').fit_predict(imgData)
    # 获取每个像素的标签
    label = label.reshape([row, col])
    # 创建一个新的图像用于保存K-Means的结果
    pic_new = image.new("L", (row, col))
    # 根据标签添加像素
    for i in range(row):
        for j in range(col):
            pic_new.putpixel((i, j), int(256 / (label[i][j] + 1)))
    pic_new.save("KMeans{}.jpg".format(n_clusters), "JPEG")

    # 计算轮廓系数
    silhouette_avg = silhouette_score(imgData, label.flatten())  # 将label转换为一维数组
    print(f"聚类n_clusters={n_clusters}效果的轮廓系数为: {silhouette_avg}")

    # 展示分割效果图
    plt.imshow(pic_new, cmap='gray')
    plt.axis('off')
    plt.show()


KMeansModel(2, imgData1)
KMeansModel(3, imgData1)
KMeansModel(4, imgData1)

# Todo: KMeans++聚类 ------------------------------------------------------------
print("# Todo: KMeans++聚类 ------------------------------------------------------------")


def KMeansPlusPlusModel(n_clusters, img):
    imgData = img
    # Initialize KMeans with KMeans++ initialization method
    kmeans = KMeans(n_clusters=n_clusters, init='k-means++')
    label = kmeans.fit_predict(imgData)
    # 获取每个像素的标签
    label = label.reshape([row, col])
    # 创建一个新的图像用于保存K-Means的结果
    pic_new = image.new("L", (row, col))
    # 根据标签添加像素
    for i in range(row):
        for j in range(col):
            pic_new.putpixel((i, j), int(256 / (label[i][j] + 1)))
    pic_new.save("KMeansPlusPlus{}.jpg".format(n_clusters), "JPEG")

    # 计算轮廓系数
    silhouette_avg = silhouette_score(imgData, label.flatten())  # 将label转换为一维数组
    print(f"KMeans++聚类n_clusters={n_clusters}效果的轮廓系数为: {silhouette_avg}")

    # 展示分割效果图
    plt.imshow(pic_new, cmap='gray')
    plt.axis('off')
    plt.show()


KMeansPlusPlusModel(2, imgData2)
KMeansPlusPlusModel(3, imgData2)
KMeansPlusPlusModel(4, imgData2)

# Todo: 二分K均值 ------------------------------------------------------------
print("# Todo: 二分K均值 ------------------------------------------------------------")


def bisectingKMeans(imgData, k):
    # Initialize with a single cluster containing all data points
    clusters = [imgData]
    while len(clusters) < k:
        # Choose the cluster to split (the one with the highest SSE)
        cluster_idx = -1
        max_sse = -1
        for i in range(len(clusters)):
            sse = np.sum((clusters[i] - np.mean(clusters[i], axis=0)) ** 2)
            if sse > max_sse:
                max_sse = sse
                cluster_idx = i

        # Perform K-Means on the chosen cluster
        kmeans = KMeans(n_clusters=2, init='k-means++')
        cluster_data = clusters.pop(cluster_idx)
        kmeans.fit(cluster_data)
        labels = kmeans.labels_

        # Split the cluster into two based on K-Means results
        cluster1 = cluster_data[labels == 0]
        cluster2 = cluster_data[labels == 1]

        # Add the split clusters back to the clusters list
        clusters.append(cluster1)
        clusters.append(cluster2)

    # Assign labels to original data points
    labels = np.zeros(len(imgData))
    for i in range(len(clusters)):
        labels[np.isin(imgData, clusters[i]).all(axis=1)] = i

    # Create a new image with cluster labels
    clustered_img = labels.reshape([row, col])
    pic_new = image.new("L", (row, col))
    for i in range(row):
        for j in range(col):
            pic_new.putpixel((i, j), int(256 / (clustered_img[i][j] + 1)))
    pic_new.save("BisectingKMeans{}.jpg".format(k), "JPEG")

    # Calculate silhouette score
    silhouette_avg = silhouette_score(imgData, labels.flatten())
    print(f"Bisecting K-Means with {k} clusters - Silhouette Score: {silhouette_avg}")

    # Show clustered image
    plt.imshow(pic_new, cmap='gray')
    plt.axis('off')
    plt.show()


# Apply bisecting K-Means clustering with different numbers of clusters
bisectingKMeans(imgData3, 2)
bisectingKMeans(imgData3, 3)
bisectingKMeans(imgData3, 4)

代码②

你可能感兴趣的:(【数据科学与大数据技术】,数据挖掘,kmeans,均值算法)