通过k-means进行图像量化压缩--python实现

作者: AwesomeTang | 来源:发表于2018-07-07 19:35 被阅读11次
    image.png

    逻辑梳理

    • 对于电脑来说,每种颜色都会有一个对应RGB值,比如黑色是[0,0,0],白色是[255,255,255],所以RGB模式下,最多可以区分16581375(255的三次方)种颜色。
    • 另外我们知道,一张图片的大小与分辨率正相关,但其实也与图片颜色的复杂度是正相关的,相同分辨率的情况下,一张纯色图片是比一张五彩斑斓的图片要小的。
    • 一张分辨率为100*100的图片,其实就是由10000个RGB值组成。所以我们要做的就是对于这10000个RGB值聚类成K个簇,然后使用每个簇内的质心点来替换簇内所有的RGB值,这样在不改变分辨率的情况下使用的颜色减少了,图片大小也就会减小了。

    内容

    导入包

    import matplotlib.pyplot as plt
    import seaborn as sns
    from sklearn.cluster import KMeans  #导入kmeans
    from sklearn.utils import shuffle
    import numpy as np
    from skimage import io
    import warnings
    
    warnings.filterwarnings('ignore')
    

    图片读取

    original = mpl.image.imread('Yosemite 5.jpg') 
    width,height,depth = original.shape
    temp = original.reshape(width*height,depth)
    temp = np.array(temp, dtype=np.float64) / 255
    

    图像读取完我们获取到的其实是一个width*height的三维矩阵(width,height是图片的分辨率)

    训练模型

    original_sample = shuffle(temp, random_state=0)[:1000] #随机取1000个RGB值作为训练集
    def cluster(k):
        estimator = KMeans(n_clusters=k,n_jobs=8,random_state=0)#构造聚类器
        kmeans = estimator.fit(original_sample)#聚类   
        return kmeans
    

    我们只随机取了1000组RGB值作为训练,k表示聚类成 k个簇,对于本文就是K种颜色。

    RGB值转化为图像

    def recreate_image(codebook, labels, w, h):
        d = codebook.shape[1]
        image = np.zeros((w, h, d))
        label_idx = 0
        for i in range(w):
            for j in range(h):
                image[i][j] = codebook[labels[label_idx]]
                label_idx += 1
        return image
    

    聚类

    我们选取了32,64,128三个K值来做比较:

    kmeans = cluster(32)
    labels = kmeans.predict(temp)
    kmeans_32 = recreate_image(kmeans.cluster_centers_, labels,width,height)
    kmeans = cluster(64)
    labels = kmeans.predict(temp)
    kmeans_64 = recreate_image(kmeans.cluster_centers_, labels,width,height)
    kmeans = cluster(128)
    labels = kmeans.predict(temp)
    kmeans_128 = recreate_image(kmeans.cluster_centers_, labels,width,height)
    

    画图并保存

    plt.figure(figsize = (15,10))
    plt.subplot(2,2,1)
    plt.axis('off')
    plt.title('Original image')
    plt.imshow(original.reshape(width,height,depth))
    plt.subplot(2,2,2)
    plt.axis('off')
    plt.title('Quantized image (128 colors, K-Means)')
    plt.imshow(kmeans_128)
    io.imsave('kmeans_128.png',kmeans_128)
    plt.subplot(2,2,3)
    plt.axis('off')
    plt.title('Quantized image (64 colors, K-Means)')
    plt.imshow(kmeans_64)
    io.imsave('kmeans_64.png',kmeans_64)
    plt.subplot(2,2,4)
    plt.axis('off')
    plt.title('Quantized image (32 colors, K-Means)')
    plt.imshow(kmeans_32)
    io.imsave('kmeans_32.png',kmeans_32)
    plt.show()
    

    结果如下:



    差别还是比较明显的,随着颜色变少,图片也越来越马赛克了。


    其实对于图片压缩这块,各大互联网公司投入人力优化,在保证图片清晰的情况下,减小文件大小,这样一能为公司节省一大笔带宽费用,二也能让用户更快的加载出图片,提升用户体验。
    这篇文章也只是我在学k-means时候看到的一个案例,对于图片压缩只是很小的一部分,写这片文章的时候我也查了下相关的知识,真要下功夫研究,可是一门大学问。
    最后:
    peace~

    相关文章

      网友评论

        本文标题:通过k-means进行图像量化压缩--python实现

        本文链接:https://www.haomeiwen.com/subject/koeguftx.html