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')
运行效果如下:
作者这水平有限,有不足之处欢迎留言指正