2010-09-20 23 views
13

Ho già dato un'occhiata a questa domanda: SO question e sembrano aver attuato una tecnica molto simile per la sostituzione di un singolo colore compresi i valori alfa:Python: PIL sostituire un singolo colore RGBA

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 

Tuttavia, questo è molto lento. Ho trovato questa ricetta sull'interwebs, ma non ho avuto successo usandolo finora: recipe

Quello che sto cercando di fare è prendere varie immagini PNG che consistono in un singolo colore, bianco. Ogni pixel è bianco al 100% con vari valori alfa, compreso alpha = 0. Ciò che voglio fare è colorare l'immagine con un nuovo colore impostato, ad esempio # ff0000 < 00-ff>. COSÌ le mie immagini iniziali e risultanti apparirebbero come questa dove il lato sinistro è la mia immagine di partenza e la destra è la mia immagine finale (NOTA: lo sfondo è stato modificato in grigio chiaro in modo da poterlo vedere poiché è effettivamente trasparente e non lo si vorrebbe t in grado di vedere i punti a sinistra.)

alt text

un modo migliore per fare questo?

risposta

32

Se si dispone di numpy, fornisce un modo molto più rapido per operare sulle immagini PIL.

Esempio:

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() 

Edit: E 'un Lunedi lento, così ho pensato di aggiungere un paio di esempi:

solo per dimostrare che sta lasciando soli i valori alfa, ecco i risultati per una versione dell'immagine esempio con un gradiente radiale applicato al canale alfa:

originale: alt text

risultati: alt text

+1

Impressionante! Eccezionale! Eccezionale! +1 e contrassegnato come "Accettato". Un enorme risparmio di tempo e risultati sono perfetti. – sberry

+0

@sberry - Felice di aiutare! –

+0

non dovrebbe essere, rosso verde blu? white_areas = – Sekai

2

Il capitolo del libro in linea Pythonware PIL per il Image module stabilisce che putpixel() è lento e suggerisce che può essere velocizzato da inlining. O in base alla versione PIL, usando invece load().

2

Prova questo, in questo esempio impostiamo il colore sul nero se il colore non è bianco.

#!/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) 

è possibile utilizzare selettore di colori in GIMP per assorbire il colore e vedere che è il colore RGBA

Problemi correlati