Generating and saving multiple images using img2img pipeline

In the StableDiffusionImg2ImgPipeline, you can generate multiple images by adding the parameter num_images_per_prompt. But what is the best way to save all those images to a directory? All the examples I can find show doing: image[0].save(“filename”)

Do you have to do one at a time:
image[0].save(“filename”)
image[1].save(“filename”)
image[2].save(“filename”)

And so on?

hi @mmcquade you could use pathlib to create a dir and then iterate over the images.

like this

DIR_NAME="./images/"
dirpath = Path(DIR_NAME)
# create parent dir if doesn't exist
dirpath.mkdir(parents=True, exist_ok=True)
....
for idx, image in enumerate(output.images):
    image_name = f'{slugify(prompt)}-{idx}.png'
    image_path = dirpath / image_name
    image.save(image_path)

full example

from diffusers import StableDiffusionPipeline, EulerDiscreteScheduler
import torch
from pathlib import Path
import re

def slugify(text):
    # remove non-word characters and foreign characters
    text = re.sub(r"[^\w\s]", "", text)
    text = re.sub(r"\s+", "-", text)
    return text

model_id = "stabilityai/stable-diffusion-2"

device = "cuda" if torch.cuda.is_available() else "cpu"
# Use the Euler scheduler here instead
scheduler = EulerDiscreteScheduler.from_pretrained(
    model_id, subfolder="scheduler")
pipe = StableDiffusionPipeline.from_pretrained(
    model_id, scheduler=scheduler, torch_dtype=torch.float16)
pipe = pipe.to(device)

DIR_NAME="./images/"
dirpath = Path(DIR_NAME)
# create parent dir if doesn't exist
dirpath.mkdir(parents=True, exist_ok=True)

prompt = "a photo of an astronaut riding a horse on mars"
negative_prompt = "blurry, dark photo, blue"
steps = 15
scale = 9
num_images_per_prompt = 5
seed = torch.randint(0, 1000000, (1,)).item()
generator = torch.Generator(device=device).manual_seed(seed)
output = pipe(prompt, negative_prompt=negative_prompt, width=512, height=512, num_inference_steps=steps,
             guidance_scale=scale, num_images_per_prompt=num_images_per_prompt, generator=generator)

for idx, image in enumerate(output.images):
    image_name = f'{slugify(prompt)}-{idx}.png'
    image_path = dirpath / image_name
    image.save(image_path)
2 Likes

Works like a charm, thank you @radames

1 Like

Actually another question for this as I get the warning:
You have passed 3 text prompts (prompt), but only 1 initial images (image). Initial images are now duplicating to match the number of text prompts. Note that this behavior is deprecated and will be removed in a version 1.0.0. Please make sure to update your script to pass as many initial images as text prompts to suppress this warning. deprecate("len(prompt) != len(image)", "1.0.0", deprecation_message, standard_warn=False)

Any insights on best practices for passing more than 1 image as the init_image?

ok @mmcquade , I think you’re talking about the Image to Image pipeline with init image right? here is an example

As you see, the number of initial images, prompts, and negative prompts are matching to make it work.

Your warning message, is for when you are passing 3 different prompts but only one initial image, internally it makes [init_image]*len(prompt).

The example below break things apart for you.

from diffusers import StableDiffusionImg2ImgPipeline, EulerDiscreteScheduler
from pathlib import Path
from PIL import Image
import torch
import re
import requests


def slugify(text):
    # remove non-word characters and foreign characters
    text = re.sub(r"[^\w\s]", "", text)
    text = re.sub(r"\s+", "-", text)
    return text

model_id = "stabilityai/stable-diffusion-2"

images_url = ["https://s3.amazonaws.com/moonup/production/uploads/1675140495576-noauth.png",
              "https://s3.amazonaws.com/moonup/production/uploads/1675032939263-noauth.png",
              "https://s3.amazonaws.com/moonup/production/uploads/1673856328001-noauth.png"]
            
init_images = [Image.open(requests.get(url, stream=True).raw).convert("RGB").resize((758,768)) for url in images_url]

prompts = ["beautiful colorful flowr",
           "green city future mountain 3d sunrise skycrapers", 
           "rainbow beach, palm trees, neon, miami"]

negative_prompts = ["blurry, dark photo, blue",
                    "blurry, dark photo, blue",
                    "blurry, dark photo, blue"]

device = "cuda" if torch.cuda.is_available() else "cpu"
# Use the Euler scheduler here instead
scheduler = EulerDiscreteScheduler.from_pretrained(
    model_id, subfolder="scheduler")
pipe = StableDiffusionImg2ImgPipeline.from_pretrained(
    model_id, scheduler=scheduler, torch_dtype=torch.float16)
pipe = pipe.to(device)

DIR_NAME="./images/"
dirpath = Path(DIR_NAME)
# create parent dir if doesn't exist
dirpath.mkdir(parents=True, exist_ok=True)

steps = 20
scale = 9
num_images_per_prompt = 1
seed = torch.randint(0, 1000000, (1,)).item()
generator = torch.Generator(device=device).manual_seed(seed)
output = pipe(prompts, negative_prompt=negative_prompts, image=init_images, num_inference_steps=steps,
             guidance_scale=scale, num_images_per_prompt=num_images_per_prompt, generator=generator)

for idx, (image,prompt) in enumerate(zip(output.images, prompts*num_images_per_prompt)):
    image_name = f'{slugify(prompt)}-{idx}.png'
    image_path = dirpath / image_name
    image.save(image_path)