2009-07-10 2 views
19

Ragazzi, sto cercando un po 'di assistenza. Sono un programmatore principiante e uno dei problemi che sto avendo al momento sta cercando di convertire un'immagine nera bianca in una lista che posso quindi modulare in un segnale audio. Questo fa parte di un progetto lager per creare un programma SSTV python.Ottenere l'elenco dei valori dei pixel da PIL

Ho importato il modulo PIL e sto provando a chiamare la funzione integrata: list(im.getdata()). Quando lo chiamo, python si blocca. C'è un modo di scomporre l'immagine (sempre 320x240) in 240 linee per semplificare i calcoli? O sto solo chiamando la funzione sbagliata.

Se qualcuno ha qualche suggerimento si prega di sparare. Se qualcuno ha esperienza nel generare toni audio modulati usando python, accetterei volentieri le "perle di saggezza" che sono disposte a comunicare. Grazie in anticipo

+1

qual è la sua 'im'? – SilentGhost

+2

Includere il messaggio che si ottiene quando si è arrestato in modo anomalo sarebbe davvero utile – dbr

risposta

46

Python non dovrebbe arrestarsi in modo anomalo quando si chiama getdata(). L'immagine potrebbe essere corrotta o c'è qualcosa di sbagliato nell'installazione del tuo PIL. Provalo con un'altra immagine o pubblica l'immagine che stai utilizzando.

Questo dovrebbe abbattere l'immagine nel modo desiderato:

from PIL import Image 
im = Image.open('um_000000.png') 

pixels = list(im.getdata()) 
width, height = im.size 
pixels = [pixels[i * width:(i + 1) * width] for i in xrange(height)] 
+5

* 'list (im.getdata())'. Quando lo chiamo, python si blocca. * – SilentGhost

+0

Quando chiamo list (im.getdata()), non solo python si blocca (presumibilmente), ma il mio intero sistema linux non risponde. Il riavvio hardware risolve questo problema. –

+0

si blocca su entrambi, windows e linux. sto iniziando a pensare alla stabilità del PIL. –

24

Se avete numpy installato è possibile provare:

data = numpy.asarray(im) 

(dico "provare" qui, perché non è chiaro il motivo per cui getdata() non funziona per voi, e non so se asarray usa getdata, ma vale la pena di un test.)

+1

+1: bel modo per ottenere rapidamente l'array di valori di pixel! – EOL

11

presumo certi di acquistare una ER Per esempio ... TypeError: 'PixelAccess' object is not iterable ...?

Vedere la documentazione Image.load per come accedere pixel ..

In sostanza, per ottenere l'elenco di pixel in un'immagine, utilizzando PIL:

from PIL import Image 
i = Image.open("myfile.png") 

pixels = i.load() # this is not a list, nor is it list()'able 
width, height = i.size 

all_pixels = [] 
for x in range(width): 
    for y in range(height): 
     cpixel = pixels[x, y] 
     all_pixels.append(cpixel) 

che aggiunge ogni pixel al all_pixels - se il file è un'immagine RGB (anche se contiene solo un'immagine in bianco e nero) si tratta di una tupla, ad esempio:

(255, 255, 255) 

per convertire l'immagine di bianco e nero, è solo nella media dei tre valori - così, le ultime tre righe di codice diventerebbero ..

cpixel = pixels[x, y] 
bw_value = int(round(sum(cpixel)/float(len(cpixel)))) 
# the above could probably be bw_value = sum(cpixel)/len(cpixel) 
all_pixels.append(bw_value) 

O per ottenere la luminanza (media ponderata):

cpixel = pixels[x, y] 
luma = (0.3 * cpixel[0]) + (0.59 * cpixel[1]) + (0.11 * cpixel[2]) 
all_pixels.append(luma) 

O puro 1-bit guardare in bianco e nero:

cpixel = pixels[x, y] 
if round(sum(cpixel))/float(len(cpixel)) > 127: 
    all_pixels.append(255) 
else: 
    all_pixels.append(0) 

C'è probabilmente metodi all'interno PIL da fare tali RGB -> BW conversioni più veloce, ma questo funziona, e non è partico particolarmente lento.

Se si desidera eseguire solo calcoli su ciascuna riga, è possibile saltare l'aggiunta di tutti i pixel a un elenco intermedio.Ad esempio, per calcolare il valore medio di ogni riga:

from PIL import Image 
i = Image.open("myfile.png") 

pixels = i.load() # this is not a list 
width, height = i.size 
row_averages = [] 
for y in range(height): 
    cur_row_ttl = 0 
    for x in range(width): 
     cur_pixel = pixels[x, y] 
     cur_pixel_mono = sum(cur_pixel)/len(cur_pixel) 
     cur_row_ttl += cur_pixel_mono 

    cur_row_avg = cur_row_ttl/width 
    row_averages.append(cur_row_avg) 

print "Brighest row:", 
print max(row_averages) 
3

Oppure, se si vuole contare i pixel bianchi o neri

Questa è anche una soluzione:

from PIL import Image 
import operator 

img = Image.open("your_file.png").convert('1') 
black, white = img.getcolors() 

print black[0] 
print white[0] 
1

Come ho commentato in precedenza , il problema sembra essere la conversione dal formato di elenco interno di PIL a un tipo di elenco python standard. Ho notato che Image.tostring() è molto più veloce e, a seconda delle esigenze, potrebbe essere sufficiente. Nel mio caso, avevo bisogno di calcolare il digest CRC32 dei dati di immagine, e andava bene.

Se è necessario eseguire calcoli più complessi, la risposta di tom10 che coinvolge numpy potrebbe essere ciò di cui si ha bisogno.

1

Non PIL, ma scipy.misc.imread potrebbe essere comunque interessante:

import scipy.misc 
im = scipy.misc.imread('um_000000.png', flatten=False, mode='RGB') 
print(im.shape) 

(480, 640, 3) 

quindi è (altezza, larghezza, canali). Così si può scorrere su di esso da

for y in range(im.shape[0]): 
    for x in range(im.shape[1]): 
     color = tuple(im[y][x]) 
     r, g, b = color 
0

Sembra cuscino potrebbe essere cambiato tostring()-tobytes(). Quando si tenta di estrarre i pixel RGBA per inserirli in una trama OpenGL, per me ha funzionato (all'interno della chiamata glTexImage2D che ometto per brevità).

from PIL import Image 
img = Image.open("mandrill.png").rotate(180).transpose(Image.FLIP_LEFT_RIGHT) 

# use img.convert("RGBA").tobytes() as texels 
0
data = numpy.asarray(im) 

Avviso: In PIL, IMG è RGBA. In cv2, img è BGRA.

mia soluzione robusta:

def cv_from_pil_img(pil_img): 
    assert pil_img.mode=="RGBA" 
    return cv2.cvtColor(np.array(pil_img), cv2.COLOR_RGBA2BGRA)