K-means聚类算法:
之前在实习面试的时候被问到这个算法,今天就总结一下对这个算法的一些理解,参考了一些博主的文章,附在了下端。
假设:数据之间的相似度可以使用欧式距离进行度量,并且欧式距离越小,两个数据相似度越高。
牧师-牧民模型:
伪代码
function K-Means(输入数据,K个聚类中心)
获取输入数据的纬度D和个数N
随机生成K个Dim纬的点
while(算法未收敛)
对N个点:计算每个点属于哪一类
对于K个中心点:
1.找到所以属于自己这一类的所以数据点
2.把坐标修改到数据中心
end
输出;
end
算法思路:
随机生成K个聚类中心点(尽量不要生成在一起),计算没一个数据点到这K个中心点的距离,把到中心点距离最短的当正自己的类别。然后这K中心点开始向属于这一类的所有数据的中心点移动(这一类所有点坐标的平均值即为移动后的中心点坐标),知道这K个中心点的坐标都固定了无法移动,算法就收敛,结束。
对于图像来说:
1.从图像中随机取K个聚类中心
2.彩色距离计算方法:
distance=sqt((r-r’)**2 + (g-g’)**2
+(b-b’)**2)
3.计算K类中每一类像素的平均值,并将该值作为新的K个类的中心
4.判断聚类中心是否移动,移动继续迭代;不移动终止迭代。
5.将原图中各个像素分配到彩色距离最小的类别中去
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
from glob import glob
def k_means(img, Class=5):
# get shape
H, W, C = img.shape
# initiate random seed
np.random.seed(0)
# reshape image
img = np.reshape(img, (H * W, -1))
# get index randomly
i = np.random.choice(np.arange(H * W), Class, replace=False)
Cs = img[i].copy()
print(Cs)
while True:
# prepare pixel class label
clss = np.zeros((H * W), dtype=int)
# each pixel
for i in range(H * W):
# get distance from index pixel
dis = np.sqrt(np.sum((Cs - img[i])**2, axis=1))
# get argmin distance
clss[i] = np.argmin(dis)
# selected pixel values
Cs_tmp = np.zeros((Class, 3))
# each class label
for i in range(Class):
Cs_tmp[i] = np.mean(img[clss == i], axis=0)
# if not any change
if (Cs == Cs_tmp).all():
break
else:
Cs = Cs_tmp.copy()
# prepare out image
out = np.zeros((H * W, 3), dtype=np.float32)
# assign selected pixel values
for i in range(Class):
out[clss == i] = Cs[i]
print(Cs)
out = np.clip(out, 0, 255)
# reshape out image
out = np.reshape(out, (H, W, 3))
out = out.astype(np.uint8)
return out
# read image
img = cv.imread("../paojie.jpg").astype(np.float32)
# K-means
out = k_means(img,Class=3)
cv.imwrite("out.jpg", out)
cv.imshow("result", out)
cv.waitKey(0)
cv.destroyAllWindows()
参考文章:
https://www.cnblogs.com/wojianxin/p/12580771.html
https://zhuanlan.zhihu.com/p/20432322