Python PIL/Image 从序列图像中制作3x3网格

13

我正在尝试通过按顺序放置图片来制作一个3x3的网格,但似乎做不对。这些图片存储在文件夹中,从0到8进行命名(共9张图片),最终输出应为3x3的网格图像。

image0 image1 image2
image3 image4 image5
image6 image7 image8 

我尝试按照如何使用PIL/Pillow将图像合并到画布中?的方法进行操作,但无法正确工作。

不需要更改图像中的任何内容,只需将它们合并并制成3x3的网格。

2个回答

24

要将 rows*cols 张图片制作成任意形状的网格 (cols*img_height, rows*img_width):

def image_grid(imgs, rows, cols):
    assert len(imgs) == rows*cols

    w, h = imgs[0].size
    grid = Image.new('RGB', size=(cols*w, rows*h))
    grid_w, grid_h = grid.size
    
    for i, img in enumerate(imgs):
        grid.paste(img, box=(i%cols*w, i//cols*h))
    return grid

假设你的imgs是一个列表,其中包含PIL图像:

grid = image_grid(imgs, rows=3, cols=3)

抱歉,实际上这与我如何输入图像有关:我写了 image, *images = [PIL.Image.open(file) for file in sorted(glob.glob(images_in))],但后来只将 images 传递给了 image_grid()。通过 images.insert(0, image) 解决了这个问题。请随意纠正我 - 我知道这不是理想的解决方法(但它有效!)。 - Dbercules
1
我猜你解包了 list 以便只使用 image?作为 images.insert(0, image) 的替代方案,你可以将 [image, *images] 传递给 image_grid :) - Ivan
太棒了,让我感觉更专业了 - 尽管我不确定为什么。您能给我解释一下吗? - Dbercules
1
image, *images = my_list 将把 list 拆分成两个变量:image 保存第一个元素(即 my_list[0]),而 images 则保存剩余的元素(即 my_list[1:])。单个星号用于可迭代对象拆包。请记住,images 将是一个 list(如果 my_list 只有一个元素,则可以为空)。此外,您还可以将一个 list 拆分成另一个 list[*images],它基本上就是 images。很酷的一点是,您可以使用其他元素定义您的 list(就像您通常创建列表一样)。 - Ivan
2
在这里我使用了字面量而不是变量,添加了 image[image, *images]。因此,列表 包含 image 作为第一个元素和 images 的内容(解包)作为列表的后续元素。了解这种行为的最佳方法是自己尝试一下:定义 x = [1,2,3],解包为 a, *rest = x,那么 rest 将是什么?你能猜到 [*rest, a] 会是什么吗?现在,对于更具挑战性的问题:a, *(what, _) = x,那么 what 将是什么?在 [1,2,3,4] 中,a, *(b,*c) = [1,2,3,4] 中的 c 是什么?祝你好运 ;) - Ivan

8
以下是如何实现此功能的示例(假设图像是您的其中一张图片):
    img_w, img_h = image.size
    background = Image.new('RGBA',(1300, 1300), (255, 255, 255, 255))
    bg_w, bg_h = background.size
    offset = (10,(((bg_h - img_h)) / 2)-370)
    background.paste(image1,offset)

调整偏移量、宽度和高度以适应您的要求。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接