mirror of
https://github.com/invoke-ai/InvokeAI.git
synced 2026-04-01 03:01:13 -04:00
- similar call structures for outpainting, outcropping and face restoration modules
- added documentation for outcropping
- post-processing steps now leave a provenance chain (of sorts) in the sd-metadata field:
~~~
scripts/sd-metadata.py outputs/img-samples/curly.942491079.upscale.png
outputs/img-samples/curly.942491079.upscale.png:
{
"model": "stable diffusion",
"model_id": "stable-diffusion-1.4",
"model_hash": "fe4efff1e174c627256e44ec2991ba279b3816e364b49f9be2abc0b3ff3f8556",
"app_id": "lstein/stable-diffusion",
"app_version": "v1.15",
"image": {
"height": 512,
"width": 512,
"steps": 50,
"cfg_scale": 7.5,
"seed": 942491079,
"prompt": [
{
"prompt": "pretty curly-haired redhead woman",
"weight": 1.0
}
],
"postprocessing": [
{
"tool": "outcrop",
"dream_command": "!fix \"test-pictures/curly.png\" -s 50 -S 942491079 -W 512 -H 512 -C 7.5 -A k_lms -c top 64 right 64"
},
{
"tool": "gfpgan",
"dream_command": "!fix \"outputs/img-samples/curly.942491079.outcrop-02.png\" -s 50 -S 942491079 -W 512 -H 512 -C 7.5 -A k_lms -G 0.8"
},
{
"tool": "upscale",
"dream_command": "!fix \"outputs/img-samples/curly.942491079.gfpgan.png\" -s 50 -S 942491079 -W 512 -H 512 -C 7.5 -A k_lms -U 4.0 0.75"
}
],
"sampler": "k_lms",
"variations": [],
"type": "txt2img"
}
}
~~~
70 lines
2.4 KiB
Python
70 lines
2.4 KiB
Python
'''
|
|
ldm.dream.generator.img2img descends from ldm.dream.generator
|
|
'''
|
|
|
|
import torch
|
|
import numpy as np
|
|
from ldm.dream.devices import choose_autocast
|
|
from ldm.dream.generator.base import Generator
|
|
from ldm.models.diffusion.ddim import DDIMSampler
|
|
|
|
class Img2Img(Generator):
|
|
def __init__(self, model, precision):
|
|
super().__init__(model, precision)
|
|
self.init_latent = None # by get_noise()
|
|
|
|
def get_make_image(self,prompt,sampler,steps,cfg_scale,ddim_eta,
|
|
conditioning,init_image,strength,step_callback=None,threshold=0.0,perlin=0.0,**kwargs):
|
|
"""
|
|
Returns a function returning an image derived from the prompt and the initial image
|
|
Return value depends on the seed at the time you call it.
|
|
"""
|
|
self.perlin = perlin
|
|
|
|
sampler.make_schedule(
|
|
ddim_num_steps=steps, ddim_eta=ddim_eta, verbose=False
|
|
)
|
|
|
|
scope = choose_autocast(self.precision)
|
|
with scope(self.model.device.type):
|
|
self.init_latent = self.model.get_first_stage_encoding(
|
|
self.model.encode_first_stage(init_image)
|
|
) # move to latent space
|
|
|
|
t_enc = int(strength * steps)
|
|
uc, c = conditioning
|
|
|
|
def make_image(x_T):
|
|
# encode (scaled latent)
|
|
z_enc = sampler.stochastic_encode(
|
|
self.init_latent,
|
|
torch.tensor([t_enc]).to(self.model.device),
|
|
noise=x_T
|
|
)
|
|
# decode it
|
|
samples = sampler.decode(
|
|
z_enc,
|
|
c,
|
|
t_enc,
|
|
img_callback = step_callback,
|
|
unconditional_guidance_scale=cfg_scale,
|
|
unconditional_conditioning=uc,
|
|
)
|
|
|
|
return self.sample_to_image(samples)
|
|
|
|
return make_image
|
|
|
|
def get_noise(self,width,height):
|
|
device = self.model.device
|
|
init_latent = self.init_latent
|
|
assert init_latent is not None,'call to get_noise() when init_latent not set'
|
|
if device.type == 'mps':
|
|
x = torch.randn_like(init_latent, device='cpu').to(device)
|
|
else:
|
|
x = torch.randn_like(init_latent, device=device)
|
|
if self.perlin > 0.0:
|
|
shape = init_latent.shape
|
|
x = (1-self.perlin)*x + self.perlin*self.get_perlin_noise(shape[3], shape[2])
|
|
return x
|