2009-07-10 16 views
19

Chicos, estoy buscando un poco de ayuda. Soy un programador novato y uno de los problemas que estoy teniendo en el minuto es tratar de convertir una imagen & blanca en una lista que luego puedo modular en una señal de audio. Esto es parte de un proyecto lager para crear un programa SSTV de python.Obtener la lista de valores de píxeles de PIL

He importado el módulo PIL y estoy tratando de llamar a la función incorporada: list(im.getdata()). Cuando lo llamo, Python se cuelga. ¿Hay alguna manera de descomponer la imagen (siempre 320x240) en 240 líneas para facilitar los cálculos? O estoy llamando a la función incorrecta.

Si alguien tiene alguna sugerencia, por favor, dispare. Si alguien tiene experiencia en la generación de tonos de audio modulados utilizando Python, aceptaría gustosamente cualquier 'perla de sabiduría' que esté dispuesto a impartir. Gracias de antemano

+1

¿cuál es su 'im'? – SilentGhost

+2

Incluir el mensaje que obtienes cuando se cuelga sería realmente útil – dbr

Respuesta

46

Python no debería bloquearse cuando llame a getdata(). La imagen puede estar dañada o hay algún problema con la instalación de su PIL. Pruébalo con otra imagen o publica la imagen que estás usando.

Esto debe romper la imagen de la forma que desee:

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())'. Cuando lo llamo, Python se cuelga. * – SilentGhost

+0

Cuando invoco list (im.getdata()), Python no se cuelga (presumiblemente), sino que todo mi sistema Linux deja de responder. El reinicio duro soluciona este problema. –

+0

se bloquea tanto en Windows como en Linux. Empecé a pensar en la estabilidad de PIL. –

24

Si tiene numpy instalado, usted puede probar:

data = numpy.asarray(im) 

(digo "tratar" aquí, porque no está claro por qué getdata() no funciona para usted, y no sé si asarray usa getdata, pero vale la pena una prueba.)

+1

+1: ¡buena forma de obtener rápidamente la matriz de valores de píxeles! – EOL

11

Supongo que recibirá una er ror como .. TypeError: 'PixelAccess' object is not iterable ...?

Consulte la documentación Image.load de cómo acceder píxeles ..

Básicamente, para obtener la lista de los píxeles de una imagen, utilizando 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) 

que anexa a cada píxel de la all_pixels - si el archivo es una imagen RGB (incluso si solo contiene una imagen en blanco y negro), será una tupla, por ejemplo:

(255, 255, 255) 

para convertir la imagen a blanco y negro, sólo un promedio de los tres valores - así, las tres últimas líneas de código se convertirían en ..

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 para obtener la luminancia (promedio ponderado):

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

O pura de 1 bit mirando en blanco y negro:

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

probablemente hay métodos dentro PIL a hacer este tipo de conversiones RGB -> BW más rápido, pero esto funciona, y no es partic ularmente lento.

Si solo desea realizar cálculos en cada fila, puede omitir la adición de todos los píxeles a una lista intermedia.Por ejemplo, para calcular el valor medio de cada fila:

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

O si lo desea contar blancas o negras píxeles

Ésta es también una solución:

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

Como os comentaba anteriormente , el problema parece ser la conversión del formato de lista interna de PIL a un tipo de lista de python estándar. Descubrí que Image.tostring() es mucho más rápido y, según sus necesidades, podría ser suficiente. En mi caso, necesitaba calcular el resumen CRC32 de los datos de imagen, y me pareció bien.

Si necesita realizar cálculos más complejos, la respuesta de tom10 con numpy podría ser lo que necesita.

1

No PIL, pero scipy.misc.imread todavía podría ser interesante:

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

da

(480, 640, 3) 

por lo que es (altura, anchura, canales). Por lo que puede iterar sobre ella por

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

Parece Almohada puede haber cambiado tostring()-tobytes(). Al tratar de extraer píxeles RGBA para obtener una textura OpenGL, lo siguiente funcionó para mí (dentro de la llamada glTexImage2D que omito por brevedad).

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) 

Aviso: En PIL, img es RGBA. En cv2, img es BGRA.

Mi solución robusta:

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