利用 k-平均聚类算法进行减色处理第二步—-减色处理.
实现上一节提到的算法的第3到5步。
# 选择的颜色
[[182.86730957 156.13246155 180.24510193]
[156.75152588 123.88993835 137.39085388]
[227.31060791 199.93135071 209.36465454]
[ 91.9105835 57.94448471 58.26378632]
[121.8759613 88.4736557 96.99688721]]
减色处理可以将图像处理成手绘风格。如果k=10,则可以在保持一些颜色的同时将图片处理成手绘风格。
现在,k=5的情况下试着将madara.jpg
进行减色处理。
输入 (imori.jpg) | 输出(answer_92.jpg) | k=10(answer_92_k10.jpg) | 输入2 (madara.jpg) | 输出(answer_92_m.jpg) |
---|---|---|---|---|
python实现:
import cv2
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()
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 = cv2.imread("imori.jpg").astype(np.float32)
# K-means
out = k_means(img)
cv2.imwrite("out.jpg", out)
cv2.imshow("result", out)
cv2.waitKey(0)