SVD和Kmeans做 《贝加尔湖畔》图片特征抽取压缩的比较

本样例比较kmeans和svd做图像压缩后的图片效果

原图如下:

代码如下:

#!/usr/bin/python
#  -*- coding:utf-8 -*-

import numpy as np
import os
from PIL import Image
import matplotlib.pyplot as plt
import matplotlib as mpl
from pprint import pprint
from sklearn.cluster import KMeans


def restore1(sigma, u, v, K):  # 奇异值、左特征向量、右特征向量
    m = len(u)
    n = len(v[0])
    a = np.zeros((m, n))
    for k in range(K):
        uk = u[:, k].reshape(m, 1)
        vk = v[k].reshape(1, n)
        a += sigma[k] * np.dot(uk, vk)
    a[a < 0] = 0
    a[a > 255] = 255
    # a = a.clip(0, 255)
    return np.rint(a).astype('uint8')


if __name__ == "__main__":
    A = Image.open("timg.png", 'r')
    a = np.array(A)
    pixel = a.reshape((-1, 3))
    K = 12
    u_r, sigma_r, v_r = np.linalg.svd(a[:, :, 0])
    u_g, sigma_g, v_g = np.linalg.svd(a[:, :, 1])
    u_b, sigma_b, v_b = np.linalg.svd(a[:, :, 2])
    plt.figure(figsize=(11, 9), facecolor='w')
    mpl.rcParams['font.sans-serif'] = ['simHei']
    mpl.rcParams['axes.unicode_minus'] = False
    for k in range(1, K+1):
        print(k)
        R = restore1(sigma_r, u_r, v_r, k)
        G = restore1(sigma_g, u_g, v_g, k)
        B = restore1(sigma_b, u_b, v_b, k)
        I = np.stack((R, G, B), axis=2)
        model = KMeans(n_clusters=k, init='k-means++', n_init=10)
        labels = model.fit_predict(pixel)  # 每个点颜色分类
        colors = model.cluster_centers_  # 聚类中心,颜色值
        new_img = colors[labels]
        # 然后用聚类中心的颜色代替原来的颜色值。
        new_img = new_img.reshape(a.shape)
        new_img = new_img.astype(np.uint8)
        plt.subplot(3, 8, 2*k-1)
        plt.imshow(I)
        plt.axis('off')
        plt.title('奇异值个数:%d' % k)
        plt.subplot(3, 8, 2*k)
        plt.imshow(new_img)
        plt.axis('off')
        plt.title('簇个数:%d' % k)
    plt.suptitle('SVD与Kmeans做图像分解', fontsize=20)
    plt.tight_layout(0.3, rect=(0, 0, 1, 0.92))
    plt.show()

从图片的效果我们可以看出,运用kmeans会直接按照簇的个数使用像素个数,svd则是选择特征值的个数,即使在特征值为1时得到的也是多像素的图片但比较模糊,看不到轮廓。发现其实kmeans的只用少量的像素得到的效果并不差,当簇个数为12时基本与原图效果一直,较奇异值分解得到的图片更清晰一些。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值