使用PIL中的Image.point()方法来处理像素数据

J.J*_*.J. 19 python image-manipulation image image-processing python-imaging-library

我正在使用Python Imaging Library使用定义颜色关系的查找表为黑白图像着色.查找表只是一个256元素的RGB元组列表:

>>> len(colors)
256
>>> colors[0]
(255, 237, 237)
>>> colors[127]
(50, 196, 33)
>>> 
Run Code Online (Sandbox Code Playgroud)

我的第一个版本使用了getpixel()putpixel()方法:

    for x in range(w):
        for y in range(h):
            pix = img.getpixel((x,y))
            img.putpixel((x,y), colors[pix[0]])
Run Code Online (Sandbox Code Playgroud)

这非常缓慢.一份profile报告指出这些putpixelgetpixel方法是罪魁祸首.稍微调查(即阅读文档),我发现" 请注意,这种方法相对较慢. "re : putpixel. (实际运行时间:对于1024x1024图像为53s in putpixelgetpixel50ss)

根据文档中的建议,我使用im.load()并直接使用像素访问:

    pixels = img.load()
    for x in range(w):
        for y in range(h):
            pix = pixels[x, y]
            pixels[x, y] = colors[pix[0]]                
Run Code Online (Sandbox Code Playgroud)

处理加速了一个数量级,但仍然很慢:处理1024x1024图像约3.5秒.

在PIL文档更透彻的研究似乎表明Image.point()正是用于这一目的:

im.point(table) =>图像

im.point(function) =>图像

返回图像的副本,其中每个像素已通过给定表进行映射.该表应包含图像中每个波段256个值.如果使用函数,则应该使用单个参数.对每个可能的像素值调用该函数一次,并将得到的表应用于图像的所有波段.

我花了一些时间来讨论这个界面,但似乎无法让它正确.原谅我的无知,但PIL的文档很简单,我没有太多的图像处理经验.我已经用Google搜索了一些例子,但是没有任何东西可以让我使用"点击".最后,我的问题:

  • Image.point()这项工作是正确的工具吗?
  • Image.point()表格的格式/结构是什么?
  • 有人可以粗略地实现示例吗?到目前为止,我尝试过的每次迭代最终都会产生一个直的黑色图像.

Nad*_*mli 15

Image.point()是这项工作的正确工具吗?

是的,Image.point()对这项工作来说是完美的

Image.point()期望表格的格式/结构是什么?

你应该扁平化列表,而不是[(12, 140, 10), (10, 100, 200), ...]使用:

[12, 140, 10, 10, 100, 200, ...]
Run Code Online (Sandbox Code Playgroud)

这是我刚试过的一个简单示例:

im = im.point(range(256, 0, -1) * 3)
Run Code Online (Sandbox Code Playgroud)

替代文字 替代文字

顺便说一句,如果你需要对颜色更多的控制,你觉得Image.point是不适合你,你也可以使用Image.getdata,并Image.putdata更快速地改变颜色比都loadputpixel.它比较慢Image.point.

Image.getdata为您提供所有像素的列表,修改它们并使用它们将其写回Image.putdata.就这么简单.但首先尝试使用它Image.point.


编辑

我在第一个解释中犯了一个错误,我现在会正确解释:

颜色表实际上是这样的

[0, 1, 2, 3, 4, 5, ...255, 0, 1, 2, 3, ....255, 0, 1, 2, 3, ...255]
Run Code Online (Sandbox Code Playgroud)

每个频段都在另一个频段旁边.要将颜色(0,0,0)更改为(10,100,10),需要变为如下所示:

[10, 1, 2, 3, 4, 5, ...255, 100, 1, 2, 3, ....255, 10, 1, 2, 3, ...255]
Run Code Online (Sandbox Code Playgroud)

要将颜色列表转换为正确的格式,请尝试以下操作:

table = sum(zip(*colors), ())
Run Code Online (Sandbox Code Playgroud)

我想我的第一个例子应该为你演示合成.

  • 你知道,我认为这可能是互联网上唯一的地方,其中描述了该表的预期格式.//感谢您的描述,我让img.point()使用查找表.结果并不完全符合我的预期,但我已经足够破解并弄清楚了.非常感谢! (4认同)