我使用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
报告指出putpixel
和getpixel
方法是罪魁祸首。稍微调查(即阅读文档),我发现“请注意,此方法相对较慢。”re:putpixel
。 (实际运行时:putpixel
中的53s和1024x1024图像的50s getpixel
根据文档中的建议,我使用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]]
处理加速了一个数量级,但仍然慢:约3.5秒来处理1024x1024图像。
对PIL文档进行更彻底的研究似乎表明Image.point()
正好用于此目的:
im.point(table)
=>图像
im.point(function)
=>图像返回图像的副本,其中每个像素已通过给定的表进行映射。该表应包含图像中每个波段256个值。如果使用函数,则应该使用单个参数。对每个可能的像素值调用该函数一次,并将结果表应用于图像的所有波段。
我花了一些时间来讨论这个界面,但看起来似乎并不是很正确。原谅我的无知,但PIL的文档很简单,我没有太多的图像处理经验。我已经用Google搜索了几个例子,但是没有任何东西可以让我使用“点击”。最后,我的问题:
Image.point()
是否适合这项工作?Image.point()
期望表格的格式/结构是什么?答案 0 :(得分:15)
Image.point()是否是正确的工具 这份工作?
是的,Image.point()
非常适合这项工作
什么格式/结构 Image.point()期望表?
您应该扁平化列表,而不是[(12, 140, 10), (10, 100, 200), ...]
使用:
[12, 140, 10, 10, 100, 200, ...]
以下是我刚试过的一个简单示例:
im = im.point(range(256, 0, -1) * 3)
顺便说一句,如果您需要更多控制颜色并且感觉Image.point不适合您,您还可以使用Image.getdata
和Image.putdata
更快地更改颜色{{1 }和load
。它虽然比putpixel
慢。
Image.point
为您提供所有像素的列表,修改它们并使用Image.getdata
将其写回。就这么简单。但首先尝试使用Image.putdata
。
修改强>
我在第一个解释中犯了一个错误,我现在会正确解释:
颜色表实际上就像这样
Image.point
每个频段都在另一个频段旁边。 要将颜色(0,0,0)更改为(10,100,10),需要变为如下:
[0, 1, 2, 3, 4, 5, ...255, 0, 1, 2, 3, ....255, 0, 1, 2, 3, ...255]
要将颜色列表转换为正确的格式,请尝试:
[10, 1, 2, 3, 4, 5, ...255, 100, 1, 2, 3, ....255, 10, 1, 2, 3, ...255]
我认为我的第一个例子应该为你演示合成。
答案 1 :(得分:3)
我认为point
在逐个频段的基础上可能更为典型(直接从PIL tutorial提取):
# 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)