首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在PIL中使用Image.point()方法操作像素数据

在PIL中使用Image.point()方法操作像素数据
EN

Stack Overflow用户
提问于 2010-02-02 09:12:34
回答 2查看 35.1K关注 0票数 21

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

代码语言:javascript
复制
>>> len(colors)
256
>>> colors[0]
(255, 237, 237)
>>> colors[127]
(50, 196, 33)
>>> 

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

代码语言:javascript
复制
    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为53s,getpixel为50s )

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

代码语言:javascript
复制
    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) =>图像

im.point(function) =>图像

返回图像的副本,其中每个像素都通过给定表进行了映射。该表应包含图像中每个波段的256个值。如果改用函数,它应该只有一个参数。该函数针对每个可能的像素值调用一次,并将结果表应用于图像的所有波段。

我花了一些时间修改界面,但似乎不能完全理解它。请原谅我的无知,但是PIL的文档很简短,而且我没有太多的图像处理经验。我在谷歌上搜索了一下,找出了一些例子,但没有什么能让我理解"click“这个用法的。因此,最后,我的问题是:

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

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-02-02 09:33:43

对于这项工作,

()是正确的工具吗?

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

Image.point()需要什么格式/结构的表?

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

代码语言:javascript
复制
[12, 140, 10, 10, 100, 200, ...]

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

代码语言:javascript
复制
im = im.point(range(256, 0, -1) * 3)

顺便说一句,如果你需要更多的颜色控制,并且你觉得Image.point不适合你,你也可以使用Image.getdataImage.putdata来比loadputpixel更快地改变颜色。不过,它比Image.point慢。

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

编辑

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

颜色表实际上是这样的

代码语言:javascript
复制
[0, 1, 2, 3, 4, 5, ...255, 0, 1, 2, 3, ....255, 0, 1, 2, 3, ...255]

每个波段范围紧挨着另一个。要将颜色(0,0,0)更改为(10,100,10),需要如下所示:

代码语言:javascript
复制
[10, 1, 2, 3, 4, 5, ...255, 100, 1, 2, 3, ....255, 10, 1, 2, 3, ...255]

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

代码语言:javascript
复制
table = sum(zip(*colors), ())

我认为我的第一个示例应该为您演示formate。

票数 15
EN

Stack Overflow用户

发布于 2010-02-02 10:07:50

我认为这可能是更典型的逐带基础上的point (直接从PIL tutorial中提升):

代码语言:javascript
复制
# 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)
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2181292

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档