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调用Orator ORM进行数据库操作

《Python调用OratorORM进行数据库操作》OratorORM是一个功能丰富且灵活的PythonORM库,旨在简化数据库操作,它支持多种数据库并提供了简洁且直观的API,下面我们就... 目录Orator ORM 主要特点安装使用示例总结Orator ORM 是一个功能丰富且灵活的 python O

Python使用国内镜像加速pip安装的方法讲解

《Python使用国内镜像加速pip安装的方法讲解》在Python开发中,pip是一个非常重要的工具,用于安装和管理Python的第三方库,然而,在国内使用pip安装依赖时,往往会因为网络问题而导致速... 目录一、pip 工具简介1. 什么是 pip?2. 什么是 -i 参数?二、国内镜像源的选择三、如何

python使用fastapi实现多语言国际化的操作指南

《python使用fastapi实现多语言国际化的操作指南》本文介绍了使用Python和FastAPI实现多语言国际化的操作指南,包括多语言架构技术栈、翻译管理、前端本地化、语言切换机制以及常见陷阱和... 目录多语言国际化实现指南项目多语言架构技术栈目录结构翻译工作流1. 翻译数据存储2. 翻译生成脚本

如何通过Python实现一个消息队列

《如何通过Python实现一个消息队列》这篇文章主要为大家详细介绍了如何通过Python实现一个简单的消息队列,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录如何通过 python 实现消息队列如何把 http 请求放在队列中执行1. 使用 queue.Queue 和 reque

Python如何实现PDF隐私信息检测

《Python如何实现PDF隐私信息检测》随着越来越多的个人信息以电子形式存储和传输,确保这些信息的安全至关重要,本文将介绍如何使用Python检测PDF文件中的隐私信息,需要的可以参考下... 目录项目背景技术栈代码解析功能说明运行结php果在当今,数据隐私保护变得尤为重要。随着越来越多的个人信息以电子形

使用Python快速实现链接转word文档

《使用Python快速实现链接转word文档》这篇文章主要为大家详细介绍了如何使用Python快速实现链接转word文档功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 演示代码展示from newspaper import Articlefrom docx import

Python Jupyter Notebook导包报错问题及解决

《PythonJupyterNotebook导包报错问题及解决》在conda环境中安装包后,JupyterNotebook导入时出现ImportError,可能是由于包版本不对应或版本太高,解决方... 目录问题解决方法重新安装Jupyter NoteBook 更改Kernel总结问题在conda上安装了

Python如何计算两个不同类型列表的相似度

《Python如何计算两个不同类型列表的相似度》在编程中,经常需要比较两个列表的相似度,尤其是当这两个列表包含不同类型的元素时,下面小编就来讲讲如何使用Python计算两个不同类型列表的相似度吧... 目录摘要引言数字类型相似度欧几里得距离曼哈顿距离字符串类型相似度Levenshtein距离Jaccard相

Python安装时常见报错以及解决方案

《Python安装时常见报错以及解决方案》:本文主要介绍在安装Python、配置环境变量、使用pip以及运行Python脚本时常见的错误及其解决方案,文中介绍的非常详细,需要的朋友可以参考下... 目录一、安装 python 时常见报错及解决方案(一)安装包下载失败(二)权限不足二、配置环境变量时常见报错及

Python中顺序结构和循环结构示例代码

《Python中顺序结构和循环结构示例代码》:本文主要介绍Python中的条件语句和循环语句,条件语句用于根据条件执行不同的代码块,循环语句用于重复执行一段代码,文章还详细说明了range函数的使... 目录一、条件语句(1)条件语句的定义(2)条件语句的语法(a)单分支 if(b)双分支 if-else(