Подтвердить что ты не робот

Библиотека изображений Python: как объединить 4 изображения в сетку 2 x 2?

У меня есть 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

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

4b9b3361

Ответ 1

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

Итак, когда вызывается вторая паста (та, которая использует изображение fuild128), она пытается применяться к "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)

Ответ 2

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

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

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

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

blank_image.save("blank.jpg")

Ответ 3

Считать сообщение об ошибке:

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.

Ответ 4

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

Ответ 5

Чрезмерные фигуры в сетке размером 2 на 2 легко достичь с помощью функции append_images, определенной в этом ответе fooobar.com/info/130898/...

Например:

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")