使用Python和Pillow,我们如何计算PNG或JPG图像中唯一颜色的数量?

4
我正在使用Pillow进行一些图像操作,并希望计算PNG或JPG图像文件中有多少个唯一颜色。如果是模式“P”图像,拥有少量颜色,那么我可以轻松地完成此操作,但对于RGB或RGBA图像则不行。通过阅读Pillow的文档,似乎 Image.getcolors()在存在256种以上颜色时会返回 None
最佳方法是什么呢?我们可以使用Pillow吗? 我的目标是纯Python + Pillow,但如果有必要,我可以将numpy列入我的依赖项列表。

循环遍历所有像素并将它们添加到一个set中? - Mad Physicist
1
Image.getcolors()默认最大为256,但您可以将其更改为Image.getcolors(maxcolors=1024)或任何您需要的值。 - John Anderson
1
实际上,如果我打开一个JPEG照片,即使我使用maxcolors=调用Image.getcolors(),它也会返回None。难道它不应该适用于RGB JPEG文件吗? - Victor Domingos
2个回答

2

一种可能的解决方案(我将PNG图像编码为Base64):

from PIL import Image
from io import BytesIO
import base64

data = '''iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAYAAABccqhmAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB+ACCAAXMEa+fpcAAAAdaVRYdENvbW1lbnQAAAAAAENyZWF0ZWQgd2l0aCBHSU1QZC5lBwAAAx9JREFUeNrt3MtNA1EMQFGMpqWIgpAiakJKA6mBBrJOL2wfBYQVDrI9c85+8pnPlWfxXrxQbSWPD6eQv3p1CkAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEAurKWPC+1nv/z/S315efLzT2ICQAQAEAAAAEABAAQAEAAAAEABAAEABAAQAAAAQAEABAAYH+sxc4r3Q8g6+vju/T7r6e7e9gEAAgAIACAAAACAAgAIACAAAACAAgAIACAAAACAAgAIADAo236H1jJ45+wmDz1EefLbfR+ApgAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAD4F5tTcGzX0736J4SrYAIABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAOBB+X4AK3l85D+C2bdAtdH7GZgAwCsAIACAAAACAAgAIACAAAACAAgAIACAAAACAAgAIABAWx3WMq+yg12A2Rd/H9ev9BYwAYBXAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAgLaesRb50Ov5ofgBTH2ECQC8AgACAAgAIACAAAACAAgAIACAAAACAAgAIACAAAACALS1OQWMtop3lIgYffpMAOAVABAAQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEABAAoC37ATBbdj1+9X4CJgBAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAH5nPwCOLbufgAkAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAAQAEABAAAABAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAKBKNPgNq+xgqH+ASp9BEwB4BQAEABAAQAAAAQAEABAAQAAAAQAEABAAQAAAAQAEAGgrdvAf7CdA5QMw+hkyAYBXAEAAAAEABAAQAEAAAAEABAAQAEAAAAEABAAQAEAAgLbCKbAlgGfABAAIACAAgAAAAgAIACAAgAAAAgAIACAAgAAAAgAIACAAQDs/+5skuT18qwIAAAAASUVORK5CYII='''

img = Image.open(BytesIO(base64.b64decode(data)))

unique_colors = set()
for i in range(img.size[0]):
    for j in range(img.size[1]):
        pixel = img.getpixel((i, j))
        unique_colors.add(pixel)

print('Image info = ', img)
print('Unique color count = ', len(unique_colors))

输出:

Image info =  <PIL.PngImagePlugin.PngImageFile image mode=RGBA size=256x256 at 0x7FFFF670A400>
Unique color count =  7

看起来它按预期工作。我希望有一些更快的方法来完成它。但也许这就是Pillow能做到的最好的了... - Victor Domingos
2
我能够使用集合推导式在一些大图像上节省几秒钟的时间,这似乎运行得更快:unique_colors = {img.getpixel((x,y)) for x in range(w) for y in range(h) } - Victor Domingos
很遗憾,这个问题已经关闭,不再接受新的回答,但是这个方法似乎更快:len(set(img.getdata())),请参见https://dev59.com/PG445IYBdhLWcg3w5OMI#59709420。 - mmj

0

能否列出像素RGB并进行扫描?正如John Anderson所说,您可以使用Image.getcolors来获取它。但是要获取唯一变量的数量,您可以将其转换为集合,这会删除重复项,然后获取其长度,使用len(set(list))


是的,这就是Andrej Kesey建议的方法。而且看起来效果也符合预期。我本来希望能找到更快的方法来完成它。但也许这已经是Pillow所能达到的最好状态了。 - Victor Domingos

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接