|
11 | 11 | A job file: |
12 | 12 | {"prompt": "...", "keyframe": "key.jpg", text-to-image (optional) |
13 | 13 | "frames": [["in1.jpg", "out1.jpg"], ...], image-to-image, each in -> out |
14 | | - "strength": 0.5, "size": 512, "seed": 1234} |
| 14 | + "strength": 0.5, "size": 512, "seed": 1234, |
| 15 | + "blend": 0.6} optional: mix each frame with the keyframe |
| 16 | + first, ramping up to this much by the last |
| 17 | + frame, so the frames turn into the keyframe |
15 | 18 |
|
16 | 19 | Each image is written as soon as it's done, so a job that gets killed part |
17 | 20 | way still leaves what it finished. --model picks another turbo model, e.g. |
@@ -54,9 +57,12 @@ def text_to_image(t2i, prompt, size, seed, steps=1): |
54 | 57 | width=size, height=size, generator=generator_for(seed)).images[0] |
55 | 58 |
|
56 | 59 |
|
57 | | -def image_to_image(i2i, prompt, init_path, size, strength, seed, steps=2): |
| 60 | +def image_to_image(i2i, prompt, init_path, size, strength, seed, steps=2, mix=None, mix_amount=0.0): |
58 | 61 | from diffusers.utils import load_image |
| 62 | + from PIL import Image |
59 | 63 | init = load_image(init_path).convert("RGB").resize((size, size)) |
| 64 | + if mix is not None and mix_amount > 0: |
| 65 | + init = Image.blend(init, mix.convert("RGB").resize((size, size)), mix_amount) |
60 | 66 | # turbo models need steps * strength >= 1 |
61 | 67 | steps = max(steps, int(1 / max(strength, 0.05)) + 1) |
62 | 68 | return i2i(prompt, image=init, num_inference_steps=steps, strength=strength, |
@@ -104,10 +110,15 @@ def main(): |
104 | 110 | t2i, i2i = load_pipelines(args.model, args.device) |
105 | 111 | prompt, size, seed = job["prompt"], int(job.get("size", 512)), job.get("seed") |
106 | 112 | strength = float(job.get("strength", 0.5)) |
| 113 | + key = None |
107 | 114 | if job.get("keyframe"): |
108 | | - save(text_to_image(t2i, prompt, size, seed), job["keyframe"]) |
109 | | - for src, dst in job.get("frames", []): |
110 | | - save(image_to_image(i2i, prompt, src, size, strength, seed), dst) |
| 115 | + key = text_to_image(t2i, prompt, size, seed) |
| 116 | + save(key, job["keyframe"]) |
| 117 | + frames = job.get("frames", []) |
| 118 | + blend = float(job.get("blend", 0) or 0) |
| 119 | + for n, (src, dst) in enumerate(frames): |
| 120 | + amount = blend * (n + 1) / len(frames) if key is not None else 0 |
| 121 | + save(image_to_image(i2i, prompt, src, size, strength, seed, mix=key, mix_amount=amount), dst) |
111 | 122 | return 0 |
112 | 123 |
|
113 | 124 |
|
|
0 commit comments