Библиотека изображений Python: Как объединить 4 изображения в сетку 2 x 2? - PullRequest
27 голосов
/ 31 декабря 2010

У меня есть 4 каталога с изображениями для анимации. Я хотел бы взять набор изображений и сгенерировать одно изображение с 4 изображениями, расположенными в сетке 2x2 для каждого кадра анимации.

Пока мой код:

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)

Не уверен, почему это не работает. Я получаю сообщение об ошибке:

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

Любая помощь будет потрясающей. Спасибо!

Ответы [ 5 ]

39 голосов
/ 31 декабря 2010

Единственная проблема в том, что "paste" не возвращает объект изображения - он скорее изменяет "пустое" изображение на месте.

Итак, когда вызывается вторая вставка (та, которая использует fuild128image), он пытается быть применен к «None» - что является возвращаемым значением первого изображения.

Если это единственная проблема, с которой вы столкнулись, просто сделайте один вызов вставки на строку, например так:

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)

Хотя, похоже, вам нужно масштабировать каждое изображение так, чтобы его формат также совпадал.И ваш код для переменной "image_num" не нужен.Python действительно хорош со строками - просто сделайте что-то вроде этого:

image64 = Image.open(fluid64 + "%02d.jpg" % pic)
10 голосов
/ 31 декабря 2010

Возможно, вы захотите использовать что-то вроде:

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

Это создаст новую область в памяти, в которой вы можете создать свое изображение. После этого вы сможете вставить в него свои изображения.

Тогда вам нужно будет снова сохранить его позже:

blank_image.save("blank.jpg")
4 голосов
/ 31 декабря 2010

Прочитайте сообщение об ошибке:

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

Это означает, что вы пытались вызвать .paste для чего-то типа NoneType, то есть для объекта None.

Image.paste возвращает None. Вы не можете «связать» вместе такие вызовы, кроме случаев, когда функции специально предназначены для его поддержки, а Image.paste - нет. (Поддержка такого рода вещей достигается с помощью функции return self. Вы получаете ошибку, которая говорит о NoneType, потому что функция написана так, чтобы ничего не возвращать, и все в Python возвращает None по умолчанию, если ничего больше возвращается явно.) Это считается Pythonic: методы либо возвращают новое значение, либо изменяют self и возвращают None. Таким образом, так называемые «плавные интерфейсы» не используются, когда функции имеют побочные эффекты - Pythonistas считают это вредным. Возвращение None является предупреждением о том, что функция имеет побочные эффекты. :)

Просто сделайте четыре отдельных .paste звонка.

1 голос
/ 09 октября 2017

Значения листов в сетке 2 на 2 легко получить с помощью функции append_images , определенной в этом ответе https://stackoverflow.com/a/46623632/8738113

Например:

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")
1 голос
/ 19 апреля 2013

В отличие от API-интерфейсов PIL copy, crop, resize или rotate, которые возвращают объект Image, paste возвращает None, который предотвращает вызовы цепных методов. Не очень удобно API design.

...