4

我是 Python 新手,并尝试使用 PIL 执行我需要的 Arduino 项目的解析任务。这个问题与Image.convert()调色板、抖动等的方法和选项有关。

我有一些硬件能够一次仅显示 16 种颜色的图像(但它们可以指定为 RGB 三元组)。因此,我想自动执行获取任意真彩色 PNG 图像的任务,选择“最佳”16 色调色板来表示它,并将图像转换为仅包含 16 种颜色的调色板。

我想使用抖动。问题是,这种image.convert()方法似乎有点古怪。它的论点没有完全记录(Image.convert() 的 PIL 文档),所以我不知道这是我的错还是该方法有问题。

我的代码的简单版本如下:

import Image
MyImageTrueColor = Image.new('RGB',100,100) # or whatever dimension...

# I paste some images from several other PNG files in using MyImageTrueColor.paste()

MyImageDithered = MyImageTrueColor.convert(mode='P',
    colors=16,
    dither=1
    )

根据我所做的一些搜索(例如:如何使用 PIL 减少调色板),我认为这种方法应该可以满足我的要求,但没有运气。它使图像抖动,但会产生超过 16 种颜色的图像。

只是为了确保,我删除了“抖动”参数。相同的输出。

我重新添加了“dither=1”参数并加入了 Image.ADAPTIVE 参数(如上面的链接所示),只是为了看看发生了什么。这导致图像包含 16 种颜色,但没有抖动。

我在这里错过了什么吗?PIL 有问题吗?我想出的解决方案是执行 2 个步骤,但这似乎草率且不必要。我想弄清楚如何正确地做到这一点:-) 为了完整起见,这是我的代码版本,它产生了正确的结果——但它以一种草率的方式做到了。(第一步会产生 >16 色的抖动图像,而第二步会产生仅包含 16 色的图像。)

MyImage_intermediate = MyImageTrueColor.convert(mode='P',
    colors=16
    )
MyImageDithered = MyImage_intermediate.convert(mode='P',
    colors=16,
    dither=1,
    palette=Image.ADAPTIVE
    )

谢谢!

4

1 回答 1

7

好吧,你没有正确调用事物,所以它不应该工作......但即使我们正确调用事物,我也不确定它是否会工作。

首先,PIL 手册的“官方”免费版既不完整又过时;http://effbot.org/imagingbook/image.htm上的草稿版本不那么完整和过时。

im.convert(“P”, **options) ⇒ 图像

相同,但在将“RGB”图像转换为 8 位调色板图像时提供了更好的控制。可用选项有:

抖动=。控制抖动。默认值为 FLOYDSTEINBERG,它将误差分布到相邻像素。要禁用抖动,请使用 NONE。

调色板=。控制调色板生成。默认为 WEB,即标准的 216 色“Web 调色板”。要使用优化的调色板,请使用 ADAPTIVE。

颜色=。当调色板为自适应时,控制用于调色板的颜色数量。默认为最大值,256 色。

colors所以,首先,你不能不使用ADAPTIVE——原因很明显:唯一的另一个选择是WEB,它只处理固定的 216 色调色板。

其次,你不能传递1dither. 如果它恰好是 的值,那可能会起作用FLOYDSTEINBERG,但那是3。因此,您正在传递一个未记录的值;谁知道那会做什么?特别是因为,查看所有听起来像是抖动算法可能名称的常量,它们都没有值 1。

因此,您可以尝试将其更改为dither=Image.FLOYDSTEINBERG(连同palette=Image.ADAPTIVE),看看是否会有所不同。

但是,看看代码,看起来这不会有任何好处:

if mode == "P" and palette == ADAPTIVE:
    im = self.im.quantize(colors)
    return self._new(im)

这发生在我们得到抖动代码之前。所以它与调用(现已弃用/私有)方法 quantize 完全相同。

多个线程表明高级convert功能仅用于公开“抖动到 Web 调色板”或“映射到最近的 N 种颜色”。这似乎与 1.1.6 及更高版本略有不同,但文档和实现仍然不完整。在http://comments.gmane.org/gmane.comp.python.image/2947,其中一位开发人员建议阅读 PIL/Image.py 源代码。

所以,看起来这就是你需要做的。无论Image.convertImage.WEB模式中做什么,您都希望这样做——但使用将由 生成的调色板,而Image.quantize(colors)不是 Web 调色板。

当然,大部分内容都发生在 C 代码中(在self.im.quantizeself.im.convert等)中,但是您可以执行以下伪代码之类的操作:

dummy = img.convert(mode='P', paletter='ADAPTIVE', colors=16)
intermediate = img.copy()
intermediate.setpalette(dummy.palette)
dithered = intermediate._new(intermediate.im.convert('P', Image.FLOYDSTEINBERG))

再说一次,你可能不会。您可能需要查看 C 头文件甚至源代码才能找到答案。或者在 PIL 邮件列表上询问。

PS,如果你不熟悉 PIL 的胆量,img.im就是 PIL Image object 下面的 C 成像对象img。根据我过去的经验,前 3 次浏览 PIL 代码并不清楚,然后突然间一切都变得更有意义了。

于 2012-09-28T19:36:26.783 回答