首页 > 解决方案 > 如何使用 RGB 图像上的调色板提取主色?

问题描述

我正在尝试构建一个可以从图像中提取主色的模块。例如,我试图从这个标志图像中提取四种颜色:

在此处输入图像描述

如果我尝试在 RGB 模式下使用 and 方法,则getpalette返回getcolorsNone(我试过设置maxcolors,我仍然得到None。)

paletted = img.convert('RGB', palette=Image.ADAPTIVE, colors=4)
print(paletted.getpalette())
print(paletted.getcolors(maxcolors=256))
# None
# None

如果我转换为P模式,我可以使用这些模块,但我失去了黄色。

paletted = img.convert('P', palette=Image.ADAPTIVE, colors=4)
paletted.show()

在此处输入图像描述

我在这里做错了什么?

标签: pythoncolorspython-imaging-librarycolor-palette

解决方案


首先,以下不起作用,或者准确地说,只是被忽略:

paletted = img.convert('RGB', palette=Image.ADAPTIVE, colors=4)

从文档中Image.convert

调色板- 从模式“RGB”转换为“P”时使用的调色板。可用的调色板是WEBADAPTIVE

您正在从RGBto转换RGB,因此paletteandcolors参数被忽略。

下一个问题,这也阻止了正确转换为模式P:您有一个带有 JPG 工件的 JPG 图像。您的图像包含的颜色比您预期的要多得多。从文档中Image.getcolors

maxcolors – 最大颜色数。如果超过此数字,则此方法返回 None。默认限制为 256 色。

增加maxcolors(对于某些完整的 24 位 RGB 图像,不同颜色的最大可能数量为 2 24),并检查四种最突出的颜色:

from PIL import Image

img = Image.open('47ckF.jpg')
n_dom_colors = 4
dom_colors = sorted(img.getcolors(2 ** 24), reverse=True)[:n_dom_colors]
print(dom_colors)
# [(135779, (0, 0, 0)), (132476, (0, 0, 254)), (109155, (254, 0, 0)), (2892, (251, 2, 0))]

你会得到纯黑色、几乎纯蓝色、几乎纯红色和红色的变体。黄色在哪里?JPG神器!你有大量的黑色、蓝色和红色,它们都比第一个黄色更突出。例如,即使设置n_dom_colors = 20也不会显示第一个黄色。

如何实现,您可能会想到什么?看看Image.quantize,它将为您提供P使用颜色量化的模式图像:

from PIL import Image

img = Image.open('47ckF.jpg')
img = img.quantize(colors=4, kmeans=4).convert('RGB')
n_dom_colors = 4
dom_colors = sorted(img.getcolors(2 ** 24), reverse=True)[:n_dom_colors]
print(dom_colors)
# [(139872, (1, 0, 1)), (138350, (0, 0, 253)), (134957, (252, 1, 1)), (3321, (253, 240, 12))]

你会得到几乎纯黑色、几乎纯蓝色、几乎纯红色和黄色变体!

作为参考,量化和重新转换的图像:

量化

----------------------------------------
System information
----------------------------------------
Platform:      Windows-10-10.0.16299-SP0
Python:        3.9.1
PyCharm:       2021.1.1
Pillow:        8.2.0
----------------------------------------

推荐阅读