简体   繁体   English

如何更改此 function 以使用 PIL 和 numpy 根据文件夹中的图像数量创建网格?

[英]How do I alter this function to create a grid based on the number of images in the folder using PIL and numpy?

The idea is to pass a list of all images found using glob into the collage_maker function and then it will save the image as a 3x3, 4x4, 5x5 etc. If there aren't enough images it goes to the next highest one and just has empty black squares.这个想法是将使用 glob 找到的所有图像的列表传递到 collage_maker function 中,然后它将图像保存为 3x3、4x4、5x5 等。如果没有足够的图像,它会转到下一个最高的图像并且只有空的黑色方块。

from PIL import Image
import numpy as np
import os
import glob

direct_loc = "/home/nikolas/Downloads/"



images = glob.glob(direct_loc + '*.jpg')
        
images_a = images[::2]
images_b = images[1::2]



def collage_maker(image1, image2, name):
    i1 = np.array(image1)
    i2 = np.array(image2)
    collage = np.vstack([i1, i2])
    image = Image.fromarray(collage)
    image.save(name)



collage_maker(Image.open(images_a[0]), Image.open(images_b[0]), 'collage.jpg')

As of right now it has no problem making a 1x2 image, but everything else I have tried just makes it longer, but never into a grid.截至目前,制作 1x2 图像没有问题,但我尝试过的所有其他方法只是让它更长,但从来没有进入网格。 Thank you!谢谢!

First of all, if you want to work with a list of image of arbitrary length, you would better have your function accepting some kind of iterable of images rather than two images, or else you would have to call it multiple times in a very convoluted way to obtain the desired result.首先,如果你想使用任意长度的图像列表,你最好让你的 function 接受某种可迭代的图像而不是两个图像,否则你将不得不在一个非常复杂的情况下多次调用它获得所需结果的方法。 You should then determine the shape of your collage square based on the number of images in said iterable.然后,您应该根据所述可迭代的图像数量确定拼贴正方形的形状。 Also, you will have to check the shapes of the images during processing, and probably find the maximum value in each dimension, unless all images have exactly the same size.此外,您必须在处理过程中检查图像的形状,并可能找到每个维度的最大值,除非所有图像的大小完全相同。 Something like this should work:像这样的东西应该工作:

import numpy as np
from PIL import Image
from typing import Iterable


def collage_maker(img_iter: Iterable[Image.Image], name: str):
    # get the np arrays from the images
    img_arrays = [np.array(img) for img in img_iter]

    # find the size of the side of you collage square
    square_side = np.ceil(np.sqrt(len(img_arrays))).astype(int)

    # now determine the max height, width and number of channels
    shapes = np.array([img.shape for img in img_arrays]).T
    dims = [np.max(d) for d in shapes]

    # create an array to gather the images, with all values 0 (black / transparent)
    # you can see this as a collection of "empty" images
    holder = np.zeros((square_side ** 2, *dims), np.uint8)

    # now, for each image ...
    for i in range(len(img_arrays)):
        # ... get its shape ...
        img_shape = img_arrays[i].shape
        # ... and copy image to an "empty" location in the holder array.
        # you need to specify a target slice as target may be larger than the source
        holder[i, :img_shape[0], :img_shape[1], :img_shape[2]] = img_arrays[i]

    # turn the collage array in a "square" of desired size...
    square = holder.reshape((square_side, square_side, dims[0], dims[1], dims[2]))

    # ... and concatenate along height and width
    collage = Image.fromarray(np.concatenate(np.concatenate(square, axis=1), axis=1))

    collage.save(name)

Usage:用法:

import glob


direct_loc = "/your/image/directory/"
images = glob.glob(direct_loc + '*.jpg')
collage_maker([Image.open(path) for path in images], 'collage.jpg')

Don't use images_a , images_b but only images and for -loop.不要使用images_aimages_b ,而只能使用imagesfor -loop。

This will create 1xN (but I did't test it)这将创建1xN (但我没有测试它)

import os
import glob
import numpy as np
from PIL import Image

direct_loc = "/home/nikolas/Downloads/"

filenames = glob.glob(direct_loc + '*.jpg')
        
images = []

for name in filenames:
    img = Image.open(name)
    images.append(img)
    
def collage_maker(images, name):
    arrays = []
    
    for img in images:
        arr = np.array(img)
        arrays.append(arr)

    collage = np.vstack(arrays)
    
    image = Image.fromarray(collage)
    image.save(name)

collage_maker(images, 'collage.jpg')

To create NxM you may get images as (flat) numpy.array and reshape it to NxM and later use nested for -loops要创建NxM ,您可以将images作为(平面) numpy.array并将其reshapeNxM ,然后使用嵌套for -loops

Something like this (but I did't test it)像这样的东西(但我没有测试它)

import os
import glob
import numpy as np
from PIL import Image

direct_loc = "/home/nikolas/Downloads/"

filenames = glob.glob(direct_loc + '*.jpg')
        
images = []

for name in filenames:
    img = Image.open(name)
    images.append(img)

# get 9 images and reshape to `3x3`
images = np.array(images[:9])
images = images.reshape(3, 3)

def collage_maker(images, name):
    all_rows = []
    
    for row in images:
        arrays = []

        for img in row:
            arr = np.array(img)
            arrays.append(arr)

        row_arr = np.vstack(arrays)
        all_rows.append(row_arr)
        
    collage = np.hstack(all_rows)
    
    image = Image.fromarray(collage)
    image.save(name)

collage_maker(images, 'collage.jpg')

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM