Python: PIL替换单一RGBA颜色

47 投票
4 回答
70453 浏览
提问于 2025-04-16 04:22

我之前看过这个问题:SO问题,似乎已经实现了一种很相似的方法来替换单一颜色,包括透明度的值:

c = Image.open(f)
c = c.convert("RGBA")
w, h = c.size
cnt = 0
for px in c.getdata():
    c.putpixel((int(cnt % w), int(cnt / w)), (255, 0, 0, px[3]))
    cnt += 1                                                                                                   

不过,这个方法速度很慢。我在网上找到过这个做法,但到现在为止还没有成功使用。

我想做的是处理一些只包含单一颜色(白色)的PNG图片。每个像素都是100%白色,透明度各不相同,包括透明度为0的情况。我想做的就是把这些图片换成一种新的颜色,比如#ff0000<00-ff>。所以我的起始图像和最终图像看起来是这样的,左边是我的起始图像,右边是我的最终图像(注意:背景已经换成浅灰色,这样你能看到,因为实际上它是透明的,左边的点你是看不见的)。

alt text

有没有更好的方法来做到这一点?

4 个回答

5

Pythonware的PIL在线书籍中关于图像模块的章节提到,putpixel()这个函数运行得比较慢。为了提高速度,建议可以通过内联的方式来加快它的运行速度。或者根据你使用的PIL版本,可以考虑使用load()函数来替代。

15

试试这个,在这个例子中,如果颜色不是白色,我们就把颜色设置为黑色。

#!/usr/bin/python
from PIL import Image
import sys

img = Image.open(sys.argv[1])
img = img.convert("RGBA")

pixdata = img.load()

# Clean the background noise, if color != white, then set to black.

for y in xrange(img.size[1]):
    for x in xrange(img.size[0]):
        if pixdata[x, y] == (255, 255, 255, 255):
            pixdata[x, y] = (0, 0, 0, 255)

你可以在GIMP这个软件里使用颜色选择器来吸取颜色,这样就能看到它的rgba颜色值。

91

如果你有使用numpy这个库,它可以让你对PIL图像进行更快的操作。

比如说:

import Image
import numpy as np

im = Image.open('test.png')
im = im.convert('RGBA')

data = np.array(im)   # "data" is a height x width x 4 numpy array
red, green, blue, alpha = data.T # Temporarily unpack the bands for readability

# Replace white with red... (leaves alpha values alone...)
white_areas = (red == 255) & (blue == 255) & (green == 255)
data[..., :-1][white_areas.T] = (255, 0, 0) # Transpose back needed

im2 = Image.fromarray(data)
im2.show()

补充说明:今天是个慢吞吞的星期一,所以我想加几个例子:

为了展示它是如何保持透明度(alpha值)不变的,这里是你示例图像的一个版本,应用了径向渐变到透明度通道的结果:

原图: alt text

结果图: alt text

撰写回答