自学内容网 自学内容网

机器学习之实战篇——图像压缩(K-means聚类算法)

机器学习之实战篇——图像压缩(K-means聚类算法)

0. 文章传送

机器学习之监督学习(一)线性回归、多项式回归、算法优化[巨详细笔记]
机器学习之监督学习(二)二元逻辑回归
机器学习之监督学习(三)神经网络基础
机器学习之监督学习(四)决策树和随机森林
机器学习之实战篇——预测二手房房价(线性回归)
机器学习之实战篇——肿瘤良性/恶性分类器(二元逻辑回归)
机器学习之实战篇——MNIST手写数字0~9识别(全连接神经网络模型)
机器学习之非监督学习(一)K-means 聚类算法

1.实验任务

图像和实验文件打包如下:
通过百度网盘分享的文件:bird.zip
链接:https://pan.baidu.com/s/1RK1AF5iY8Pfi_tFxf-bLyw?pwd=tmdt
提取码:tmdt

2.实验思想

使用聚类算法进行图像压缩的思想:

①对于每一个像素点,表示其颜色需要存储三个颜色通道的值,每个值取值为范围0~255的整数,需要8bit(1byte)的存储空间,故对于原始图像共占128×128×1×3
=48kb的存储空间。通过图片属性可以查看其大小约为36kb,这是因为PNG 格式采用了无损压缩技术。虽然原始图像未压缩时大约占用 48 KB,但由于压缩,实际存储在计算机上的文件大小会小于这个值。

②进行图像压缩,需要减少像素点颜色的种类,本案例中假设压缩后颜色种类为16,假设用整数0~15表示每个整数可以用4bit(即0.5byte)表示,对于压缩后的图片,每个像素点只需存储相应的颜色编号,因此占据的存储空间为128×128×0.5+(16×1×3)≈ 8KB,大小仅仅是原始图像的 1 6 \frac{1}{6} 61!

③因此可以采用K-means聚类算法,数据集由包含三个颜色分量特征的128×128个像素点构成,设置目标聚类类别K=16,并使用编写的kmeans.py中的run_kMeans函数实现聚类算法。

3.实验过程

手动编写的kmeans模块,实现k-means聚类算法

#kmeans.py

import numpy as np
import matplotlib.pyplot as plt


# 计算每个数据点所归属的簇
def find_closest_centroids(X, centroids):
    K = centroids.shape[0]
    m = X.shape[0]
    idx = np.zeros(m, dtype=int)
    for i in range(m):
        idx[i] = np.argmin(np.sum((X[i] - centroids) ** 2, axis=1))
    return idx


# 根据当前分类情况计算新的簇心
def compute_centroids(X, idx, K):
    m, n = X.shape
    centroids = np.zeros((K, n))
    for k in range(K):
        cond = (idx == k)
        if cond.any():
            X_k = X[cond]
            centroids[k] = np.mean(X_k, axis=0)
        else:  # 如果没有点被分配到这个簇,则随机选择一个点作为新的簇心
            centroids[k] = X[np.random.choice(X.shape[0])]
    return centroids


# 随机初始化簇心
def kMeans_init_centroids(X, K):
    randidx = np.random.permutation(X.shape[0])
    centroids = X[randidx[:K]]
    return centroids


# 成本函数
def KMeans_compute_cost(X, centroids, idx):
    m = X.shape[0]
    cost = 0
    for i in range(m):
        K_idx = idx[i]
        X_centroid = centroids[K_idx]
        cost += np.sum((X_centroid - X[i]) ** 2)
    return cost / m


# 运行 K-means 聚类算法
def run_kMeans(X, K, max_iters=10, test_times=10):
    m, n = X.shape
    min_cost = float('inf')
    best_idx = np.zeros(m)
    best_centroids = np.zeros((K, n))

    for j in range(test_times):
        print(f'K-Means test {j}/{test_times - 1}:')
        initial_centroids = kMeans_init_centroids(X, K)
        centroids = initial_centroids

        for i in range(max_iters):
            print(f' K-Means iteration {i}/{max_iters - 1}')
            idx = find_closest_centroids(X, centroids)
            centroids = compute_centroids(X, idx, K)
            cost = KMeans_compute_cost(X, centroids, idx)

        if cost < min_cost:
            min_cost = cost
            best_idx = idx
            best_centroids = centroids

        print(f'cost: {cost}, min_cost: {min_cost}')

    return best_centroids, best_idx

导入所需模块

#导入所需模块
import numpy as np
import matplotlib.pyplot as plt
import kmeans as km

处理原始图像作为数据集

#将小鸟图读取为像素矩阵
bird=plt.imread('bird.png')
print(bird)
print(f'bird.shape:{bird.shape}')

原始小鸟彩色图片分辨率为128*128,RGB三个颜色通道值都已进行归一化处理(÷255)
注:因为png格式的图片以浮点数形式存储,而jpeg图像以整数(0~255)存储

#进行聚类之前,先将128*128*3的像素矩阵转化为(128*128=16384)*3的二维特征矩阵
bird_X=bird.reshape((128*128,3))
bird_X

运行聚类算法

K=16
color_centroids, color_idx=km.run_kMeans(bird_X,K)

使用聚类结果进行图像压缩

bird_compressed_X=color_centroids[color_idx]
bird_compressed=bird_compressed_X.reshape((128,128,3))
plt.imshow(bird_compressed)

对比压缩前后图片

# Display original image
fig, ax = plt.subplots(1,2, figsize=(8,8))
plt.axis('off')

ax[0].imshow(bird)
ax[0].set_title('Original')
ax[0].set_axis_off()


# Display compressed image
ax[1].imshow(bird_compressed)
ax[1].set_title('Compressed with %d colours'%K)
ax[1].set_axis_off()
#%% md

在这里插入图片描述

可以看到压缩后的图像大体上还是保留了原图像的主要特征,但大大节省了存储空间!


原文地址:https://blog.csdn.net/2301_79376014/article/details/142406859

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!