import numpy as np
import matplotlib.pyplot as plt
因为这道题目相对的比较简单,就使用和numpy 和matplotlib 这两个库进行代码的浮现
归一化,按照像素作为输入还是3*3窗函数对某一坐标周围的9个点做平均或者最大值和最小值求平均这三种方式对我们的图像进行预处理作为真正的输入。
def preprocess(image,way = 1): #way 作为一个额外的输入代表不同的预处理方式
image = (image - np.min(image))/(np.max(image)-np.min(image)) # 归一化
if way == 1: #3*3*平均值
image_new = np.zeros(image.shape)
image_new[[0,-1],:] = image[[0,-1],:]
image_new[:,[0,-1]] = image[:,[0,-1]]
for i in range(1,image.shape[0]-1):
for j in range(1,image.shape[1]-1):
image_new[i,j] = np.average(image[i-1:i+2,j-1:j+2])
return image_new
elif way == 2: # 3*3窗的最大值与最小值平均
image_new = np.zeros(image.shape)
image_new[[0,-1],:] = image[[0,-1],:]
image_new[:,[0,-1]] = image[:,[0,-1]]
for i in range(1,image.shape[0]-1):
for j in range(1,image.shape[1]-1):
image_new[i,j] = (np.max(image[i-1:i+2,j-1:j+2]) + np.min(image[i-1:i+2,j-1:j+2]))/2
return image_new
else : #
return image
简单来说就是用两个像素值之间差的绝对值作为相似性的度量,若某一个坐标的像素值与kmeans中的一个代表向量绝对差越小则说明他们越相似的。
由于本题中是像素级别的,并没有涉及到民科夫斯基距离这些可度量距离的概念。
def dist(val1,val2):
return np.abs(val1-val2)
image = np.average(plt.imread('iamge.png',format = None)[:,:,0:3],axis = 2)
(a,b) = image.shape
image = preprocess(image,way =1)
k0 = np.max(image)
k1 = np.min(image)
theta = 1
count = 0
while theta > 0.00001:
class1 = np.array([[1 if dist(k0,image[i,j])>dist(k1,image[i,j]) else 0 for j in range(b)] for i in range(a)])
k0_new = np.average(image[class1==0])
k1_new = np.average(image[class1==1])
theta = (k0-k0_new)**2 + (k1 - k1_new)**2
k0 = k0_new
k1 = k1_new
count += 1
plt.subplot(121)
plt.imshow(image,cmap ='gray')
plt.axis('off')
plt.title('original')
plt.subplot(122)
plt.imshow(class1,cmap ='gray')
plt.axis('off')
plt.title('kmeans')
plt.show()
1:确定需要分类的个数K
2:随机选取k个聚类中心
3:遍历数据集中的所有元素,并将其划分到这K个聚类中心代表下的区域里
4:对分别属于这K个聚类区域的里面的元素向量进行求平均得到新的K个聚类中心
5:判断新生成的聚类中心和老的k个中心是否满足循环结束条件(一般来说就是他们变化很小就可以,说明聚类中心收敛到稳定了),不满足返回步骤**3**
6:算法结束
可以尝试去学习和证明kmeans算法的收敛性。