使用PIL使所有白色像素透明?

时间:2009-04-19 17:13:28

标签: python image python-imaging-library

我正在尝试使用Python Image Library使所有白色像素透明。 (我是一名C黑客,试图学习python,所以要温柔) 我有转换工作(至少像素值看起来正确)但我无法弄清楚如何将列表转换为缓冲区来重新创建图像。这是代码

img = Image.open('img.png')
imga = img.convert("RGBA")
datas = imga.getdata()

newData = list()
for item in datas:
    if item[0] == 255 and item[1] == 255 and item[2] == 255:
        newData.append([255, 255, 255, 0])
    else:
        newData.append(item)

imgb = Image.frombuffer("RGBA", imga.size, newData, "raw", "RGBA", 0, 1)
imgb.save("img2.png", "PNG")

8 个答案:

答案 0 :(得分:65)

您需要进行以下更改:

  • 附加元组(255, 255, 255, 0)而不是列表[255, 255, 255, 0]
  • 使用img.putdata(newData)

这是工作代码:

from PIL import Image

img = Image.open('img.png')
img = img.convert("RGBA")
datas = img.getdata()

newData = []
for item in datas:
    if item[0] == 255 and item[1] == 255 and item[2] == 255:
        newData.append((255, 255, 255, 0))
    else:
        newData.append(item)

img.putdata(newData)
img.save("img2.png", "PNG")

答案 1 :(得分:39)

您还可以使用像素访问模式就地修改图像:

from PIL import Image

img = Image.open('img.png')
img = img.convert("RGBA")

pixdata = img.load()

width, height = image.size
for y in xrange(height):
    for x in xrange(width):
        if pixdata[x, y] == (255, 255, 255, 255):
            pixdata[x, y] = (255, 255, 255, 0)

img.save("img2.png", "PNG")

答案 2 :(得分:7)

import Image
import ImageMath

def distance2(a, b):
    return (a[0] - b[0]) * (a[0] - b[0]) + (a[1] - b[1]) * (a[1] - b[1]) + (a[2] - b[2]) * (a[2] - b[2])

def makeColorTransparent(image, color, thresh2=0):
    image = image.convert("RGBA")
    red, green, blue, alpha = image.split()
    image.putalpha(ImageMath.eval("""convert(((((t - d(c, (r, g, b))) >> 31) + 1) ^ 1) * a, 'L')""",
        t=thresh2, d=distance2, c=color, r=red, g=green, b=blue, a=alpha))
    return image

if __name__ == '__main__':
    import sys
    makeColorTransparent(Image.open(sys.argv[1]), (255, 255, 255)).save(sys.argv[2]);

答案 3 :(得分:2)

由于这是Google搜索“白色到透明的枕头”时的第一个结果,因此我想补充一点,用numpy可以达到同样的效果,并且在我的基准测试中(一张带有很多白色背景的8MP图像) )的速度提高了约10倍(建议的解决方案约为300毫秒vs 3.28 s)。代码也更短:

import numpy as np

def white_to_transparency(img):
    x = np.asarray(img.convert('RGBA')).copy()

    x[:, :, 3] = (255 * (x[:, :, :3] != 255).any(axis=2)).astype(np.uint8)

    return Image.fromarray(x)

对于“几乎白色”(例如,一个通道为254而不是255)为“几乎透明”的版本,它也很容易实现。当然,除了纯黑色之外,这将使整个图片部分透明:

def white_to_transparency_gradient(img):
    x = np.asarray(img.convert('RGBA')).copy()

    x[:, :, 3] = (255 - x[:, :, :3].mean(axis=2)).astype(np.uint8)

    return Image.fromarray(x)

备注:.copy()是必需的,因为默认情况下,枕头图像会转换为只读数组。

答案 4 :(得分:2)

自大循环起,循环需要很长时间,这是一种更Python化的方式

from PIL import Image

img = Image.open('img.png')
img = img.convert("RGBA")

imgnp = np.array(img)

white = np.sum(imgnp[:,:,:3], axis=2)
white_mask = np.where(white == 255*3, 1, 0)

alpha = np.where(white_mask, 0, imgnp[:,:,-1])

imgnp[:,:,-1] = alpha 

img = Image.fromarray(np.uint8(imgnp))
img.save("img2.png", "PNG")

答案 5 :(得分:1)

令我惊讶的是,没有人看到不仅需要更改特定颜色,还需要更改该颜色与其他颜色的混合。这就是 Gimp 对“颜色到 alpha”功能所做的。使用 https://stackoverflow.com/a/62334218/5189462 扩展 cr333 的代码,我们得到类似于此功能的内容:

from PIL import Image

target_color = (255, 255, 255)

img   = Image.open('img.png')
imga  = img.convert("RGBA")
datas = imga.getdata()

newData = list()
for item in datas:
    newData.append((
        item[0], item[1], item[2],
        max( 
            abs(item[0] - target_color[0]), 
            abs(item[1] - target_color[1]), 
            abs(item[2] - target_color[2]), 
        )  
    ))

imgb = Image.frombuffer("RGBA", imga.size, newData, "raw", "RGBA", 0, 1)
imgb.save("img2.png", "PNG")

答案 6 :(得分:0)

Python 3版本,所有文件都位于一个目录中

import glob
from PIL import Image

def transparent(myimage):
    img = Image.open(myimage)
    img = img.convert("RGBA")

    pixdata = img.load()

    width, height = img.size
    for y in range(height):
        for x in range(width):
            if pixdata[x, y] == (255, 255, 255, 255):
                pixdata[x, y] = (255, 255, 255, 0)

    img.save(myimage, "PNG")

for image in glob.glob("*.png"):
    transparent(image)

答案 7 :(得分:-2)

在模式中使用RGBA,如果你打开它 img = img.convert("RGBA") 或 IMG = Image.new(mode="RGB", size=(width,high)) 这样您就可以将 alpha 添加到图像中 IMG.putpixel((Y_Axis, X_Axis),(R, G, B))