Python计算机视觉第六章-图像聚类

2024-09-02 18:28

本文主要是介绍Python计算机视觉第六章-图像聚类,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

6.1 K-means聚类

6.1.1 SciPy聚类包

6.1.2 图像聚类

6.1.3 在主成分上可视化图像

6.1.4 像素聚类

6.2 层次聚类

6.3 谱聚类


6.1 K-means聚类

        K-means 是一种将输入数据划分成 k 个簇的简单的聚类算法。K-means 反复提炼初 始评估的类中心,步骤如下:

(1) 以随机或猜测的方式初始化类中心 u i i =1 k
(2) 将每个数据点归并到离它距离最近的类中心所属的类 c i
(3) 对所有属于该类的数据点求平均,将平均值作为新的类中心;
(4) 重复步骤( 2 )和步骤( 3 )直到收敛。
        K-means 试图使 类内总方差 最小:      V=\sum_{i=1}^{k}\sum_{x_{j}\in c_{i}}(x_{j}-\mu_{i})^{2}
        xj 是输入数据,并且是矢量。 该算法是启发式提炼算法,在很多情形下都适用,但 是并不能保证得到最优的结果。
        
        K-means 算法最大的缺陷是必须预先设定聚类数 k ,如果选择不恰当则会导致聚类出来的结果很差。

6.1.1 SciPy聚类包

        在SciPy库中,scipy.cluster.vq模块提供了K-means算法的实现。K-means是一种常见的聚类算法,其主要目标是将数据点分配到预定数量的簇中,使得簇内的数据点尽可能相似,而簇间的数据点尽可能不同。

实验代码:

import numpy as np
from scipy.cluster.vq import kmeans, vq
import matplotlib.pyplot as plt# 生成测试数据
np.random.seed(42)
data = np.concatenate([np.random.normal(loc=[1, 1], scale=0.5, size=(100, 2)),np.random.normal(loc=[5, 5], scale=0.5, size=(100, 2)),np.random.normal(loc=[8, 1], scale=0.5, size=(100, 2))
])# 聚类数量
k = 3# 计算K-means聚类的质心
centroids, distortion = kmeans(data, k)# 将数据点分配到簇
code, distance = vq(data, centroids)# 绘制结果
plt.figure(figsize=(8, 6))
plt.scatter(data[:, 0], data[:, 1], c=code, s=30, cmap='viridis')
plt.scatter(centroids[:, 0], centroids[:, 1], c='red', s=100, marker='x')  # 质心
plt.title('K-means Clustering')
plt.xlabel('Feature 1')
plt.ylabel('Feature 2')
plt.show()# 打印结果
print("质心位置:")
print(centroids)
print("失真度(Distortion):", distortion)

分析:

  1. 聚类效果

    • 上述代码生成了三类数据点,每类数据点在二维空间中分布。K-means聚类会将这些数据点分成三簇,并计算每簇的质心。
    • 绘图中,数据点的颜色表示它们所属的簇,红色的“x”标记表示各簇的质心。
  2. 质心位置

    • centroids数组中包含了每个簇的质心位置。你可以通过这些质心了解每个簇的中心位置。
  3. 失真度

    • distortion是一个衡量聚类效果的指标,表示所有数据点到其最近质心的平均距离。较低的失真度意味着更好的聚类效果。

结果:

        

        通过上述实验,可以观察到K-means算法如何将数据点分成不同的簇,并计算每个簇的质心。质心位置和失真度可以帮助评估聚类效果。此实验示例仅为基本的K-means应用,实际应用中可能需要进一步优化和调整参数,以适应不同的数据集和应用场景。

6.1.2 图像聚类

        我们用 K-means 对这些字体图像进行聚类。

实验代码:

