web-dev-qa-db-fra.com

Utiliser PIL pour rendre tous les pixels blancs transparents?

J'essaie de rendre tous les pixels blancs transparents en utilisant la bibliothèque d'images Python. (Je suis un pirate C essayant d'apprendre python alors soyez doux)) I 'ai réussi la conversion (au moins les valeurs en pixels semblent correctes) mais je ne sais pas comment convertir la liste en tampon pour recréer l'image. Voici le code

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")
50
haseman

Vous devez apporter les modifications suivantes:

  • ajouter un tuple (255, 255, 255, 0) et non une liste [255, 255, 255, 0]
  • utilisez img.putdata(newData)

Voici le code de travail:

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")
70
cr333

Vous pouvez également utiliser le mode d'accès aux pixels pour modifier l'image sur place:

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")
39
keithb
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 __== '__main__':
    import sys
    makeColorTransparent(Image.open(sys.argv[1]), (255, 255, 255)).save(sys.argv[2]);
7
Dardo

Étant donné qu'il s'agit actuellement du premier résultat Google en recherchant "Oreiller blanc à transparent", j'aimerais ajouter que la même chose peut être obtenue avec numpy, et dans mon benchmark (une seule image 8MP avec beaucoup de fond blanc) est d'environ 10 fois plus rapide (environ 300 ms vs 3,28 s pour la solution proposée). Le code est également un peu plus court:

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)

Il est également facilement échangeable vers une version où le "presque blanc" (par exemple un canal est 254 au lieu de 255) est "presque transparent". Bien sûr, cela rendra l'image entière partiellement transparente, à l'exception du noir pur:

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)

Remarque: la .copy() est nécessaire car par défaut les images Pillow sont converties en tableaux en lecture seule.

2
Marco Spinaci

Version Python 3 avec tous les fichiers dans un répertoire

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)
0
Giovanni Python