Python Image Library:如何将4个图像组合成2 x 2网格?

时间:2021-06-18 00:24:44

I have 4 directories with images for an animation. I would like to take the set of images and generate a single image with the 4 images arranged into a 2x2 grid for each frame of the animation.

我有4个目录,包含动画图像。我想拍摄一组图像并生成一个图像,其中4个图像排列成动画的每个帧的2x2网格。

My code so far is:

到目前为止我的代码是:

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)

Not sure why it's not working. I'm getting the 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

Any help would be awesome. Thanks!

任何帮助都是极好的。谢谢!

5 个解决方案

#1


38  

The only problem there is that "paste" does not return an image object - it rather modifies the "blank" image inplace.

唯一的问题是“粘贴”不会返回图像对象 - 而是在原位修改“空白”图像。

So, when the second paste is called (the one that uses the fuild128 image), it tries to be applied on "None" - which is the return value of the first image.

因此,当调用第二个粘贴(使用fuild128图像的粘贴)时,它会尝试应用于“无” - 这是第一个图像的返回值。

If that is the only problem you are having, just make one paste call per line, like this:

如果这是您遇到的唯一问题,请每行进行一次粘贴调用,如下所示:

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)

Although it looks likely you'd need to scale each image so that their format match as well. And your code for the "image_num" variable is unecessary. Python is really good with strings - just do something like this:

虽然看起来很可能需要缩放每个图像,以便它们的格式也匹配。你的“image_num”变量的代码是不必要的。 Python对字符串非常好 - 只需执行以下操作:

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

#2


10  

You may want to be using something along the lines of :

您可能希望使用以下内容:

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

This will create a new area in memory in which you can generate your image. You should then be able to paste you images into that.

这将在内存中创建一个新区域,您可以在其中生成图像。然后,您应该能够将图像粘贴到其中。

Then you'll need to save it out again later on with:

然后你需要在以后再次保存它:

blank_image.save("blank.jpg")

#3


4  

Read the error message:

阅读错误消息:

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

This means you tried to call .paste on something that was of type NoneType, i.e. on the None object.

这意味着你试图在类型为NoneType的东西上调用.paste,即在None对象上。

Image.paste returns None. You can't "chain" together calls like that except when the functions are specifically designed to support it, and Image.paste is not. (Support for this sort of thing is accomplished by having the function return self. You get an error that talks about NoneType because the function is written not to return anything, and everything in Python returns None by default if nothing else is returned explicitly.) This is considered Pythonic: methods either return a new value, or modify self and return None. Thus, so-called "fluent interfaces" are not used when the functions have side effects - Pythonistas consider that harmful. Returning None is a warning that the function has side effects. :)

Image.paste返回None。你不能将这样的调用“链接”在一起,除非这些函数是专门设计用来支持它的,而Image.paste则不是。 (通过让函数返回self来完成对这种事情的支持。你得到一个关于NoneType的错误,因为编写的函数不会返回任何内容,并且如果没有显式返回任何其他内容,Python中的所有内容都会返回None。)这被认为是Pythonic:方法要么返回一个新值,要么修改self并返回None。因此,当函数具有副作用时,不使用所谓的“流畅接口” - Pythonistas认为这有害。返回None是警告该功能有副作用。 :)

Just do four separate .paste calls.

只需要进行四次单独的.paste调用。

#4


1  

Unlike PIL APIs copy, crop, resize or rotate which return an Image object, paste returns None which prevents chained method calls. Not so convenient API design.

与返回Image对象的PIL API复制,裁剪,调整大小或旋转不同,粘贴返回None以防止链式方法调用。 API设计不太方便。

#5


0  

Tiling figures in a 2-by-2 grid would be easy to achieve with the append_images function defined in this reply https://*.com/a/46623632/8738113

使用此回复中定义的append_images函数可轻松实现2×2网格中的平铺数字https://*.com/a/46623632/8738113

For example:

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


38  

The only problem there is that "paste" does not return an image object - it rather modifies the "blank" image inplace.

唯一的问题是“粘贴”不会返回图像对象 - 而是在原位修改“空白”图像。

So, when the second paste is called (the one that uses the fuild128 image), it tries to be applied on "None" - which is the return value of the first image.

因此,当调用第二个粘贴(使用fuild128图像的粘贴)时,它会尝试应用于“无” - 这是第一个图像的返回值。

If that is the only problem you are having, just make one paste call per line, like this:

如果这是您遇到的唯一问题,请每行进行一次粘贴调用,如下所示:

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)

Although it looks likely you'd need to scale each image so that their format match as well. And your code for the "image_num" variable is unecessary. Python is really good with strings - just do something like this:

虽然看起来很可能需要缩放每个图像,以便它们的格式也匹配。你的“image_num”变量的代码是不必要的。 Python对字符串非常好 - 只需执行以下操作:

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

#2


10  

You may want to be using something along the lines of :

您可能希望使用以下内容:

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

This will create a new area in memory in which you can generate your image. You should then be able to paste you images into that.

这将在内存中创建一个新区域,您可以在其中生成图像。然后,您应该能够将图像粘贴到其中。

Then you'll need to save it out again later on with:

然后你需要在以后再次保存它:

blank_image.save("blank.jpg")

#3


4  

Read the error message:

阅读错误消息:

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

This means you tried to call .paste on something that was of type NoneType, i.e. on the None object.

这意味着你试图在类型为NoneType的东西上调用.paste,即在None对象上。

Image.paste returns None. You can't "chain" together calls like that except when the functions are specifically designed to support it, and Image.paste is not. (Support for this sort of thing is accomplished by having the function return self. You get an error that talks about NoneType because the function is written not to return anything, and everything in Python returns None by default if nothing else is returned explicitly.) This is considered Pythonic: methods either return a new value, or modify self and return None. Thus, so-called "fluent interfaces" are not used when the functions have side effects - Pythonistas consider that harmful. Returning None is a warning that the function has side effects. :)

Image.paste返回None。你不能将这样的调用“链接”在一起,除非这些函数是专门设计用来支持它的,而Image.paste则不是。 (通过让函数返回self来完成对这种事情的支持。你得到一个关于NoneType的错误,因为编写的函数不会返回任何内容,并且如果没有显式返回任何其他内容,Python中的所有内容都会返回None。)这被认为是Pythonic:方法要么返回一个新值,要么修改self并返回None。因此,当函数具有副作用时,不使用所谓的“流畅接口” - Pythonistas认为这有害。返回None是警告该功能有副作用。 :)

Just do four separate .paste calls.

只需要进行四次单独的.paste调用。

#4


1  

Unlike PIL APIs copy, crop, resize or rotate which return an Image object, paste returns None which prevents chained method calls. Not so convenient API design.

与返回Image对象的PIL API复制,裁剪,调整大小或旋转不同,粘贴返回None以防止链式方法调用。 API设计不太方便。

#5


0  

Tiling figures in a 2-by-2 grid would be easy to achieve with the append_images function defined in this reply https://*.com/a/46623632/8738113

使用此回复中定义的append_images函数可轻松实现2×2网格中的平铺数字https://*.com/a/46623632/8738113

For example:

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