2010-12-31 12 views
24

Tengo 4 directorios con imágenes para una animación. Me gustaría tomar el conjunto de imágenes y generar una sola imagen con las 4 imágenes dispuestas en una cuadrícula de 2x2 para cada fotograma de la animación.Biblioteca de imágenes de Python: ¿cómo combinar 4 imágenes en una cuadrícula de 2 x 2?

Mi código hasta ahora es:

import Image 

fluid64 = "Fluid64_half_size/00" 
fluid128 = "Fluid128_half_size/00" 
fluid512 = "Fluid512_half_size/00" 
fluid1024 = "Fluid1024_half_size/00" 

out_image = "Fluid_all/00" 

for pic in range(1, 26): 
    blank_image = Image.open("blank.jpg") 

    if pic < 10: 
     image_num = "0"+str(pic) 
    else: 
     image_num = str(pic) 

    image64 = Image.open(fluid64+image_num+".jpg") 
    image128 = Image.open(fluid128+image_num+".jpg") 
    image512 = Image.open(fluid512+image_num+".jpg") 
    image1024 = Image.open(fluid1024+image_num+".jpg") 
    out = out_image + image_num + ".jpg" 

    blank_image.paste(image64, (0,0)).paste(fluid128, (400,0)).paste(fluid512, (0,300)).paste(fluid1024, (400,300)).save(out) 

No sé por qué no está funcionando. Obtengo el error:

Traceback (most recent call last): 
    File "C:\Users\Casey\Desktop\Image_composite.py", line 24, in <module> 
    blank_image.paste(image64, (0,0)).paste(fluid128, (400,0)).paste(fluid512, (
ste(fluid1024, (400,300)).save(out) 
AttributeError: 'NoneType' object has no attribute 'paste' 
shell returned 1 

Cualquier ayuda sería increíble. ¡Gracias!

Respuesta

37

El único problema es que "pegar" no devuelve un objeto de imagen, sino que más bien modifica la imagen "en blanco" en el lugar.

Por lo tanto, cuando se llama a la segunda pasta (la que usa la imagen fuild128), intenta aplicarse en "Ninguno", que es el valor de retorno de la primera imagen.

Si ese es el único problema que tiene, simplemente hacer una llamada pasta por línea, así:

blank_image.paste(image64, (0,0)) 
blank_image.paste(fluid128, (400,0)) 
blank_image.paste(fluid512, (0,300)) 
blank_image.paste(fluid1024, (400,300)) 
blank_image.save(out) 

Aunque parece probable que lo que se necesita para escalar cada imagen para que su partido formato bien. Y su código para la variable "image_num" no es necesario. Python es muy bueno con las cadenas - acaba de hacer algo como esto:

image64 = Image.open(fluid64 + "%02d.jpg" % pic) 
10

Es posible que desee estar usando algo en la línea de:

blank_image = Image.new("RGB", (800, 600)) 

Esto creará una nueva área de memoria en la que se puede generar tu imagen Deberías poder pegar tus imágenes en eso.

A continuación, tendrá que guardarlo de nuevo más tarde con:

blank_image.save("blank.jpg") 
+1

Esto no es lo que se " mal "en el código, aunque también se beneficiaría de ello. – jsbueno

+0

Sí, noté lo que estaba realmente "mal" después. Miré el rastro y parecía que la imagen en blanco no se había definido correctamente. Así que solo hice suposiciones. Es bastante tarde aquí después de todo :) –

+0

Mi caso de uso fue crear una nueva imagen con un tamaño dinámico, concatenando segmentos juntos en la nueva imagen en blanco, por lo que fue muy útil. +1 –

4

Leer el mensaje de error:

AttributeError: 'NoneType' object has no attribute 'paste' 

Esto significa que ha intentado llamar .paste en algo que era de tipo NoneType, es decir, en el objeto None.

Image.paste regresa Ninguno. No puede "encadenar" llamadas así excepto cuando las funciones están diseñadas específicamente para admitirlo, y Image.paste no. (El soporte para este tipo de cosas se logra teniendo la función return self. Se obtiene un error que habla de NoneType porque la función está escrita para no devolver nada, y todo en Python devuelve None de manera predeterminada si no se devuelve nada explícitamente). se considera Pythonic: los métodos devuelven un nuevo valor o modifican self y devuelven None. Por lo tanto, las llamadas "interfaces fluidas" no se usan cuando las funciones tienen efectos secundarios: los pitonistas consideran que son dañinas. La devolución None es una advertencia de que la función tiene efectos secundarios. :)

Simplemente haga cuatro llamadas .paste por separado.

1

diferencia de APIs PIL copy, crop, resize o rotate que devolver un objeto Image, paste rendimientos None que impide que las llamadas a métodos encadenados. No es tan conveniente API diseño.

0

figuras baldosas en una cuadrícula de 2 por 2 serían fáciles de conseguir con los append_images función definida en esta respuesta https://stackoverflow.com/a/46623632/8738113

Por ejemplo:

img1 = append_images([image64, image128], direction='horizontal') 
img2 = append_images([image512, image1024], direction='horizontal') 
final = append_images([img1, img2], direction='vertical') 
final.save("Fluid_all/00.jpg") 
Cuestiones relacionadas