K-Means进行色彩量化的方法思路是什么,代码如何写
Admin 2022-07-04 群英技术资讯 1100 次浏览
今天这篇给大家分享的知识是“K-Means进行色彩量化的方法思路是什么,代码如何写”,小编觉得挺不错的,对大家学习或是工作可能会有所帮助,对此分享发大家做个参考,希望这篇“K-Means进行色彩量化的方法思路是什么,代码如何写”文章能帮助大家解决问题。色彩量化问题可以定义为减少图像中颜色数量的过程。色彩量化对于某些设备显示图像非常关键,这些设备可能由于内存限制等原因只能显示有限颜色,因此,在这些设备上显示色彩通常需要在准确性和减少颜色数量之间进行权衡,在利用 K-Means 聚类进行色彩量化时,权衡两者是通过正确设置 K 参数来进行的。
利用 K-Means 聚类算法来执行色彩量化,簇中心数据由 3 个特征组成,它们对应于图像每个像素的 B、G 和 R 值。因此,关键是将图像转换为数据:
data = np.float32(image).reshape((-1, 3))
为了观察如何权衡准确性和颜色数,我们使用不同 K 值 (3 、 5 、 10 、 20 和 40) 执行聚类过程,以查看生成的图像如何变化,如果我们想要只有 3 种颜色 (K = 3) 的结果图像,需要执行以下操作:
加载 BGR 图像:
img = cv2.imread('example.jpg')
使用 color_quantization() 函数执行色彩量化:
def color_quantization(image, k):
# 将图像转换为数据
data = np.float32(image).reshape((-1, 3))
# 算法终止条件
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 20, 1.0)
# K-Means 聚类
ret, label, center = cv2.kmeans(data, k, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS)
# 簇中心
center = np.uint8(center)
# 将具有 k 颜色中心的图像转换为 uint8
result = center[label.flatten()]
result = result.reshape(img.shape)
return result
color_3 = color_quantization(img, 3)
color_quantization() 函数中,关键点是利用 cv2.kmeans() 方法。最后,可以用 k 种颜色来构建图像,用它们对应的中心值替换每个像素值,程序的运行结果如下所示:


利用 K-Means 聚类进行色彩量化的完整代码如下所示:
import numpy as np
import cv2
from matplotlib import pyplot as plt
def show_img_with_matplotlib(color_img, title, pos):
img_RGB = color_img[:, :, ::-1]
ax = plt.subplot(2, 4, pos)
plt.imshow(img_RGB)
plt.title(title, fontsize=8)
plt.axis('off')
def color_quantization(image, k):
# 将图像转换为数据
data = np.float32(image).reshape((-1, 3))
# 算法终止条件
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 20, 1.0)
# K-Means 聚类
ret, label, center = cv2.kmeans(data, k, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS)
# 簇中心
center = np.uint8(center)
# 将具有 k 颜色中心的图像转换为 uint8
result = center[label.flatten()]
result = result.reshape(img.shape)
return result
fig = plt.figure(figsize=(16, 8))
plt.suptitle("Color quantization using K-means clustering algorithm", fontsize=14, fontweight='bold')
# 图片加载
img = cv2.imread('example.png')
show_img_with_matplotlib(img, "original image", 1)
# 使用不同 K 值进行色彩量化
for i in range(7):
color = color_quantization(img, (i+1) * 10)
show_img_with_matplotlib(color, "color quantization (k = {})".format((i+1) * 10), i+2)
plt.show()
可以扩展以上程序使其显示色彩量化后的色彩分布,该色彩分布显示了分配给每个聚类中心的像素数。只需扩展 color_quantization() 函数已被修改为包含所需功能:
import collections
def color_quantization(image, k):
# 将图像转换为数据
data = np.float32(image).reshape((-1, 3))
# 算法终止条件
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 20, 1.0)
# K-Means 聚类
ret, label, center = cv2.kmeans(data, k, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS)
# 簇中心
center = np.uint8(center)
# 将具有 k 颜色中心的图像转换为 uint8
result = center[label.flatten()]
result = result.reshape(img.shape)
# 统计分配给每个聚类中心的像素数
counter = collections.Counter(label.flatten())
print(counter)
# 计算输入图像的总像素数
total = img.shape[0] * img.shape[1]
# 为色彩分布图像指定宽度和高度:
desired_width = img.shape[1]
desired_height = 70
desired_height_colors = 50
# 初始化色彩分布图像
color_distribution = np.ones((desired_height, desired_width, 3), dtype='uint8') * 255
start = 0
for key, value in counter.items():
# 归一化
value_normalized = value / total * desired_width
end = start + value_normalized
# 绘制与当前颜色对应的矩形
cv2.rectangle(color_distribution, (int(start), 0), (int(end), desired_height_colors), center[key].tolist(), -1)
start = end
return np.vstack((color_distribution, result))
上述代码中,使用 collections.Counter() 来统计分配给每个聚类中心的像素数:
counter = collections.Counter(label.flatten())
例如,如果 K = 10,则可以得到如下结果:
Counter({7: 37199, 3: 36302, 0: 29299, 5: 23987, 6: 23895, 1: 20077, 9: 19814, 8: 18427, 4: 16221, 2: 14779})
构建色彩分布图像后,将其与色彩量化后的图像连接在一起:
np.vstack((color_distribution, result))
程序的输出如下所示:

从上图可以看出,使用 K-Means 聚类算法应用色彩量化后改变参数 k (10、20、30、40、50、60 和 70) 的结果,k 值越大产生的图像越逼真。
Note:除了 color_quantization() 函数外,由于其他代码并未修改,因此不再另外给出。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。
猜你喜欢
python中的append()函数是在列表末尾添加新的对象,且将添加的对象最为一个整体,下面这篇文章主要给大家介绍了关于Python列表append()函数使用方法的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
我们从小学开始背诵九九乘法表,是因为九九乘法表是一切计算的前提,没有九九乘法表,就难以进行计算。而且九九乘法表易于记忆和运算,让我们的数学计算起来更简便,更快捷,更有趣味。九九乘法表这么重要,我们就用for语句来打印乘法表吧。
这篇文章主要介绍了Python 实现绘制子图及子图刻度的变换等问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
Python内置函数-len()函数。python len() 方法返回对象(字符、列表、元组等)长度或项目个数。
文本主要给大家介绍python条件表达式,python中的条件表达式在其他编程语言里也叫做三元运算符,本文会介绍python条件表达式的多项分支和双向分支,以及python双分支选择结构和三元运算符的使用。感兴趣的朋友就跟随小编一起来了解python条件表达式吧。。
成为群英会员,开启智能安全云计算之旅
立即注册关注或联系群英网络
7x24小时售前:400-678-4567
7x24小时售后:0668-2555666
24小时QQ客服
群英微信公众号
CNNIC域名投诉举报处理平台
服务电话:010-58813000
服务邮箱:service@cnnic.cn
投诉与建议:0668-2555555
Copyright © QY Network Company Ltd. All Rights Reserved. 2003-2020 群英 版权所有
增值电信经营许可证 : B1.B2-20140078 ICP核准(ICP备案)粤ICP备09006778号 域名注册商资质 粤 D3.1-20240008