$$k-$$平均聚类算法进行减色处理第一步—-按颜色距离分类.
对imori.jpg
利用 k-平均聚类算法进行减色处理。
在问题六中涉及到了减色处理,但是在问题六中事先确定了要减少的颜色。这里,k-平均聚类算法用于动态确定要减少的颜色。
算法如下:
- 从图像中随机选取K个\text{RGB}分量(这我们称作类别)。
-
将图像中的像素分别分到颜色距离最短的那个类别的索引中去,色彩距离按照下面的方法计算:
\text{dis}=\sqrt{(R-R’)^2+(G-G’)^2+(B-B’)^2} -
计算各个索引下像素的颜色的平均值,这个平均值成为新的类别;
- 如果原来的类别和新的类别完全一样的话,算法结束。如果不一样的话,重复步骤2和步骤3;
- 将原图像的各个像素分配到色彩距离最小的那个类别中去。
完成步骤1和步骤2。
- 类别数K=5;
- 使用
reshape((HW, 3))
来改变图像大小之后图像将更容易处理; - 步骤1中,对于
np.random.seed(0)
,使用np.random.choice(np.arrange(图像的HW), 5, replace=False)
; - 现在先不考虑步骤3到步骤5的循环。
python实现:
import cv2
import numpy as np
import matplotlib.pyplot as plt
from glob import glob
# K-means step1
def k_means_step1(img, Class=5):
# get shape
H, W, C = img.shape
# initiate random seed
np.random.seed(0)
# reshape
img = np.reshape(img, (H * W, -1))
# select one index randomly
i = np.random.choice(np.arange(H * W), Class, replace=False)
Cs = img[i].copy()
print(Cs)
clss = np.zeros((H * W), dtype=int)
# each pixel
for i in range(H * W):
# get distance from base pixel
dis = np.sqrt(np.sum((Cs - img[i]) ** 2, axis=1))
# get argmin distance
clss[i] = np.argmin(dis)
# show
out = np.reshape(clss, (H, W)) * 50
out = out.astype(np.uint8)
return out
# read image
img = cv2.imread("imori.jpg").astype(np.float32)
# K-means step2
out = k_means_step1(img)
cv2.imwrite("out.jpg", out)
cv2.imshow("result", out)
cv2.waitKey(0)
# 最初选择的颜色
[[140. 121. 148.]
[135. 109. 122.]
[211. 189. 213.]
[135. 86. 84.]
[118. 99. 96.]]
输入 (imori.jpg) | 输出 |
---|---|