Библиотека изображений 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
Любая помощь будет потрясающей. Спасибо!
Ответы
Ответ 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")