import numpy as np
import cv2
import os
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt# 设置图像文件夹路径和其他参数
image_folder = 'path_to_your_font_images'
image_size = (64, 64)  # 统一图像大小
n_clusters = 5  # 设定簇的数量# 读取和预处理图像
def load_and_preprocess_images(image_folder, image_size):images = []filenames = []for filename in os.listdir(image_folder):if filename.endswith('.png') or filename.endswith('.jpg'):img_path = os.path.join(image_folder, filename)img = cv2.imread(img_path, cv2.IMREAD_GRAYSCALE)img = cv2.resize(img, image_size)images.append(img.flatten())filenames.append(filename)return np.array(images), filenames# 加载数据
images, filenames = load_and_preprocess_images(image_folder, image_size)# 应用K-means聚类
kmeans = KMeans(n_clusters=n_clusters, random_state=0)
kmeans.fit(images)
labels = kmeans.labels_# 可视化结果
def plot_clustered_images(images, labels, filenames, n_clusters, image_size):fig, axes = plt.subplots(n_clusters, len(filenames) // n_clusters, figsize=(15, 10))for i in range(n_clusters):cluster_images = [images[j].reshape(image_size) for j in range(len(images)) if labels[j] == i]for j in range(len(cluster_images)):axes[i, j].imshow(cluster_images[j], cmap='gray')axes[i, j].set_title(f'Cluster {i+1}')axes[i, j].axis('off')plt.tight_layout()plt.show()# 绘制聚类结果
plot_clustered_images(images, labels, filenames, n_clusters, image_size)# 打印每个图像的簇标签
for filename, label in zip(filenames, labels):print(f'{filename}: Cluster {label}')

分析:

  1. 数据加载和预处理

    • load_and_preprocess_images()函数从指定文件夹中读取图像,将每个图像转换为灰度图像,并调整大小为64x64像素。然后,将图像展平为一维特征向量,存储在images数组中。
  2. K-means聚类

    • 使用KMeans类对图像特征进行聚类。n_clusters参数指定簇的数量。fit()方法用于计算K-means模型,labels_属性包含每个图像的簇标签。
  3. 结果可视化

    • plot_clustered_images()函数用于绘制每个簇中的图像。每个簇的图像在一行中显示,便于查看相似图像的分组情况。
  4. 打印结果

    • 输出每个图像及其对应的簇标签,方便查看具体的聚类结果。

结果:

6.1.3 在主成分上可视化图像

        用 40 个主成分数对字体图像进行 K-means 聚类:

  1. 加载和预处理数据:加载字体图像数据,并将其展平为特征向量。
  2. PCA降维:使用主成分分析(PCA)将数据降到 40 个主成分。
  3. K-means聚类:对降维后的数据进行 K-means 聚类。
  4. 可视化:将图像在前两个主成分上进行可视化,显示聚类结果。

实验代码:

import numpy as np
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA
from sklearn.cluster import KMeans
from sklearn.datasets import fetch_olivetti_faces  # 示例数据# 1. 加载和预处理数据
data = fetch_olivetti_faces()
images = data.images
X = data.data  # 展平后的图像数据# 2. PCA降维
pca = PCA(n_components=40)
X_pca = pca.fit_transform(X)# 3. K-means聚类
n_clusters = 10  # 假设有 10 个簇
kmeans = KMeans(n_clusters=n_clusters, random_state=42)
labels = kmeans.fit_predict(X_pca)# 4. 可视化
def plot_pca_clusters(X_pca, labels, images, n_clusters):plt.figure(figsize=(10, 8))scatter = plt.scatter(X_pca[:, 0], X_pca[:, 1], c=labels, cmap='viridis', s=5)plt.colorbar(scatter, label='Cluster')plt.title('PCA of Font Images with K-means Clustering')plt.xlabel('Principal Component 1')plt.ylabel('Principal Component 2')# 在主成分方向上显示示例图像for i in range(n_clusters):cluster_indices = np.where(labels == i)[0]if len(cluster_indices) > 0:example_idx = cluster_indices[0]  # 选择该簇中的第一张图像plt.figure(figsize=(2, 2))plt.imshow(images[example_idx], cmap='gray')plt.title(f'Cluster {i+1} Example')plt.axis('off')plt.show()# 执行可视化
plot_pca_clusters(X_pca, labels, images, n_clusters)

分析:

  1. PCA降维:将高维图像数据降到 40 个主成分,这使得 K-means 聚类可以在较低维度空间中进行。主成分提取了最重要的特征信息,有助于提高聚类效率和准确性。

  2. K-means聚类:在 40 个主成分上应用 K-means 聚类将图像分为若干簇。通过选择适当的簇数(在示例中为 10),可以根据图像的特征进行分类。

  3. 可视化:将数据在前两个主成分上可视化,可以直观地看到不同簇的分布情况。展示每个簇的示例图像有助于理解聚类的结果和图像的特征。

结果:

  • 主成分可视化:前两个主成分通常能捕捉到数据的主要结构。散点图将显示图像在主成分方向上的分布,颜色代表不同的簇。

  • 簇的示例:每个簇的示例图像帮助识别每个簇的典型特征。通过观察这些示例图像,可以评估 K-means 聚类的效果以及是否达到了预期的分组。

6.1.4 像素聚类

        将图像区域或像素合并成有意义的部分称为图像分割

        K-means 聚类是一种无监督学习算法,可以用于图像的像素聚类。在这种应用中,我们将图像视为一个像素的集合,每个像素可以用一个特征向量表示。我们可以将图像的每个像素点的颜色特征(通常是 RGB 颜色值)作为特征向量输入到 K-means 算法中,然后通过 K-means 聚类将这些像素点分成几个簇。这样,我们可以根据颜色特征将图像划分为几个区域,类似于图像分割。

实验代码:

import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.datasets import load_sample_image# 1. 加载图像数据
image = load_sample_image("china.jpg")  # 使用 sklearn 的示例图像
image = image / 255.0  # 归一化到 [0, 1] 范围
height, width, channels = image.shape# 将图像转换为二维数组 (每行是一个像素的 RGB 值)
pixels = image.reshape(-1, 3)# 2. 应用 K-means 聚类
n_clusters = 5  # 假设我们将图像分为 5 个簇
kmeans = KMeans(n_clusters=n_clusters, random_state=42)
labels = kmeans.fit_predict(pixels)# 3. 重构图像
# 每个像素的颜色将被替换为其簇的中心颜色
segmented_image = kmeans.cluster_centers_[labels].reshape(height, width, channels)# 4. 可视化结果
def plot_image_and_segments(original, segmented):fig, ax = plt.subplots(1, 2, figsize=(12, 6))ax[0].imshow(original)ax[0].set_title("Original Image")ax[0].axis('off')ax[1].imshow(segmented)ax[1].set_title("Segmented Image (K-means)")ax[1].axis('off')plt.show()# 执行可视化
plot_image_and_segments(image, segmented_image)

分析:

  1. K-means 聚类:在此实验中,我们将图像的每个像素表示为一个 RGB 颜色值,并将这些值作为 K-means 的输入。通过 K-means 算法将像素分为 5 个簇,表示图像中的主要颜色区域。

  2. 重构图像:聚类后,每个像素的颜色被替换为其所在簇的中心颜色。这样,图像的颜色信息被简化为几种主要的颜色,形成了聚类后的分割效果。

  3. 结果可视化:展示原始图像与 K-means 聚类后图像的对比。通过这种对比,可以观察到聚类的效果,了解算法如何将图像中的颜色区域分成若干簇。

结果:

  • 原始图像:展示了图像的真实颜色和细节。
  • 聚类后的图像:显示了图像经过 K-means 聚类后的效果。可以看到,图像的颜色被分成了几个主要的颜色区域。每个区域代表了一个簇,其颜色为该簇的中心颜色。

6.2 层次聚类

        层次聚类(或凝聚式聚类)是另一种简单但有效的聚类算法,其思想是基于样本间成对距离建立一个简相似性树。层次聚类有若干优点。例如,利用树结构可以可视化数据间的关系,并显示这些簇 是如何关联的。在树中,一个好的特征向量可以给出一个很好的分离结果。另外一个优点是,对于给定的不同的阈值,可以直接利用原来的树,而不需要重新计算。

        

# 导入必要的库
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
from sklearn.cluster import AgglomerativeClustering
from scipy.cluster.hierarchy import dendrogram, linkage
from sklearn.metrics import silhouette_score# 生成示例数据
X, _ = make_blobs(n_samples=300, centers=4, cluster_std=0.60, random_state=0)# 绘制数据点
plt.scatter(X[:, 0], X[:, 1], s=50)
plt.title('Generated Data')
plt.xlabel('Feature 1')
plt.ylabel('Feature 2')
plt.show()# 使用凝聚式聚类
def agglomerative_clustering(n_clusters):model = AgglomerativeClustering(n_clusters=n_clusters)model.fit(X)return model# 可视化凝聚式聚类结果
def plot_clusters(n_clusters):model = agglomerative_clustering(n_clusters)labels = model.labels_plt.scatter(X[:, 0], X[:, 1], c=labels, s=50, cmap='viridis')plt.title(f'Agglomerative Clustering (n_clusters={n_clusters})')plt.xlabel('Feature 1')plt.ylabel('Feature 2')plt.show()# 画出不同簇数的结果
for n_clusters in [2, 3, 4, 5]:plot_clusters(n_clusters)# 绘制层次树状图(dendrogram)
linked = linkage(X, 'ward')
plt.figure(figsize=(10, 7))
dendrogram(linked, orientation='top', distance_sort='descending', show_leaf_counts=True)
plt.title('Hierarchical Clustering Dendrogram')
plt.xlabel('Sample index')
plt.ylabel('Distance')
plt.show()# 计算轮廓系数(Silhouette Score)以评估聚类效果
def calculate_silhouette_score(n_clusters):model = agglomerative_clustering(n_clusters)labels = model.labels_score = silhouette_score(X, labels)return score# 打印不同簇数下的轮廓系数
for n_clusters in [2, 3, 4, 5]:score = calculate_silhouette_score(n_clusters)print(f'Silhouette Score for {n_clusters} clusters: {score:.2f}')

分析:

  1. 数据可视化:不同的簇数(2、3、4、5)下,聚类结果会有所不同。我们可以通过查看不同簇数下的聚类结果图来直观地了解数据如何被分组。

  2. 层次树状图:树状图展示了数据的层次结构。可以看到不同簇的合并过程,以及合并时的距离。

  3. 轮廓系数:轮廓系数是衡量聚类效果的指标。值的范围是[-1, 1],值越高,说明聚类效果越好。通过轮廓系数,我们可以选择最佳的簇数

结果:

6.3 谱聚类

        谱聚类方法是一种有趣的聚类算法,与前面 K-means 和层次聚类方法截然不同。

        对于 n 个元素(如 n 幅图像), 相似矩阵 (或 亲和矩阵 ,有时也称 距离矩阵 )是一个
n × n 的矩阵,矩阵每个元素表示两两之间的相似性分数。谱聚类是由相似性矩阵构
建谱矩阵而得名的。对该谱矩阵进行特征分解得到的特征向量可以用于降维,然后
聚类。
下面是用拉普拉斯矩阵的特征向量对字体图像进行谱聚类的实验:
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import fetch_olivetti_faces
from sklearn.metrics.pairwise import euclidean_distances
from sklearn.cluster import KMeans
from sklearn.preprocessing import normalize
from scipy.sparse.csgraph import laplacian
from sklearn.neighbors import kneighbors_graph# 1. 加载数据
faces = fetch_olivetti_faces()
X = faces.data
n_samples, n_features = X.shape# 2. 计算相似性矩阵
# 使用k邻近图来构建相似性矩阵
knn_graph = kneighbors_graph(X, n_neighbors=10, mode='connectivity', include_self=False)
similarity_matrix = (knn_graph.toarray() + knn_graph.T.toarray()) / 2  # 对称化# 3. 构建图拉普拉斯矩阵
laplacian_matrix = laplacian(similarity_matrix, normed=True)# 4. 计算特征值和特征向量
eigenvalues, eigenvectors = np.linalg.eigh(laplacian_matrix)
# 选择前k个特征向量
k = 40
X_reduced = eigenvectors[:, :k]# 5. 使用k-means聚类
kmeans = KMeans(n_clusters=40, random_state=42)
labels = kmeans.fit_predict(X_reduced)# 6. 可视化结果
# 由于结果是按照标签排序的,这里选择了一些代表性的图像来展示
fig, axes = plt.subplots(4, 10, figsize=(10, 4))
for i in range(4):for j in range(10):index = np.where(labels == i * 10 + j)[0]if len(index) > 0:img_index = index[0]axes[i, j].imshow(faces.images[img_index], cmap='gray')axes[i, j].axis('off')
plt.show()

分析:

  1. 数据准备

    • 加载了Olivetti人脸数据集,包含了4096张64x64像素的灰度图像,每张图像有4096个特征(像素值)。
  2. 构建相似性矩阵

    • 使用k邻近图(k=10)来构建图像之间的相似性矩阵,邻近图保留了数据点之间的局部结构信息。
  3. 构建拉普拉斯矩阵

    • 从相似性矩阵计算图的拉普拉斯矩阵,拉普拉斯矩阵用于捕捉数据的全局结构。
  4. 计算特征向量

    • 计算拉普拉斯矩阵的特征值和特征向量,并选择前40个特征向量作为新的数据表示。
  5. 聚类

    • 使用k-means算法对降维后的数据进行聚类,指定了40个聚类中心(与数据集中的类别数量一致)。
  6. 可视化

    • 通过可视化聚类结果中的一些代表性图像,可以观察到聚类效果。每个子图展示了一些被分到同一类别的图像

结果:

  • 如果聚类效果较好,相同类别的图像应该在视觉上相似。
  • 聚类的效果与k值选择密切相关,可以通过交叉验证等方法优化k值。
  • 聚类的质量还依赖于相似性矩阵的构建和特征向量的选择。在实际应用中可能需要调整相似性矩阵的构建方法和特征向量的选择策略。

这篇关于Python计算机视觉第六章-图像聚类的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1130725

相关文章

使用Python实现图像LBP特征提取的操作方法

《使用Python实现图像LBP特征提取的操作方法》LBP特征叫做局部二值模式,常用于纹理特征提取,并在纹理分类中具有较强的区分能力,本文给大家介绍了如何使用Python实现图像LBP特征提取的操作方... 目录一、LBP特征介绍二、LBP特征描述三、一些改进版本的LBP1.圆形LBP算子2.旋转不变的LB

Python中__init__方法使用的深度解析

《Python中__init__方法使用的深度解析》在Python的面向对象编程(OOP)体系中,__init__方法如同建造房屋时的奠基仪式——它定义了对象诞生时的初始状态,下面我们就来深入了解下_... 目录一、__init__的基因图谱二、初始化过程的魔法时刻继承链中的初始化顺序self参数的奥秘默认

Python实现特殊字符判断并去掉非字母和数字的特殊字符

《Python实现特殊字符判断并去掉非字母和数字的特殊字符》在Python中,可以通过多种方法来判断字符串中是否包含非字母、数字的特殊字符,并将这些特殊字符去掉,本文为大家整理了一些常用的,希望对大家... 目录1. 使用正则表达式判断字符串中是否包含特殊字符去掉字符串中的特殊字符2. 使用 str.isa

python中各种常见文件的读写操作与类型转换详细指南

《python中各种常见文件的读写操作与类型转换详细指南》这篇文章主要为大家详细介绍了python中各种常见文件(txt,xls,csv,sql,二进制文件)的读写操作与类型转换,感兴趣的小伙伴可以跟... 目录1.文件txt读写标准用法1.1写入文件1.2读取文件2. 二进制文件读取3. 大文件读取3.1

使用Python实现一个优雅的异步定时器

《使用Python实现一个优雅的异步定时器》在Python中实现定时器功能是一个常见需求,尤其是在需要周期性执行任务的场景下,本文给大家介绍了基于asyncio和threading模块,可扩展的异步定... 目录需求背景代码1. 单例事件循环的实现2. 事件循环的运行与关闭3. 定时器核心逻辑4. 启动与停

基于Python实现读取嵌套压缩包下文件的方法

《基于Python实现读取嵌套压缩包下文件的方法》工作中遇到的问题,需要用Python实现嵌套压缩包下文件读取,本文给大家介绍了详细的解决方法,并有相关的代码示例供大家参考,需要的朋友可以参考下... 目录思路完整代码代码优化思路打开外层zip压缩包并遍历文件:使用with zipfile.ZipFil

Python处理函数调用超时的四种方法

《Python处理函数调用超时的四种方法》在实际开发过程中,我们可能会遇到一些场景,需要对函数的执行时间进行限制,例如,当一个函数执行时间过长时,可能会导致程序卡顿、资源占用过高,因此,在某些情况下,... 目录前言func-timeout1. 安装 func-timeout2. 基本用法自定义进程subp

Python实现word文档内容智能提取以及合成

《Python实现word文档内容智能提取以及合成》这篇文章主要为大家详细介绍了如何使用Python实现从10个左右的docx文档中抽取内容,再调整语言风格后生成新的文档,感兴趣的小伙伴可以了解一下... 目录核心思路技术路径实现步骤阶段一:准备工作阶段二:内容提取 (python 脚本)阶段三:语言风格调

Python结合PyWebView库打造跨平台桌面应用

《Python结合PyWebView库打造跨平台桌面应用》随着Web技术的发展,将HTML/CSS/JavaScript与Python结合构建桌面应用成为可能,本文将系统讲解如何使用PyWebView... 目录一、技术原理与优势分析1.1 架构原理1.2 核心优势二、开发环境搭建2.1 安装依赖2.2 验

一文详解如何在Python中从字符串中提取部分内容

《一文详解如何在Python中从字符串中提取部分内容》:本文主要介绍如何在Python中从字符串中提取部分内容的相关资料,包括使用正则表达式、Pyparsing库、AST(抽象语法树)、字符串操作... 目录前言解决方案方法一:使用正则表达式方法二:使用 Pyparsing方法三:使用 AST方法四:使用字