用小例子讲解k-means算法流程及如何实现
图像色彩量化
请参考:图像色彩量化讲解及实现
k-means算法
请参考:k-means算法讲解及实现
算法流程:
- 从图像中随机选取K个RGB分量(K是k-means的类别数)
- 将图像中的像素分配到颜色距离最短的那个类别的索引中去,色彩距离按照下面的方法计算:
- 计算各个索引下像素的颜色的平均值,这个平均值成为新的类别
- 如果原来的类别和新的类别一致,算法结束;不一致,重复步骤2和步骤3
- 将原图中各个像素分配到色彩距离最小的那个类别中去
算法实现(python):
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()