2009-07-10 19 views
19

Les gars, je suis à la recherche d'un peu d'aide. Je suis un programmeur novice et l'un des problèmes que j'ai à la minute est de convertir une image & .jpg en une liste que je peux ensuite moduler en un signal audio. Cela fait partie d'un projet de lager pour créer un programme SSTV python.Obtenir la liste des valeurs de pixel de PIL

J'ai importé le module PIL et j'essaie d'appeler la fonction intégrée: list(im.getdata()). Quand je l'appelle, python se bloque. Existe-t-il un moyen de décomposer l'image (toujours 320x240) en 240 lignes pour faciliter les calculs? Ou suis-je juste appeler la mauvaise fonction.

Si quelqu'un a des suggestions s'il vous plaît allumer. Si quelqu'un a l'expérience de générer des sons audio modulés à l'aide de python, j'accepterais volontiers toutes les «perles de sagesse» qu'ils sont prêts à transmettre. Merci d'avance

+1

quel est votre 'im'? – SilentGhost

+2

Y compris le message que vous obtenez quand il s'est écrasé serait vraiment utile – dbr

Répondre

46

Python ne devrait pas planter lorsque vous appelez getdata(). L'image peut être corrompue ou il y a un problème avec votre installation PIL. Essayez-le avec une autre image ou postez l'image que vous utilisez.

Cela devrait briser l'image comme vous voulez:

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

* 'liste (im.getdata())'. Quand je l'appelle, python se bloque. * – SilentGhost

+0

Lorsque j'appelle la liste (im.getdata()), non seulement python plante (vraisemblablement), mais tout mon système Linux ne répond plus. Le redémarrage dur résout ce problème. –

+0

il se bloque à la fois sur Windows et Linux. Je commence à penser à la stabilité de PIL. –

24

Si vous avez numpy installé, vous pouvez essayer:

data = numpy.asarray(im) 

(je dis « essayer » ici, car on ne sait pas pourquoi getdata() ne fonctionne pas pour vous, et je ne sais pas si asarray utilise getdata, mais ça vaut le test.)

+1

+1: bonne façon d'obtenir rapidement le tableau des valeurs de pixels! – EOL

11

Je suppose que vous obtenez un er comme .. TypeError: 'PixelAccess' object is not iterable ...?

Voir la documentation Image.load pour savoir comment accéder à des pixels ..

En gros, pour obtenir la liste des pixels dans une image, en utilisant 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) 

chaque pixel qui ajoute à la all_pixels - si le fichier est une image RVB (même si elle ne contient qu'une image en noir et blanc) ce sera un tuple, par exemple:

(255, 255, 255) 

Pour convertir l'image en noir et blanc, vous en moyenne que les trois valeurs - donc, les trois dernières lignes de code deviendraient ..

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) 

Ou pour obtenir la luminance (moyenne pondérée):

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

Ou pur 1-bit à la recherche en noir et blanc:

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

Il y a probablement des méthodes dans PIL pour faire de telles conversions RGB -> BW plus rapide, mais cela fonctionne, et ne partic surtout lent.

Si vous souhaitez uniquement effectuer des calculs sur chaque ligne, vous pouvez ignorer l'ajout de tous les pixels à une liste intermédiaire.Par exemple, pour calculer la valeur moyenne de chaque ligne:

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

Ou si vous voulez compter les pixels blancs ou noirs

Ceci est également une solution:

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

Comme je l'ai commenté ci-dessus , le problème semble être la conversion du format de liste interne PIL à un type de liste Python standard. J'ai trouvé que Image.tostring() est beaucoup plus rapide, et en fonction de vos besoins, cela pourrait suffire. Dans mon cas, j'avais besoin de calculer le condensé CRC32 des données d'image, et cela convenait bien.

Si vous devez effectuer des calculs plus complexes, la réponse tom10 impliquant numpy pourrait être ce dont vous avez besoin.

1

Non PIL, mais scipy.misc.imread pourrait encore être intéressant:

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

donne

(480, 640, 3) 

il est donc (hauteur, largeur, canaux). Ainsi, vous pouvez itérer par

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

On dirait que Pillow peut avoir changé tostring()-tobytes(). Lorsque j'ai essayé d'extraire des pixels RGBA pour les obtenir dans une texture OpenGL, ce qui suit a fonctionné pour moi (dans l'appel glTexImage2D que j'omets par souci de brièveté).

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) 

Avis: En PIL, img RGBA. En cv2, img est BGRA.

Ma solution robuste:

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