机器学习之聚类——MeanShift算法和图像矢量量化


活动地址:CSDN21天学习挑战赛

MeanShift:见名知意

        大家英语怎么样,不好也没关系,没有人比百度更懂翻译。看看这个算法的名字,Mean和Shift紧紧相随,Mean的意思是平均值,Shift的意思是转移,挪动,可以更形象的解释为漂移。组合起来就是均值漂移。

        MeanShift 这个概念最早是由Fukunaga等人于1975年在一篇关于概率密度梯度函数的估计中提出来的。然而在以后的很长一段时间内 MeanShift 并没有引起人们的注意,直到20年以后,也就是1995年,YizongCheng发表了一篇对均值漂移算法里程碑意义的文章,大大扩大了 MeanShift 的适用范围,另外YizongCheng指出了 MeanShift 可能应用的领域,并给出了具体的例子。

算法原理及优缺点

        MeanShift 算法的思路是这样的:
        我们以二维的数据为例,首先以平面内任意一个点为圆心,以半径R画一个圆(也有可能是矩形、椭圆形),形成所谓感兴趣区域,然后计算感兴趣区域中所有数据样本点的质心,这个质心大概率与刚才的圆心不同,圆心到质心的向量就是漂移向量,如下图:

然后再以上面的漂移向量的终点,即上一步的质心为圆心,继续上述过程,又可以得到一个新的质心和漂移向量,如下图: 

然后不断地继续这样的过程,直到算法收敛,比如两次质心的偏移量足够小时,则结束算法

可以预见,算法过程最终的效果就是:圆心从起点开始,最终会一步一步走到样本数据最密集的地方

这里说明一下核函数的概念,在计算质心时,核函数决定了感兴趣区域内各样本点对质心的贡献,下面是几个常用的核函数:

原理介绍了,总结一下它的优缺点吧:

 优点:
1、与K-Means算法不一样的是,MeanShift算法可以自动决定类别的数目。
2、不受异常值影响。
3、没有局部最小值。

缺点:
1、在高维空间数据下表现不佳。
2、无法指定聚类的数量。

图片的矢量量化

        简单来讲,图片的矢量量化就是用更少的颜色种类来表达图片,颜色可以用数据表达,所以矢量量化可以看作是对图片数据的压缩。原图片可能有很多种颜色,有着丰富的表达力,经过矢量量化处理后,图片的颜色变化更加生硬,颜色边界更清晰。在具体的程序处理中,可以对图片的像素数据进行聚类,用聚类中心代替原图片中属于该聚类的像素点。这里的聚类可以使用多种聚类算法,比如K-means、AP聚类、MeanShift等,本文采用MeanShift。好了,上代码!

我们处理的素材是经典的Lena

代码如下:

from PIL import Image
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from sklearn.cluster import MeanShift
from sklearn.metrics import euclidean_distances


# 将像素数据转化为图像
def restore_image(cb, cluster, shape):
    row, col, dummy = shape
    _image = np.empty((row, col, 3))
    index = 0
    for _r in range(row):
        for _c in range(col):
            _image[_r, _c] = cb[cluster[index]]
            index += 1
    return _image


if __name__ == '__main__':
    matplotlib.rcParams['font.sans-serif'] = ['SimHei']
    matplotlib.rcParams['axes.unicode_minus'] = False
    # 加载图像并对图像数据进行预处理
    im = Image.open('.\\lena.png')
    image = np.array(im).astype(float) / 255
    image = image[:, :, :3]
    # 摊平像素数据
    image_v = image.reshape((-1, 3))
    # 图像像素总数
    N = image_v.shape[0]
    # 选择足够多的样本(如1000个),计算聚类中心
    idx = np.random.randint(0, N, size=1000)
    image_sample = image_v[idx]
    # 取像素点欧氏距离中值最为MeanShift感兴趣区域半径
    m = euclidean_distances(image_sample, squared=True)
    band_width = np.median(m)
    # 模型
    model = MeanShift(bin_seeding=True, bandwidth=band_width)
    # 训练
    ms = model.fit(image_sample)
    # 簇中心
    centers = ms.cluster_centers_
    # 聚类图片像素
    c = model.predict(image_v)
    # 像素类别标签
    y_hat = ms.labels_
    # 聚类个数
    n_clusters = np.unique(y_hat).size
    print('聚类结果:\n', c)
    print('带宽:', band_width, '聚类簇的个数为:', n_clusters)
    # 绘制结果
    plt.figure(figsize=(12, 6), facecolor='w')
    plt.subplot(121)
    plt.axis('off')
    plt.title('原始图片', fontsize=14)
    plt.imshow(image)

    plt.subplot(122)
    vq_image = restore_image(centers, c, image.shape)
    plt.axis('off')
    plt.title('矢量量化后图片:%d色' % n_clusters, fontsize=14)
    plt.imshow(vq_image)

    plt.tight_layout()
    plt.subplots_adjust(top=0.9)
    # plt.show()
    plt.savefig('VectorQuantization.png')

运行效果如下:

 


作者这水平有限,有不足之处欢迎留言指正

  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

肥猪猪爸

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值