mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
Compare commits
54 Commits
release/ad
...
JPPhoto-sy
Author | SHA1 | Date | |
---|---|---|---|
55dfcfc792 | |||
93cebc336b | |||
5d70923d51 | |||
b5d02452bc | |||
8564159677 | |||
3bff9abae0 | |||
72351a7aea | |||
1ff569b56d | |||
8b1a24a92c | |||
ddaa28b226 | |||
3d1164f94f | |||
7b78496509 | |||
0e925be1c4 | |||
da2577620d | |||
ac6fbee866 | |||
fe5f6ac3cf | |||
a78aff4016 | |||
c4f5ff2b15 | |||
3584605d5f | |||
46cc20ad94 | |||
ca9a29b960 | |||
93a0f36472 | |||
f21062f144 | |||
44b863e5de | |||
938700d2f3 | |||
a12558f947 | |||
37189721fc | |||
9eba24f7ab | |||
9f8f85e922 | |||
ba5ef93b5d | |||
733361735b | |||
09751a7c97 | |||
40a84c29d0 | |||
2471643226 | |||
1103e49d3e | |||
1417d33188 | |||
c4c531fa65 | |||
a91dddcbe1 | |||
c619a8a026 | |||
2690c9f28b | |||
2c9ec0baae | |||
9ec6fbfee0 | |||
4765e707bf | |||
c9eec1e576 | |||
65e33962ec | |||
e880754745 | |||
d186c8fde5 | |||
e9f1b5e3b1 | |||
33411ec79e | |||
43a8352958 | |||
c0f259173d | |||
a48610598a | |||
9d97b106b0 | |||
bb6772498a |
@ -1,3 +1,4 @@
|
||||
from enum import Enum
|
||||
from contextlib import contextmanager
|
||||
from dataclasses import dataclass
|
||||
from math import ceil
|
||||
@ -6,6 +7,7 @@ from typing import Any, Callable, Dict, Optional, Union
|
||||
import numpy as np
|
||||
import torch
|
||||
from diffusers.models.cross_attention import AttnProcessor
|
||||
from einops import einops
|
||||
from typing_extensions import TypeAlias
|
||||
|
||||
from invokeai.backend.globals import Globals
|
||||
@ -31,12 +33,17 @@ ModelForwardCallback: TypeAlias = Union[
|
||||
]
|
||||
|
||||
|
||||
|
||||
SymmetryType = Enum('SymmetryType', ['MIRROR', 'FADE'])
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class PostprocessingSettings:
|
||||
threshold: float
|
||||
warmup: float
|
||||
h_symmetry_time_pct: Optional[float]
|
||||
v_symmetry_time_pct: Optional[float]
|
||||
symmetry_type: Optional[SymmetryType] = None
|
||||
|
||||
|
||||
class InvokeAIDiffuserComponent:
|
||||
@ -529,25 +536,44 @@ class InvokeAIDiffuserComponent:
|
||||
):
|
||||
v_symmetry_time_pct = None
|
||||
|
||||
width = latents.shape[3]
|
||||
height = latents.shape[2]
|
||||
dev = latents.device.type
|
||||
dtype = latents.dtype
|
||||
symmetry_type = postprocessing_settings.symmetry_type or SymmetryType.FADE
|
||||
|
||||
latents.to(device="cpu")
|
||||
|
||||
def make_ramp(ease_in: int, total: int) -> torch.Tensor:
|
||||
ramp1 = torch.linspace(start=1.0, end=0.5, steps=ease_in, device=dev)
|
||||
ramp2 = torch.linspace(start=0.5, end=1.0, steps=total - ease_in, device=dev)
|
||||
ramp = torch.cat((ramp1, ramp2))
|
||||
return ramp
|
||||
|
||||
if (
|
||||
h_symmetry_time_pct != None
|
||||
and self.last_percent_through < h_symmetry_time_pct
|
||||
and percent_through >= h_symmetry_time_pct
|
||||
):
|
||||
# Horizontal symmetry occurs on the 3rd dimension of the latent
|
||||
width = latents.shape[3]
|
||||
x_flipped = torch.flip(latents, dims=[3])
|
||||
latents = torch.cat(
|
||||
[
|
||||
latents[:, :, :, 0 : int(width / 2)],
|
||||
x_flipped[:, :, :, int(width / 2) : int(width)],
|
||||
],
|
||||
dim=3,
|
||||
)
|
||||
if symmetry_type is SymmetryType.MIRROR:
|
||||
latents = torch.cat(
|
||||
[
|
||||
latents[:, :, :, 0 : int(width / 2)],
|
||||
x_flipped[:, :, :, int(width / 2) : int(width)],
|
||||
],
|
||||
dim=3,
|
||||
)
|
||||
elif symmetry_type is SymmetryType.FADE:
|
||||
apply_width = width // 2
|
||||
# Create a linear ramp so the middle gets perfect symmetry but the edges retain their original latents
|
||||
ramp = make_ramp(ease_in=apply_width, total=width)
|
||||
fade1 = einops.repeat(tensor=ramp, pattern='m -> 1 4 k m', k=height).to(latents.device).type(dtype)
|
||||
fade0 = 1 - fade1
|
||||
# Multiply the crossover region to retain details and avoid a "muddy" appearance
|
||||
multiplier = (fade1 * fade0) * 1.25 + 1
|
||||
latents = ((latents * fade1) + (x_flipped * fade0)) * multiplier
|
||||
|
||||
if (
|
||||
v_symmetry_time_pct != None
|
||||
@ -555,15 +581,24 @@ class InvokeAIDiffuserComponent:
|
||||
and percent_through >= v_symmetry_time_pct
|
||||
):
|
||||
# Vertical symmetry occurs on the 2nd dimension of the latent
|
||||
height = latents.shape[2]
|
||||
y_flipped = torch.flip(latents, dims=[2])
|
||||
latents = torch.cat(
|
||||
[
|
||||
latents[:, :, 0 : int(height / 2)],
|
||||
y_flipped[:, :, int(height / 2) : int(height)],
|
||||
],
|
||||
dim=2,
|
||||
)
|
||||
if symmetry_type is SymmetryType.MIRROR:
|
||||
latents = torch.cat(
|
||||
[
|
||||
latents[:, :, 0 : int(height / 2)],
|
||||
y_flipped[:, :, int(height / 2) : int(height)],
|
||||
],
|
||||
dim=2,
|
||||
)
|
||||
elif symmetry_type is SymmetryType.FADE:
|
||||
apply_height = height // 2
|
||||
# Create a linear ramp so the middle gets perfect symmetry but the edges retain their original latents
|
||||
ramp = make_ramp(ease_in=apply_height, total=height)
|
||||
fade1 = einops.repeat(tensor=ramp, pattern='m -> 1 4 m k', k=width).to(latents.device).type(dtype)
|
||||
fade0 = 1 - fade1
|
||||
# Multiply the crossover region to retain details and avoid a "muddy" appearance
|
||||
multiplier = (fade1 * fade0) * 1.25 + 1
|
||||
latents = ((latents * fade1) + (y_flipped * fade0)) * multiplier
|
||||
|
||||
self.last_percent_through = percent_through
|
||||
return latents.to(device=dev)
|
||||
|
Reference in New Issue
Block a user