我正在使用 Python 成像库 通过查找表对黑白图像进行着色,该查找表定义了颜色关系。查找表只是一个包含 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
方法是罪魁祸首。经过一番调查(即阅读文档),我发现“请注意,此方法相对较慢。”回复:putpixel
。 (实际运行时间:对于 1024x1024 图像,putpixel
需要 53 秒,getpixel
需要 50 秒)
根据文档中的建议,我使用了 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)
=>;图片
im.point(函数)
=>图片
返回图像的副本,其中每个像素都已通过给定表进行映射。该表应包含图像中每个波段 256 个值。如果改用函数,则它应该采用单个参数。对于每个可能的像素值调用该函数一次,并将结果表应用于图像的所有波段。
我花了一些时间修改界面,但似乎不太正确。原谅我的无知,但是 PIL 的文档很简短,而且我没有太多的图像处理经验。我用谷歌搜索了一下,找到了一些例子,但没有什么能让我“点击”这个用法。因此,最后我的问题
- 是:
Image.point()
是完成这项工作的正确工具吗?
-
Image.point()
需要什么格式/结构的表格?
- 有人可以粗略地给出一个示例实现吗?到目前为止,我尝试过的每次迭代都以纯黑色图像结束。
I am using the Python Imaging Library to colorize a black and white image with a lookup table that defines the color relationships. The lookup table is simply a 256-element list of RGB tuples:
>>> len(colors)
256
>>> colors[0]
(255, 237, 237)
>>> colors[127]
(50, 196, 33)
>>>
My first version used the getpixel()
and putpixel()
methods:
for x in range(w):
for y in range(h):
pix = img.getpixel((x,y))
img.putpixel((x,y), colors[pix[0]])
This was horribly slow. A profile
report pointed to the putpixel
and getpixel
methods as the culprits. A little investigation (i.e, read the docs) and I find "Note that this method is relatively slow." re: putpixel
. (actual runtime: 53s in putpixel
and 50s getpixel
for a 1024x1024 image)
Based on the suggestion in the docs, I used im.load()
and direct pixel access instead:
pixels = img.load()
for x in range(w):
for y in range(h):
pix = pixels[x, y]
pixels[x, y] = colors[pix[0]]
Processing sped up by an order of magnitude, but is still slow: about 3.5s to process a 1024x1024 image.
A more thorough study of the PIL docs seems to indicate Image.point()
is exactly intended for this purpose:
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.
I've spent some time hacking around with the interface, but can't quite seem to get it right. Forgive my ignorance, but PIL's docs are curt and I don't have much image processing experience. I've googled around a bit and turned up a few examples, but nothing that made the usage "click" for me. Thus, finally, my questions:
- Is
Image.point()
the right tool for this job?
- What format/structure does
Image.point()
expect the table?
- Can someone rough out an example implementation? Every iteration I've tried so far has ended up with a straight black image.
发布评论
评论(2)
是的,确实,
Image.point()
非常适合这项工作您应该展平列表,而不是使用
[(12, 140, 10), (10, 100, 200), ...]
:这是我刚刚尝试过的一个简单示例:
顺便说一下,如果您需要更多地控制颜色并且您觉得 Image.point 不适合您,您可以还可以使用
Image.getdata
和Image.putdata
比load
和putpixel
更快地更改颜色。但它比 Image.point 慢。Image.getdata
为您提供所有像素的列表,修改它们并使用Image.putdata
将它们写回。就是这么简单。但首先尝试使用Image.point
来实现。编辑
我在第一个解释中犯了一个错误,现在我将正确解释:
颜色表实际上是这样的
每个波段范围彼此相邻。
要将颜色 (0, 0, 0) 更改为 (10, 100, 10),它需要变成这样:
要将颜色列表转换为正确的格式,请尝试以下操作:
我认为我的第一个示例应该为您演示格式。
Yes indeed,
Image.point()
is perfect for this jobYou should flatten the list so instead of
[(12, 140, 10), (10, 100, 200), ...]
use:Here is a quick example I just tried:
And by the way, if you need more control over colors and you feel Image.point is not for you you can also use
Image.getdata
andImage.putdata
to change colors more quickly than bothload
andputpixel
. It is slower thanImage.point
though.Image.getdata
gives you the list of all pixels, modify them and write them back usingImage.putdata
. It is that simple. But try to do it usingImage.point
first.EDIT
I made a mistake in the first explanation, I'll explain correctly now:
The color table actually is like this
Each band range next to the other.
To change the color (0, 0, 0) to (10, 100, 10) it need to become like this:
To transform your color list into the right format try this:
I think my first example should demonstrate the formate for you.
我认为在逐个频段的基础上
点
可能更典型(直接从PIL 教程):I think it might be more typical to
point
on a band-by-band basis like so (lifted directly from the PIL tutorial):