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.
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. Thank you!
CodePudding user response:
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. 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')
CodePudding user response:
Don't use images_a
, images_b
but only images
and for
-loop.
This will create 1xN
(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)
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
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')