使用PIL中的Image.point()方法操作像素d

2024-09-28 20:47:05 发布

您现在位置:Python中文网/ 问答频道 /正文

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

>>> len(colors)
256
>>> colors[0]
(255, 237, 237)
>>> colors[127]
(50, 196, 33)
>>> 

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

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

太慢了。一份profile报告指出,putpixelgetpixel方法是罪魁祸首。稍加调查(即阅读文档),我发现“注意,这种方法相对较慢。“回复:putpixel。(对于1024x1024图像,putpixel和50sgetpixel中的实际运行时:53s)

根据文档中的建议,我使用了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]]                

处理速度提高了一个数量级,但仍然很慢:处理1024x1024图像的时间约为3.5秒。

对PIL文档进行更深入的研究似乎表明,Image.point()正是为了这个目的而设计的:

im.point(table) => image

im.point(function) => image

Returns a copy of the image where each pixel has been mapped through the given table. The table should contains 256 values per band in the image. If a function is used instead, it should take a single argument. The function is called once for each possible pixel value, and the resulting table is applied to all bands of the image.

我花了一些时间修改界面,但似乎不能完全正确。请原谅我的无知,但皮尔的文件是简略的,我没有太多的图像处理经验。我在谷歌上搜索了一下,找到了一些例子,但没有什么能让我使用“点击”。因此,最后,我的问题是:

  • Image.point()是这项工作的正确工具吗?
  • Image.point()需要什么格式/结构的表?
  • 有人能给出一个示例实现吗?到目前为止,我尝试过的每一个迭代都以一个直接的黑色图像结束。

Tags: the方法in文档图像imageimgfor
2条回答

Is Image.point() the right tool for this job?

是的,确实,Image.point()非常适合这个工作

What format/structure does Image.point() expect the table?

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

[12, 140, 10, 10, 100, 200, ...]

下面是我刚刚尝试的一个快速示例:

im = im.point(range(256, 0, -1) * 3)

alt textalt text

顺便说一下,如果你需要更多的颜色控制并且你觉得Image.point不适合你,你也可以使用Image.getdataImage.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]

每个波段都是相邻的。 要将颜色(0,0,0)更改为(10,100,10),需要如下所示:

[10, 1, 2, 3, 4, 5, ...255, 100, 1, 2, 3, ....255, 10, 1, 2, 3, ...255]

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

table = sum(zip(*colors), ())

我认为我的第一个例子应该为您演示格式。

我认为像so(直接从PIL tutorial)这样的逐带基础上point可能更为典型:

# split the image into individual bands
source = im.split()

R, G, B = 0, 1, 2

# select regions where red is less than 100
mask = source[R].point(lambda i: i < 100 and 255)

# process the green band
out = source[G].point(lambda i: i * 0.7)

# paste the processed band back, but only where red was < 100
source[G].paste(out, None, mask)

# build a new multiband image
im = Image.merge(im.mode, source)

相关问题 更多 >