Skip to content
Advertisement

How do I randomly select multiple images from folders and then layer them as a single image in Python?

I’m trying to use python to create a composite .png of randomly selected and layered png’s all with transparent backgrounds, so all layers are visible in the finished piece.

For example using different coloured circles of decreasing size: a folder of the largest circles called ‘layer1’ contains 3 different coloured circles of the same size and position on transparent backgrounds, ‘layer2’ folder contains 3 smaller different coloured circles of the same size and position and so on. I want to first place a random selection from ‘layer1’ then a random selection from ‘layer2’ on top etc. and save to an output file.

I have had the code working without random selection of the image, but using specific image files. When I try to make the file selection random using os I receive the message:

'PIL.UnidentifiedImageError: cannot identify image file '.DS_Store''

There seems to be a clash between the random selection code and the image paste code. I’ve tried to prefix random.choice with Image.open as per my working code, but it’s evidently not that straightforward.

It is important that I can keep the selected images as having transparent backgrounds as there are to be more than two stacked and they are being placed on a coloured background.

Here’s my original (working) code:

from PIL import Image
import random, os
import numpy as np

layer1 = Image.open('bigcircle/Circle 1.png', 'r')
layer2 = Image.open('mediumcircle/Circle 2.png', 'r')

img = Image.new('RGB', (4961, 4961), color = (0, 220, 15))
img.paste(layer1, (0, 0), layer1)
img.paste(layer2, (0, 0), layer2)

img.save("output.png")

In my attempt at making the selections random, which is throwing up the error, I have changed ‘layer1 = Image.open(‘layer1/Circle 1.png’, ‘r’)’ to the following (and would do the same for layer2 if I hadn’t encountered the error).

path = r"bigcircle"
layer1 = random.choice([
    x for x in os.listdir(path)
    if os.path.isfile(os.path.join(path, x))
])

Advertisement

Answer

Something like this maybe? This discovers all paths to PNG images in your two directories, and then picks one at random from each directory/layer. Then it iterates over the selected paths, and pastes them into a single image. I haven’t tested this, but it should work:

from pathlib import Path
from random import choice

layers = [list(Path(directory).glob("*.png")) for directory in ("bigcircle/", "mediumcircle/")]

selected_paths = [choice(paths) for paths in layers]

img = Image.new("RGB", (4961, 4961), color=(0, 220, 15))
for path in selected_paths:
    layer = Image.open(str(path), "r")
    img.paste(layer, (0, 0), layer)


img.save("output.png")
User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement