Kmeans图像分割及聚类

Kmeans图像分割及聚类


一、目标

  1. 利用K-means算法实现图像分割,尝试使用不同的K值,观察对结果的影响。

  2. 利用K-means算法实现对UCI数据集中数值型数据Iris的聚类,将结果可视化表示。

二、算法思想

  1. K-means
    首先分别设定计算欧氏距离和随机取初始聚类中心的函数,然后计算点与聚类中心的距离,如小于最短距离则更新聚类中心的点的类别,进行迭代。最后得出聚类中心和样本分类情况。

  2. 图像分割
    利用 matplotlib 导入数据后,将图像转化为矩阵,代入 kmeans进行运算。手动改变 k 值,分别取 2、3、4、5,分别导出图像。

  3. Iris 处理
    首先用 sklearn 模块导入 iris 数据,再用 PCA 方法将数据从四维降到二维,将降维后数据代入 kmeans 进行聚类,得到三个类别,用 matplotlib 和 pil 辅助绘图。

三、核心代码

1、图像分割

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import matplotlib.pyplot as plt 
import matplotlib.image as original
from PIL import Image
import numpy as np
import time,random

#计算欧式距离
def distance(A, B):
dis=np.sqrt(sum(np.power(A-B,2)))
return dis

#初始化聚类中心
def initcenter0(data, k):
s=np.shape(data)[1]
center0=np.mat(np.zeros((k, s)))
for j in range(s):
center0[:, j]=(np.max(data[:, j])-np.min(data[:, j]))*np.random.rand(k, 1)
return center0

#kmeans
def kmeans(data, k):
change=True
num=data.shape[0] #样本数量
effect = np.zeros(n) #分类效果
center=initcenter0(data, k) #初始中心
label=np.zeros(n,dtype=np.int) #类别

while change:
change=False
for i in range(num):
dismin=np.inf
labelori=-1
for j in range(k):
dis=distance(center[j, :], data[i, :])
if dis<dismin:
dismin=dis
labelori=j
if label[i,0]!=labelori:
change=True
label[i,:]=labelori,dismin**2
for i in range(k):
center[i,:]=np.mean(data[label==i],axis=0)
return center,label

#处理图像
img=original.imread("C:\\Users\\Administrator\\Desktop\\MarleneDietrich.jpg")
final=img.reshape(-1,5)
size=np.shape(img)
k=5
center,label=kmeans(final, k)
for i in range(k):
final[np.nonzero(label[:,0].A==i)[0]]=center[i,:]

#输出图像
plt.imshow(original.imread("C:\\Users\\Administrator\\Desktop\\MarleneDietrich.jpg"))
plt.imshow(final.reshape(size))
plt.show()

2、Iris

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
import matplotlib.pyplot as plt 
import matplotlib.image as mpimg
from sklearn import datasets
from PIL import Image
import numpy as np

# 读取iris数据
iris = datasets.load_iris()
dataori = iris.data
targetori=iris.target

#利用PCA将数据降到2维
def PCA(dataori, k):
m = np.mean(dataori, axis=0) # 按列计算数组均值
dataori -= m # 计算协方差矩阵
vector = np.cov(np.transpose(dataori)) # 计算特征值a 特征向量b 并按降序排序
a, b = np.linalg.eig(vector)
index = np.argsort(a)
index = index[::-1] # 返回索引值并反转
a = a[index]
b = b[:, index]
bfin = b[:, :k] # 提取k个特征向量
data = np.dot(dataori, bfin)
return data

#完成降维
data=PCA(dataori,2)

#计算欧氏距离
def distance(A, B):
dis=np.sqrt(sum(np.power(A-B,2)))
return dis

#初始化聚类中心
def initcenter0(data, k):
s=np.shape(data)[1]
center0=np.mat(np.zeros((k, s)))
for j in range(s):
center0[:, j]=(np.max(data[:, j])-np.min(data[:, j]))*np.random.rand(k, 1)
return center0

#kmeans
def kmeans(data, k=3):
change=True
num=data.shape[0] #样本数量
center=initcenter0(data, k) #初始中心
label=np.zeros(n,dtype=np.int) #类别

while change:
change=False
for i in range(num):
dismin=np.inf
labelori=-1
for j in range(k):
dis=distance(center[j, :], data[i, :])
if dis<dismin:
dismin=dis
labelori=j
if label[i, 0]!=labelori:
change=True
label[i,:]=labelori,dismin**2
for i in range(k):
center[i,:]=np.mean(data[label==i],axis=0)
return center,label

# 分类结果
data0 = data[label==0]
data1 = data[label==1]
data2 = data[label==2]

# 绘图
fig, (ax1,ax2) = plt.subplots(1,2,figsize=(10,5))
ax1.scatter(data[:,0],data[:,1],c='m',s=20,marker='o')
ax2.scatter(data0[:,0],data0[:,1],c='r')
ax2.scatter(data1[:,0],data1[:,1],c='c')
ax2.scatter(data2[:,0],data2[:,1],c='y')
ax2.scatter(centroids[:,0],centroids[:,1],c='k',s=100,marker='o')
plt.show()

四、结果图像

  1. 图像分割原图

    图像分割原图

  2. 图像分割 k=2

    图像分割 k=2

  3. 图像分割 k=3

    图像分割 k=3

  4. 图像分割 k=4

    图像分割 k=4

  5. 图像分割 k=5

    图像分割 k=5

  6. Iris聚类结果

    Iris聚类结果