Spaces:
Running
Running
Upload folder using huggingface_hub
Browse files- .gitattributes +1 -0
- Dockerfile +0 -1
- README.md +8 -5
- __init__.py +0 -0
- app_settings.py +89 -0
- backend/__init__.py +0 -0
- backend/device.py +23 -0
- backend/image_saver.py +40 -0
- backend/lcm_text_to_image.py +361 -0
- backend/models/lcmdiffusion_setting.py +39 -0
- backend/openvino/custom_ov_model_vae_decoder.py +21 -0
- backend/openvino/pipelines.py +75 -0
- backend/pipelines/lcm.py +90 -0
- backend/pipelines/lcm_lora.py +25 -0
- backend/tiny_decoder.py +30 -0
- configs/lcm-lora-models.txt +3 -0
- configs/lcm-models.txt +5 -0
- configs/openvino-lcm-models.txt +4 -0
- configs/stable-diffusion-models.txt +7 -0
- constants.py +17 -210
- context.py +47 -0
- frontend/gui/app_window.py +604 -0
- frontend/gui/image_generator_worker.py +37 -0
- frontend/gui/ui.py +15 -0
- frontend/utils.py +54 -0
- frontend/webui/css/style.css +22 -0
- frontend/webui/generation_settings_ui.py +140 -0
- frontend/webui/image_to_image_ui.py +123 -0
- frontend/webui/image_variations_ui.py +105 -0
- frontend/webui/models_ui.py +85 -0
- frontend/webui/realtime_ui.py +144 -0
- frontend/webui/text_to_image_ui.py +103 -0
- frontend/webui/ui.py +73 -0
- image_ops.py +15 -0
- main.py +223 -24
- models/interface_types.py +7 -0
- models/settings.py +8 -0
- paths.py +61 -0
- requirements.txt +16 -4
- state.py +32 -0
- utils.py +17 -11
.gitattributes
CHANGED
@@ -25,6 +25,7 @@
|
|
25 |
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
26 |
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
27 |
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
|
|
28 |
*.tflite filter=lfs diff=lfs merge=lfs -text
|
29 |
*.tgz filter=lfs diff=lfs merge=lfs -text
|
30 |
*.wasm filter=lfs diff=lfs merge=lfs -text
|
|
|
25 |
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
26 |
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
27 |
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
28 |
+
*.tar filter=lfs diff=lfs merge=lfs -text
|
29 |
*.tflite filter=lfs diff=lfs merge=lfs -text
|
30 |
*.tgz filter=lfs diff=lfs merge=lfs -text
|
31 |
*.wasm filter=lfs diff=lfs merge=lfs -text
|
Dockerfile
CHANGED
@@ -1,4 +1,3 @@
|
|
1 |
-
|
2 |
FROM python:3.9
|
3 |
|
4 |
WORKDIR /code
|
|
|
|
|
1 |
FROM python:3.9
|
2 |
|
3 |
WORKDIR /code
|
README.md
CHANGED
@@ -1,10 +1,13 @@
|
|
1 |
---
|
2 |
-
title:
|
3 |
-
emoji:
|
4 |
-
colorFrom:
|
5 |
-
colorTo:
|
6 |
-
sdk:
|
|
|
|
|
7 |
pinned: false
|
|
|
8 |
---
|
9 |
|
10 |
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
|
|
1 |
---
|
2 |
+
title: Fastlcm
|
3 |
+
emoji: 🏆
|
4 |
+
colorFrom: gray
|
5 |
+
colorTo: yellow
|
6 |
+
sdk: gradio
|
7 |
+
sdk_version: 4.8.0
|
8 |
+
app_file: app.py
|
9 |
pinned: false
|
10 |
+
license: apache-2.0
|
11 |
---
|
12 |
|
13 |
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
__init__.py
ADDED
File without changes
|
app_settings.py
ADDED
@@ -0,0 +1,89 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import yaml
|
2 |
+
from os import path, makedirs
|
3 |
+
from models.settings import Settings
|
4 |
+
from paths import FastStableDiffusionPaths
|
5 |
+
from utils import get_models_from_text_file
|
6 |
+
from constants import (
|
7 |
+
OPENVINO_LCM_MODELS_FILE,
|
8 |
+
LCM_LORA_MODELS_FILE,
|
9 |
+
SD_MODELS_FILE,
|
10 |
+
LCM_MODELS_FILE,
|
11 |
+
)
|
12 |
+
from copy import deepcopy
|
13 |
+
|
14 |
+
|
15 |
+
class AppSettings:
|
16 |
+
def __init__(self):
|
17 |
+
self.config_path = FastStableDiffusionPaths().get_app_settings_path()
|
18 |
+
self._stable_diffsuion_models = get_models_from_text_file(
|
19 |
+
FastStableDiffusionPaths().get_models_config_path(SD_MODELS_FILE)
|
20 |
+
)
|
21 |
+
self._lcm_lora_models = get_models_from_text_file(
|
22 |
+
FastStableDiffusionPaths().get_models_config_path(LCM_LORA_MODELS_FILE)
|
23 |
+
)
|
24 |
+
self._openvino_lcm_models = get_models_from_text_file(
|
25 |
+
FastStableDiffusionPaths().get_models_config_path(OPENVINO_LCM_MODELS_FILE)
|
26 |
+
)
|
27 |
+
self._lcm_models = get_models_from_text_file(
|
28 |
+
FastStableDiffusionPaths().get_models_config_path(LCM_MODELS_FILE)
|
29 |
+
)
|
30 |
+
|
31 |
+
@property
|
32 |
+
def settings(self):
|
33 |
+
return self._config
|
34 |
+
|
35 |
+
@property
|
36 |
+
def stable_diffsuion_models(self):
|
37 |
+
return self._stable_diffsuion_models
|
38 |
+
|
39 |
+
@property
|
40 |
+
def openvino_lcm_models(self):
|
41 |
+
return self._openvino_lcm_models
|
42 |
+
|
43 |
+
@property
|
44 |
+
def lcm_models(self):
|
45 |
+
return self._lcm_models
|
46 |
+
|
47 |
+
@property
|
48 |
+
def lcm_lora_models(self):
|
49 |
+
return self._lcm_lora_models
|
50 |
+
|
51 |
+
def load(self, skip_file=False):
|
52 |
+
if skip_file:
|
53 |
+
print("Skipping config file")
|
54 |
+
settings_dict = self._load_default()
|
55 |
+
self._config = Settings.parse_obj(settings_dict)
|
56 |
+
else:
|
57 |
+
if not path.exists(self.config_path):
|
58 |
+
base_dir = path.dirname(self.config_path)
|
59 |
+
if not path.exists(base_dir):
|
60 |
+
makedirs(base_dir)
|
61 |
+
try:
|
62 |
+
print("Settings not found creating default settings")
|
63 |
+
with open(self.config_path, "w") as file:
|
64 |
+
yaml.dump(
|
65 |
+
self._load_default(),
|
66 |
+
file,
|
67 |
+
)
|
68 |
+
except Exception as ex:
|
69 |
+
print(f"Error in creating settings : {ex}")
|
70 |
+
exit()
|
71 |
+
try:
|
72 |
+
with open(self.config_path) as file:
|
73 |
+
settings_dict = yaml.safe_load(file)
|
74 |
+
self._config = Settings.parse_obj(settings_dict)
|
75 |
+
except Exception as ex:
|
76 |
+
print(f"Error in loading settings : {ex}")
|
77 |
+
|
78 |
+
def save(self):
|
79 |
+
try:
|
80 |
+
with open(self.config_path, "w") as file:
|
81 |
+
tmp_cfg = deepcopy(self._config)
|
82 |
+
tmp_cfg.lcm_diffusion_setting.init_image = None
|
83 |
+
yaml.dump(tmp_cfg.dict(), file)
|
84 |
+
except Exception as ex:
|
85 |
+
print(f"Error in saving settings : {ex}")
|
86 |
+
|
87 |
+
def _load_default(self) -> dict:
|
88 |
+
defult_config = Settings()
|
89 |
+
return defult_config.dict()
|
backend/__init__.py
ADDED
File without changes
|
backend/device.py
ADDED
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import platform
|
2 |
+
from constants import DEVICE
|
3 |
+
import torch
|
4 |
+
import openvino as ov
|
5 |
+
|
6 |
+
core = ov.Core()
|
7 |
+
|
8 |
+
|
9 |
+
def is_openvino_device() -> bool:
|
10 |
+
if DEVICE.lower() == "cpu" or DEVICE.lower()[0] == "g":
|
11 |
+
return True
|
12 |
+
else:
|
13 |
+
return False
|
14 |
+
|
15 |
+
|
16 |
+
def get_device_name() -> str:
|
17 |
+
if DEVICE == "cuda" or DEVICE == "mps":
|
18 |
+
default_gpu_index = torch.cuda.current_device()
|
19 |
+
return torch.cuda.get_device_name(default_gpu_index)
|
20 |
+
elif platform.system().lower() == "darwin":
|
21 |
+
return platform.processor()
|
22 |
+
elif is_openvino_device():
|
23 |
+
return core.get_property(DEVICE.upper(), "FULL_DEVICE_NAME")
|
backend/image_saver.py
ADDED
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from os import path, mkdir
|
2 |
+
from typing import Any
|
3 |
+
from uuid import uuid4
|
4 |
+
from backend.models.lcmdiffusion_setting import LCMDiffusionSetting
|
5 |
+
import json
|
6 |
+
|
7 |
+
|
8 |
+
class ImageSaver:
|
9 |
+
@staticmethod
|
10 |
+
def save_images(
|
11 |
+
output_path: str,
|
12 |
+
images: Any,
|
13 |
+
folder_name: str = "",
|
14 |
+
format: str = ".png",
|
15 |
+
lcm_diffusion_setting: LCMDiffusionSetting = None,
|
16 |
+
) -> None:
|
17 |
+
gen_id = uuid4()
|
18 |
+
|
19 |
+
for index, image in enumerate(images):
|
20 |
+
if not path.exists(output_path):
|
21 |
+
mkdir(output_path)
|
22 |
+
|
23 |
+
if folder_name:
|
24 |
+
out_path = path.join(
|
25 |
+
output_path,
|
26 |
+
folder_name,
|
27 |
+
)
|
28 |
+
else:
|
29 |
+
out_path = output_path
|
30 |
+
|
31 |
+
if not path.exists(out_path):
|
32 |
+
mkdir(out_path)
|
33 |
+
image.save(path.join(out_path, f"{gen_id}-{index+1}{format}"))
|
34 |
+
if lcm_diffusion_setting:
|
35 |
+
with open(path.join(out_path, f"{gen_id}.json"), "w") as json_file:
|
36 |
+
json.dump(
|
37 |
+
lcm_diffusion_setting.model_dump(exclude="init_image"),
|
38 |
+
json_file,
|
39 |
+
indent=4,
|
40 |
+
)
|
backend/lcm_text_to_image.py
ADDED
@@ -0,0 +1,361 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from typing import Any
|
2 |
+
from diffusers import LCMScheduler
|
3 |
+
import torch
|
4 |
+
from backend.models.lcmdiffusion_setting import LCMDiffusionSetting
|
5 |
+
import numpy as np
|
6 |
+
from constants import DEVICE
|
7 |
+
from backend.models.lcmdiffusion_setting import LCMLora
|
8 |
+
from backend.device import is_openvino_device
|
9 |
+
from backend.openvino.pipelines import (
|
10 |
+
get_ov_text_to_image_pipeline,
|
11 |
+
ov_load_taesd,
|
12 |
+
get_ov_image_to_image_pipeline,
|
13 |
+
)
|
14 |
+
from backend.pipelines.lcm import (
|
15 |
+
get_lcm_model_pipeline,
|
16 |
+
load_taesd,
|
17 |
+
get_image_to_image_pipeline,
|
18 |
+
)
|
19 |
+
from backend.pipelines.lcm_lora import get_lcm_lora_pipeline
|
20 |
+
from backend.models.lcmdiffusion_setting import DiffusionTask
|
21 |
+
from image_ops import resize_pil_image
|
22 |
+
from math import ceil
|
23 |
+
|
24 |
+
|
25 |
+
class LCMTextToImage:
|
26 |
+
def __init__(
|
27 |
+
self,
|
28 |
+
device: str = "cpu",
|
29 |
+
) -> None:
|
30 |
+
self.pipeline = None
|
31 |
+
self.use_openvino = False
|
32 |
+
self.device = ""
|
33 |
+
self.previous_model_id = None
|
34 |
+
self.previous_use_tae_sd = False
|
35 |
+
self.previous_use_lcm_lora = False
|
36 |
+
self.previous_ov_model_id = ""
|
37 |
+
self.previous_safety_checker = False
|
38 |
+
self.previous_use_openvino = False
|
39 |
+
self.img_to_img_pipeline = None
|
40 |
+
self.is_openvino_init = False
|
41 |
+
self.task_type = DiffusionTask.text_to_image
|
42 |
+
self.torch_data_type = (
|
43 |
+
torch.float32 if is_openvino_device() or DEVICE == "mps" else torch.float16
|
44 |
+
)
|
45 |
+
print(f"Torch datatype : {self.torch_data_type}")
|
46 |
+
|
47 |
+
def _pipeline_to_device(self):
|
48 |
+
print(f"Pipeline device : {DEVICE}")
|
49 |
+
print(f"Pipeline dtype : {self.torch_data_type}")
|
50 |
+
self.pipeline.to(
|
51 |
+
torch_device=DEVICE,
|
52 |
+
torch_dtype=self.torch_data_type,
|
53 |
+
)
|
54 |
+
|
55 |
+
def _add_freeu(self):
|
56 |
+
pipeline_class = self.pipeline.__class__.__name__
|
57 |
+
if isinstance(self.pipeline.scheduler, LCMScheduler):
|
58 |
+
if pipeline_class == "StableDiffusionPipeline":
|
59 |
+
print("Add FreeU - SD")
|
60 |
+
self.pipeline.enable_freeu(
|
61 |
+
s1=0.9,
|
62 |
+
s2=0.2,
|
63 |
+
b1=1.2,
|
64 |
+
b2=1.4,
|
65 |
+
)
|
66 |
+
elif pipeline_class == "StableDiffusionXLPipeline":
|
67 |
+
print("Add FreeU - SDXL")
|
68 |
+
self.pipeline.enable_freeu(
|
69 |
+
s1=0.6,
|
70 |
+
s2=0.4,
|
71 |
+
b1=1.1,
|
72 |
+
b2=1.2,
|
73 |
+
)
|
74 |
+
|
75 |
+
def _update_lcm_scheduler_params(self):
|
76 |
+
if isinstance(self.pipeline.scheduler, LCMScheduler):
|
77 |
+
self.pipeline.scheduler = LCMScheduler.from_config(
|
78 |
+
self.pipeline.scheduler.config,
|
79 |
+
beta_start=0.001,
|
80 |
+
beta_end=0.01,
|
81 |
+
)
|
82 |
+
|
83 |
+
def init(
|
84 |
+
self,
|
85 |
+
device: str = "cpu",
|
86 |
+
lcm_diffusion_setting: LCMDiffusionSetting = LCMDiffusionSetting(),
|
87 |
+
) -> None:
|
88 |
+
self.device = device
|
89 |
+
self.use_openvino = lcm_diffusion_setting.use_openvino
|
90 |
+
model_id = lcm_diffusion_setting.lcm_model_id
|
91 |
+
use_local_model = lcm_diffusion_setting.use_offline_model
|
92 |
+
use_tiny_auto_encoder = lcm_diffusion_setting.use_tiny_auto_encoder
|
93 |
+
use_lora = lcm_diffusion_setting.use_lcm_lora
|
94 |
+
lcm_lora: LCMLora = lcm_diffusion_setting.lcm_lora
|
95 |
+
ov_model_id = lcm_diffusion_setting.openvino_lcm_model_id
|
96 |
+
|
97 |
+
if lcm_diffusion_setting.diffusion_task == DiffusionTask.image_to_image.value:
|
98 |
+
w, h = lcm_diffusion_setting.init_image.size
|
99 |
+
newW = lcm_diffusion_setting.image_width
|
100 |
+
newH = int(h * newW / w)
|
101 |
+
img = lcm_diffusion_setting.init_image.resize((newW, newH))
|
102 |
+
print("新图",newH,newW, lcm_diffusion_setting.image_height)
|
103 |
+
lcm_diffusion_setting.init_image = resize_pil_image(
|
104 |
+
img,
|
105 |
+
lcm_diffusion_setting.image_width,
|
106 |
+
lcm_diffusion_setting.image_height,
|
107 |
+
)
|
108 |
+
print("图片大小",lcm_diffusion_setting.init_image)
|
109 |
+
|
110 |
+
if (
|
111 |
+
self.pipeline is None
|
112 |
+
or self.previous_model_id != model_id
|
113 |
+
or self.previous_use_tae_sd != use_tiny_auto_encoder
|
114 |
+
or self.previous_lcm_lora_base_id != lcm_lora.base_model_id
|
115 |
+
or self.previous_lcm_lora_id != lcm_lora.lcm_lora_id
|
116 |
+
or self.previous_use_lcm_lora != use_lora
|
117 |
+
or self.previous_ov_model_id != ov_model_id
|
118 |
+
or self.previous_safety_checker != lcm_diffusion_setting.use_safety_checker
|
119 |
+
or self.previous_use_openvino != lcm_diffusion_setting.use_openvino
|
120 |
+
or self.previous_task_type != lcm_diffusion_setting.diffusion_task
|
121 |
+
):
|
122 |
+
if self.use_openvino and is_openvino_device():
|
123 |
+
if self.pipeline:
|
124 |
+
del self.pipeline
|
125 |
+
self.pipeline = None
|
126 |
+
self.is_openvino_init = True
|
127 |
+
if (
|
128 |
+
lcm_diffusion_setting.diffusion_task
|
129 |
+
== DiffusionTask.text_to_image.value
|
130 |
+
):
|
131 |
+
print(f"***** Init Text to image (OpenVINO) - {ov_model_id} *****")
|
132 |
+
self.pipeline = get_ov_text_to_image_pipeline(
|
133 |
+
ov_model_id,
|
134 |
+
use_local_model,
|
135 |
+
)
|
136 |
+
elif (
|
137 |
+
lcm_diffusion_setting.diffusion_task
|
138 |
+
== DiffusionTask.image_to_image.value
|
139 |
+
):
|
140 |
+
print(f"***** Image to image (OpenVINO) - {ov_model_id} *****")
|
141 |
+
self.pipeline = get_ov_image_to_image_pipeline(
|
142 |
+
ov_model_id,
|
143 |
+
use_local_model,
|
144 |
+
)
|
145 |
+
else:
|
146 |
+
if self.pipeline:
|
147 |
+
del self.pipeline
|
148 |
+
self.pipeline = None
|
149 |
+
if self.img_to_img_pipeline:
|
150 |
+
del self.img_to_img_pipeline
|
151 |
+
self.img_to_img_pipeline = None
|
152 |
+
|
153 |
+
if use_lora:
|
154 |
+
print(
|
155 |
+
f"***** Init LCM-LoRA pipeline - {lcm_lora.base_model_id} *****"
|
156 |
+
)
|
157 |
+
self.pipeline = get_lcm_lora_pipeline(
|
158 |
+
lcm_lora.base_model_id,
|
159 |
+
lcm_lora.lcm_lora_id,
|
160 |
+
use_local_model,
|
161 |
+
torch_data_type=self.torch_data_type,
|
162 |
+
)
|
163 |
+
else:
|
164 |
+
print(f"***** Init LCM Model pipeline - {model_id} *****")
|
165 |
+
self.pipeline = get_lcm_model_pipeline(
|
166 |
+
model_id,
|
167 |
+
use_local_model,
|
168 |
+
)
|
169 |
+
|
170 |
+
if (
|
171 |
+
lcm_diffusion_setting.diffusion_task
|
172 |
+
== DiffusionTask.image_to_image.value
|
173 |
+
):
|
174 |
+
self.img_to_img_pipeline = get_image_to_image_pipeline(
|
175 |
+
self.pipeline
|
176 |
+
)
|
177 |
+
self._pipeline_to_device()
|
178 |
+
|
179 |
+
if use_tiny_auto_encoder:
|
180 |
+
if self.use_openvino and is_openvino_device():
|
181 |
+
print("Using Tiny Auto Encoder (OpenVINO)")
|
182 |
+
ov_load_taesd(
|
183 |
+
self.pipeline,
|
184 |
+
use_local_model,
|
185 |
+
)
|
186 |
+
else:
|
187 |
+
print("Using Tiny Auto Encoder")
|
188 |
+
if (
|
189 |
+
lcm_diffusion_setting.diffusion_task
|
190 |
+
== DiffusionTask.text_to_image.value
|
191 |
+
):
|
192 |
+
load_taesd(
|
193 |
+
self.pipeline,
|
194 |
+
use_local_model,
|
195 |
+
self.torch_data_type,
|
196 |
+
)
|
197 |
+
elif (
|
198 |
+
lcm_diffusion_setting.diffusion_task
|
199 |
+
== DiffusionTask.image_to_image.value
|
200 |
+
):
|
201 |
+
load_taesd(
|
202 |
+
self.img_to_img_pipeline,
|
203 |
+
use_local_model,
|
204 |
+
self.torch_data_type,
|
205 |
+
)
|
206 |
+
|
207 |
+
if (
|
208 |
+
lcm_diffusion_setting.diffusion_task
|
209 |
+
== DiffusionTask.image_to_image.value
|
210 |
+
and lcm_diffusion_setting.use_openvino
|
211 |
+
):
|
212 |
+
self.pipeline.scheduler = LCMScheduler.from_config(
|
213 |
+
self.pipeline.scheduler.config,
|
214 |
+
)
|
215 |
+
else:
|
216 |
+
self._update_lcm_scheduler_params()
|
217 |
+
|
218 |
+
if use_lora:
|
219 |
+
self._add_freeu()
|
220 |
+
|
221 |
+
self.previous_model_id = model_id
|
222 |
+
self.previous_ov_model_id = ov_model_id
|
223 |
+
self.previous_use_tae_sd = use_tiny_auto_encoder
|
224 |
+
self.previous_lcm_lora_base_id = lcm_lora.base_model_id
|
225 |
+
self.previous_lcm_lora_id = lcm_lora.lcm_lora_id
|
226 |
+
self.previous_use_lcm_lora = use_lora
|
227 |
+
self.previous_safety_checker = lcm_diffusion_setting.use_safety_checker
|
228 |
+
self.previous_use_openvino = lcm_diffusion_setting.use_openvino
|
229 |
+
self.previous_task_type = lcm_diffusion_setting.diffusion_task
|
230 |
+
if (
|
231 |
+
lcm_diffusion_setting.diffusion_task
|
232 |
+
== DiffusionTask.text_to_image.value
|
233 |
+
):
|
234 |
+
print(f"Pipeline : {self.pipeline}")
|
235 |
+
elif (
|
236 |
+
lcm_diffusion_setting.diffusion_task
|
237 |
+
== DiffusionTask.image_to_image.value
|
238 |
+
):
|
239 |
+
if self.use_openvino and is_openvino_device():
|
240 |
+
print(f"Pipeline : {self.pipeline}")
|
241 |
+
else:
|
242 |
+
print(f"Pipeline : {self.img_to_img_pipeline}")
|
243 |
+
|
244 |
+
def generate(
|
245 |
+
self,
|
246 |
+
lcm_diffusion_setting: LCMDiffusionSetting,
|
247 |
+
reshape: bool = False,
|
248 |
+
) -> Any:
|
249 |
+
guidance_scale = lcm_diffusion_setting.guidance_scale
|
250 |
+
img_to_img_inference_steps = lcm_diffusion_setting.inference_steps
|
251 |
+
check_step_value = int(
|
252 |
+
lcm_diffusion_setting.inference_steps * lcm_diffusion_setting.strength
|
253 |
+
)
|
254 |
+
if (
|
255 |
+
lcm_diffusion_setting.diffusion_task == DiffusionTask.image_to_image.value
|
256 |
+
and check_step_value < 1
|
257 |
+
):
|
258 |
+
img_to_img_inference_steps = ceil(1 / lcm_diffusion_setting.strength)
|
259 |
+
print(
|
260 |
+
f"Strength: {lcm_diffusion_setting.strength},{img_to_img_inference_steps}"
|
261 |
+
)
|
262 |
+
|
263 |
+
if lcm_diffusion_setting.use_seed:
|
264 |
+
cur_seed = lcm_diffusion_setting.seed
|
265 |
+
if self.use_openvino:
|
266 |
+
np.random.seed(cur_seed)
|
267 |
+
else:
|
268 |
+
torch.manual_seed(cur_seed)
|
269 |
+
|
270 |
+
is_openvino_pipe = lcm_diffusion_setting.use_openvino and is_openvino_device()
|
271 |
+
if is_openvino_pipe:
|
272 |
+
print("Using OpenVINO")
|
273 |
+
if reshape and not self.is_openvino_init:
|
274 |
+
print("Reshape and compile")
|
275 |
+
self.pipeline.reshape(
|
276 |
+
batch_size=-1,
|
277 |
+
height=lcm_diffusion_setting.image_height,
|
278 |
+
width=lcm_diffusion_setting.image_width,
|
279 |
+
num_images_per_prompt=lcm_diffusion_setting.number_of_images,
|
280 |
+
)
|
281 |
+
self.pipeline.compile()
|
282 |
+
|
283 |
+
if self.is_openvino_init:
|
284 |
+
self.is_openvino_init = False
|
285 |
+
|
286 |
+
if not lcm_diffusion_setting.use_safety_checker:
|
287 |
+
self.pipeline.safety_checker = None
|
288 |
+
if (
|
289 |
+
lcm_diffusion_setting.diffusion_task
|
290 |
+
== DiffusionTask.image_to_image.value
|
291 |
+
and not is_openvino_pipe
|
292 |
+
):
|
293 |
+
self.img_to_img_pipeline.safety_checker = None
|
294 |
+
|
295 |
+
if (
|
296 |
+
not lcm_diffusion_setting.use_lcm_lora
|
297 |
+
and not lcm_diffusion_setting.use_openvino
|
298 |
+
and lcm_diffusion_setting.guidance_scale != 1.0
|
299 |
+
):
|
300 |
+
print("Not using LCM-LoRA so setting guidance_scale 1.0")
|
301 |
+
guidance_scale = 1.0
|
302 |
+
|
303 |
+
if lcm_diffusion_setting.use_openvino:
|
304 |
+
if (
|
305 |
+
lcm_diffusion_setting.diffusion_task
|
306 |
+
== DiffusionTask.text_to_image.value
|
307 |
+
):
|
308 |
+
result_images = self.pipeline(
|
309 |
+
prompt=lcm_diffusion_setting.prompt,
|
310 |
+
negative_prompt=lcm_diffusion_setting.negative_prompt,
|
311 |
+
num_inference_steps=lcm_diffusion_setting.inference_steps,
|
312 |
+
guidance_scale=guidance_scale,
|
313 |
+
width=lcm_diffusion_setting.image_width,
|
314 |
+
height=lcm_diffusion_setting.image_height,
|
315 |
+
num_images_per_prompt=lcm_diffusion_setting.number_of_images,
|
316 |
+
).images
|
317 |
+
elif (
|
318 |
+
lcm_diffusion_setting.diffusion_task
|
319 |
+
== DiffusionTask.image_to_image.value
|
320 |
+
):
|
321 |
+
result_images = self.pipeline(
|
322 |
+
image=lcm_diffusion_setting.init_image,
|
323 |
+
strength=lcm_diffusion_setting.strength,
|
324 |
+
prompt=lcm_diffusion_setting.prompt,
|
325 |
+
negative_prompt=lcm_diffusion_setting.negative_prompt,
|
326 |
+
num_inference_steps=img_to_img_inference_steps * 3,
|
327 |
+
guidance_scale=guidance_scale,
|
328 |
+
num_images_per_prompt=lcm_diffusion_setting.number_of_images,
|
329 |
+
).images
|
330 |
+
|
331 |
+
else:
|
332 |
+
if (
|
333 |
+
lcm_diffusion_setting.diffusion_task
|
334 |
+
== DiffusionTask.text_to_image.value
|
335 |
+
):
|
336 |
+
result_images = self.pipeline(
|
337 |
+
prompt=lcm_diffusion_setting.prompt,
|
338 |
+
negative_prompt=lcm_diffusion_setting.negative_prompt,
|
339 |
+
num_inference_steps=lcm_diffusion_setting.inference_steps,
|
340 |
+
guidance_scale=guidance_scale,
|
341 |
+
width=lcm_diffusion_setting.image_width,
|
342 |
+
height=lcm_diffusion_setting.image_height,
|
343 |
+
num_images_per_prompt=lcm_diffusion_setting.number_of_images,
|
344 |
+
).images
|
345 |
+
elif (
|
346 |
+
lcm_diffusion_setting.diffusion_task
|
347 |
+
== DiffusionTask.image_to_image.value
|
348 |
+
):
|
349 |
+
result_images = self.img_to_img_pipeline(
|
350 |
+
image=lcm_diffusion_setting.init_image,
|
351 |
+
strength=lcm_diffusion_setting.strength,
|
352 |
+
prompt=lcm_diffusion_setting.prompt,
|
353 |
+
negative_prompt=lcm_diffusion_setting.negative_prompt,
|
354 |
+
num_inference_steps=img_to_img_inference_steps,
|
355 |
+
guidance_scale=guidance_scale,
|
356 |
+
width=lcm_diffusion_setting.image_width,
|
357 |
+
height=lcm_diffusion_setting.image_height,
|
358 |
+
num_images_per_prompt=lcm_diffusion_setting.number_of_images,
|
359 |
+
).images
|
360 |
+
|
361 |
+
return result_images
|
backend/models/lcmdiffusion_setting.py
ADDED
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from typing import Optional, Any
|
2 |
+
from enum import Enum
|
3 |
+
from pydantic import BaseModel
|
4 |
+
from constants import LCM_DEFAULT_MODEL, LCM_DEFAULT_MODEL_OPENVINO
|
5 |
+
|
6 |
+
|
7 |
+
class LCMLora(BaseModel):
|
8 |
+
base_model_id: str = "Lykon/dreamshaper-8"
|
9 |
+
lcm_lora_id: str = "latent-consistency/lcm-lora-sdv1-5"
|
10 |
+
|
11 |
+
|
12 |
+
class DiffusionTask(str, Enum):
|
13 |
+
"""Diffusion task types"""
|
14 |
+
|
15 |
+
text_to_image = "text_to_image"
|
16 |
+
image_to_image = "image_to_image"
|
17 |
+
|
18 |
+
|
19 |
+
class LCMDiffusionSetting(BaseModel):
|
20 |
+
lcm_model_id: str = LCM_DEFAULT_MODEL
|
21 |
+
openvino_lcm_model_id: str = LCM_DEFAULT_MODEL_OPENVINO
|
22 |
+
use_offline_model: bool = False
|
23 |
+
use_lcm_lora: bool = False
|
24 |
+
lcm_lora: Optional[LCMLora] = LCMLora()
|
25 |
+
use_tiny_auto_encoder: bool = False
|
26 |
+
use_openvino: bool = False
|
27 |
+
prompt: str = ""
|
28 |
+
negative_prompt: str = ""
|
29 |
+
init_image: Any = None
|
30 |
+
strength: Optional[float] = 0.6
|
31 |
+
image_height: Optional[int] = 512
|
32 |
+
image_width: Optional[int] = 512
|
33 |
+
inference_steps: Optional[int] = 1
|
34 |
+
guidance_scale: Optional[float] = 1
|
35 |
+
number_of_images: Optional[int] = 1
|
36 |
+
seed: Optional[int] = 123123
|
37 |
+
use_seed: bool = False
|
38 |
+
use_safety_checker: bool = False
|
39 |
+
diffusion_task: str = DiffusionTask.text_to_image.value
|
backend/openvino/custom_ov_model_vae_decoder.py
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from backend.device import is_openvino_device
|
2 |
+
|
3 |
+
if is_openvino_device():
|
4 |
+
from optimum.intel.openvino.modeling_diffusion import OVModelVaeDecoder
|
5 |
+
|
6 |
+
|
7 |
+
class CustomOVModelVaeDecoder(OVModelVaeDecoder):
|
8 |
+
def __init__(
|
9 |
+
self,
|
10 |
+
model,
|
11 |
+
parent_model,
|
12 |
+
ov_config=None,
|
13 |
+
model_dir=None,
|
14 |
+
):
|
15 |
+
super(OVModelVaeDecoder, self).__init__(
|
16 |
+
model,
|
17 |
+
parent_model,
|
18 |
+
ov_config,
|
19 |
+
"vae_decoder",
|
20 |
+
model_dir,
|
21 |
+
)
|
backend/openvino/pipelines.py
ADDED
@@ -0,0 +1,75 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from constants import DEVICE, LCM_DEFAULT_MODEL_OPENVINO
|
2 |
+
from backend.tiny_decoder import get_tiny_decoder_vae_model
|
3 |
+
from typing import Any
|
4 |
+
from backend.device import is_openvino_device
|
5 |
+
from paths import get_base_folder_name
|
6 |
+
|
7 |
+
if is_openvino_device():
|
8 |
+
from huggingface_hub import snapshot_download
|
9 |
+
from optimum.intel.openvino.modeling_diffusion import OVBaseModel
|
10 |
+
|
11 |
+
from optimum.intel.openvino.modeling_diffusion import (
|
12 |
+
OVStableDiffusionPipeline,
|
13 |
+
OVStableDiffusionImg2ImgPipeline,
|
14 |
+
OVStableDiffusionXLPipeline,
|
15 |
+
OVStableDiffusionXLImg2ImgPipeline,
|
16 |
+
)
|
17 |
+
from backend.openvino.custom_ov_model_vae_decoder import CustomOVModelVaeDecoder
|
18 |
+
|
19 |
+
|
20 |
+
def ov_load_taesd(
|
21 |
+
pipeline: Any,
|
22 |
+
use_local_model: bool = False,
|
23 |
+
):
|
24 |
+
taesd_dir = snapshot_download(
|
25 |
+
repo_id=get_tiny_decoder_vae_model(pipeline.__class__.__name__),
|
26 |
+
local_files_only=use_local_model,
|
27 |
+
)
|
28 |
+
pipeline.vae_decoder = CustomOVModelVaeDecoder(
|
29 |
+
model=OVBaseModel.load_model(f"{taesd_dir}/vae_decoder/openvino_model.xml"),
|
30 |
+
parent_model=pipeline,
|
31 |
+
model_dir=taesd_dir,
|
32 |
+
)
|
33 |
+
|
34 |
+
|
35 |
+
def get_ov_text_to_image_pipeline(
|
36 |
+
model_id: str = LCM_DEFAULT_MODEL_OPENVINO,
|
37 |
+
use_local_model: bool = False,
|
38 |
+
) -> Any:
|
39 |
+
if "xl" in get_base_folder_name(model_id).lower():
|
40 |
+
pipeline = OVStableDiffusionXLPipeline.from_pretrained(
|
41 |
+
model_id,
|
42 |
+
local_files_only=use_local_model,
|
43 |
+
ov_config={"CACHE_DIR": ""},
|
44 |
+
device=DEVICE.upper(),
|
45 |
+
)
|
46 |
+
else:
|
47 |
+
pipeline = OVStableDiffusionPipeline.from_pretrained(
|
48 |
+
model_id,
|
49 |
+
local_files_only=use_local_model,
|
50 |
+
ov_config={"CACHE_DIR": ""},
|
51 |
+
device=DEVICE.upper(),
|
52 |
+
)
|
53 |
+
|
54 |
+
return pipeline
|
55 |
+
|
56 |
+
|
57 |
+
def get_ov_image_to_image_pipeline(
|
58 |
+
model_id: str = LCM_DEFAULT_MODEL_OPENVINO,
|
59 |
+
use_local_model: bool = False,
|
60 |
+
) -> Any:
|
61 |
+
if "xl" in get_base_folder_name(model_id).lower():
|
62 |
+
pipeline = OVStableDiffusionXLImg2ImgPipeline.from_pretrained(
|
63 |
+
model_id,
|
64 |
+
local_files_only=use_local_model,
|
65 |
+
ov_config={"CACHE_DIR": ""},
|
66 |
+
device=DEVICE.upper(),
|
67 |
+
)
|
68 |
+
else:
|
69 |
+
pipeline = OVStableDiffusionImg2ImgPipeline.from_pretrained(
|
70 |
+
model_id,
|
71 |
+
local_files_only=use_local_model,
|
72 |
+
ov_config={"CACHE_DIR": ""},
|
73 |
+
device=DEVICE.upper(),
|
74 |
+
)
|
75 |
+
return pipeline
|
backend/pipelines/lcm.py
ADDED
@@ -0,0 +1,90 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from constants import LCM_DEFAULT_MODEL
|
2 |
+
from diffusers import (
|
3 |
+
DiffusionPipeline,
|
4 |
+
AutoencoderTiny,
|
5 |
+
UNet2DConditionModel,
|
6 |
+
LCMScheduler,
|
7 |
+
)
|
8 |
+
import torch
|
9 |
+
from backend.tiny_decoder import get_tiny_decoder_vae_model
|
10 |
+
from typing import Any
|
11 |
+
from diffusers import (
|
12 |
+
LCMScheduler,
|
13 |
+
StableDiffusionImg2ImgPipeline,
|
14 |
+
StableDiffusionXLImg2ImgPipeline,
|
15 |
+
)
|
16 |
+
|
17 |
+
|
18 |
+
def _get_lcm_pipeline_from_base_model(
|
19 |
+
lcm_model_id: str,
|
20 |
+
base_model_id: str,
|
21 |
+
use_local_model: bool,
|
22 |
+
):
|
23 |
+
pipeline = None
|
24 |
+
unet = UNet2DConditionModel.from_pretrained(
|
25 |
+
lcm_model_id,
|
26 |
+
torch_dtype=torch.float32,
|
27 |
+
local_files_only=use_local_model,
|
28 |
+
)
|
29 |
+
pipeline = DiffusionPipeline.from_pretrained(
|
30 |
+
base_model_id,
|
31 |
+
unet=unet,
|
32 |
+
torch_dtype=torch.float32,
|
33 |
+
local_files_only=use_local_model,
|
34 |
+
)
|
35 |
+
pipeline.scheduler = LCMScheduler.from_config(pipeline.scheduler.config)
|
36 |
+
return pipeline
|
37 |
+
|
38 |
+
|
39 |
+
def load_taesd(
|
40 |
+
pipeline: Any,
|
41 |
+
use_local_model: bool = False,
|
42 |
+
torch_data_type: torch.dtype = torch.float32,
|
43 |
+
):
|
44 |
+
vae_model = get_tiny_decoder_vae_model(pipeline.__class__.__name__)
|
45 |
+
pipeline.vae = AutoencoderTiny.from_pretrained(
|
46 |
+
vae_model,
|
47 |
+
torch_dtype=torch_data_type,
|
48 |
+
local_files_only=use_local_model,
|
49 |
+
)
|
50 |
+
|
51 |
+
|
52 |
+
def get_lcm_model_pipeline(
|
53 |
+
model_id: str = LCM_DEFAULT_MODEL,
|
54 |
+
use_local_model: bool = False,
|
55 |
+
):
|
56 |
+
pipeline = None
|
57 |
+
if model_id == "latent-consistency/lcm-sdxl":
|
58 |
+
pipeline = _get_lcm_pipeline_from_base_model(
|
59 |
+
model_id,
|
60 |
+
"stabilityai/stable-diffusion-xl-base-1.0",
|
61 |
+
use_local_model,
|
62 |
+
)
|
63 |
+
|
64 |
+
elif model_id == "latent-consistency/lcm-ssd-1b":
|
65 |
+
pipeline = _get_lcm_pipeline_from_base_model(
|
66 |
+
model_id,
|
67 |
+
"segmind/SSD-1B",
|
68 |
+
use_local_model,
|
69 |
+
)
|
70 |
+
else:
|
71 |
+
pipeline = DiffusionPipeline.from_pretrained(
|
72 |
+
model_id,
|
73 |
+
local_files_only=use_local_model,
|
74 |
+
)
|
75 |
+
|
76 |
+
return pipeline
|
77 |
+
|
78 |
+
|
79 |
+
def get_image_to_image_pipeline(pipeline: Any) -> Any:
|
80 |
+
components = pipeline.components
|
81 |
+
pipeline_class = pipeline.__class__.__name__
|
82 |
+
if (
|
83 |
+
pipeline_class == "LatentConsistencyModelPipeline"
|
84 |
+
or pipeline_class == "StableDiffusionPipeline"
|
85 |
+
):
|
86 |
+
return StableDiffusionImg2ImgPipeline(**components)
|
87 |
+
elif pipeline_class == "StableDiffusionXLPipeline":
|
88 |
+
return StableDiffusionXLImg2ImgPipeline(**components)
|
89 |
+
else:
|
90 |
+
raise Exception(f"Unknown pipeline {pipeline_class}")
|
backend/pipelines/lcm_lora.py
ADDED
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from diffusers import DiffusionPipeline, LCMScheduler
|
2 |
+
import torch
|
3 |
+
|
4 |
+
|
5 |
+
def get_lcm_lora_pipeline(
|
6 |
+
base_model_id: str,
|
7 |
+
lcm_lora_id: str,
|
8 |
+
use_local_model: bool,
|
9 |
+
torch_data_type: torch.dtype,
|
10 |
+
):
|
11 |
+
pipeline = DiffusionPipeline.from_pretrained(
|
12 |
+
base_model_id,
|
13 |
+
torch_dtype=torch_data_type,
|
14 |
+
local_files_only=use_local_model,
|
15 |
+
)
|
16 |
+
pipeline.load_lora_weights(
|
17 |
+
lcm_lora_id,
|
18 |
+
local_files_only=use_local_model,
|
19 |
+
)
|
20 |
+
if "lcm" in lcm_lora_id.lower():
|
21 |
+
print("LCM LoRA model detected so using recommended LCMScheduler")
|
22 |
+
pipeline.scheduler = LCMScheduler.from_config(pipeline.scheduler.config)
|
23 |
+
pipeline.fuse_lora()
|
24 |
+
pipeline.unet.to(memory_format=torch.channels_last)
|
25 |
+
return pipeline
|
backend/tiny_decoder.py
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from constants import (
|
2 |
+
TAESD_MODEL,
|
3 |
+
TAESDXL_MODEL,
|
4 |
+
TAESD_MODEL_OPENVINO,
|
5 |
+
TAESDXL_MODEL_OPENVINO,
|
6 |
+
)
|
7 |
+
|
8 |
+
|
9 |
+
def get_tiny_decoder_vae_model(pipeline_class) -> str:
|
10 |
+
print(f"Pipeline class : {pipeline_class}")
|
11 |
+
if (
|
12 |
+
pipeline_class == "LatentConsistencyModelPipeline"
|
13 |
+
or pipeline_class == "StableDiffusionPipeline"
|
14 |
+
or pipeline_class == "StableDiffusionImg2ImgPipeline"
|
15 |
+
):
|
16 |
+
return TAESD_MODEL
|
17 |
+
elif (
|
18 |
+
pipeline_class == "StableDiffusionXLPipeline"
|
19 |
+
or pipeline_class == "StableDiffusionXLImg2ImgPipeline"
|
20 |
+
):
|
21 |
+
return TAESDXL_MODEL
|
22 |
+
elif (
|
23 |
+
pipeline_class == "OVStableDiffusionPipeline"
|
24 |
+
or pipeline_class == "OVStableDiffusionImg2ImgPipeline"
|
25 |
+
):
|
26 |
+
return TAESD_MODEL_OPENVINO
|
27 |
+
elif pipeline_class == "OVStableDiffusionXLPipeline":
|
28 |
+
return TAESDXL_MODEL_OPENVINO
|
29 |
+
else:
|
30 |
+
raise Exception("No valid pipeline class found!")
|
configs/lcm-lora-models.txt
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
latent-consistency/lcm-lora-sdv1-5
|
2 |
+
latent-consistency/lcm-lora-sdxl
|
3 |
+
latent-consistency/lcm-lora-ssd-1b
|
configs/lcm-models.txt
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
SimianLuo/LCM_Dreamshaper_v7
|
2 |
+
stabilityai/sd-turbo
|
3 |
+
stabilityai/sdxl-turbo
|
4 |
+
latent-consistency/lcm-sdxl
|
5 |
+
latent-consistency/lcm-ssd-1b
|
configs/openvino-lcm-models.txt
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
rupeshs/LCM-dreamshaper-v7-openvino
|
2 |
+
rupeshs/sd-turbo-openvino
|
3 |
+
rupeshs/sdxl-turbo-openvino-int8
|
4 |
+
Disty0/LCM_SoteMix
|
configs/stable-diffusion-models.txt
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Lykon/dreamshaper-8
|
2 |
+
Fictiverse/Stable_Diffusion_PaperCut_Model
|
3 |
+
stabilityai/stable-diffusion-xl-base-1.0
|
4 |
+
runwayml/stable-diffusion-v1-5
|
5 |
+
segmind/SSD-1B
|
6 |
+
stablediffusionapi/anything-v5
|
7 |
+
prompthero/openjourney-v4
|
constants.py
CHANGED
@@ -1,211 +1,18 @@
|
|
1 |
-
|
2 |
-
# Real Time Latent Consistency Model
|
3 |
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
""
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
<path
|
21 |
-
d="M52.308 3.07812H57.8465V4.92428H56.0003V6.77043H54.1541V10.4627H57.8465V12.3089H54.1541V25.232H52.308V27.0781H46.7695V25.232H48.6157V12.3089H46.7695V10.4627H48.6157V6.77043H50.4618V4.92428H52.308V3.07812Z"
|
22 |
-
fill="currentColor"
|
23 |
-
></path>
|
24 |
-
<path
|
25 |
-
d="M79.3849 23.3858H81.2311V25.232H83.0772V27.0781H88.6157V25.232H86.7695V23.3858H84.9234V4.92428H79.3849V23.3858Z"
|
26 |
-
fill="currentColor"
|
27 |
-
></path>
|
28 |
-
<path
|
29 |
-
d="M57.8465 14.155H59.6926V12.3089H61.5388V10.4627H70.7695V12.3089H74.4618V23.3858H76.308V25.232H78.1541V27.0781H72.6157V25.232H70.7695V23.3858H68.9234V14.155H67.0772V12.3089H65.2311V14.155H63.3849V23.3858H65.2311V25.232H67.0772V27.0781H61.5388V25.232H59.6926V23.3858H57.8465V14.155Z"
|
30 |
-
fill="currentColor"
|
31 |
-
></path>
|
32 |
-
<path
|
33 |
-
d="M67.0772 25.232V23.3858H68.9234V25.232H67.0772Z"
|
34 |
-
fill="currentColor"
|
35 |
-
></path>
|
36 |
-
<rect
|
37 |
-
opacity="0.22"
|
38 |
-
x="7.38477"
|
39 |
-
y="29.5391"
|
40 |
-
width="2.46154"
|
41 |
-
height="2.46154"
|
42 |
-
fill="#5F4CD9"
|
43 |
-
></rect>
|
44 |
-
<rect
|
45 |
-
opacity="0.85"
|
46 |
-
x="2.46094"
|
47 |
-
y="19.6914"
|
48 |
-
width="12.3077"
|
49 |
-
height="2.46154"
|
50 |
-
fill="#5F4CD9"
|
51 |
-
></rect>
|
52 |
-
<rect
|
53 |
-
x="4.92383"
|
54 |
-
y="17.2305"
|
55 |
-
width="9.84615"
|
56 |
-
height="2.46154"
|
57 |
-
fill="#5F4CD9"
|
58 |
-
></rect>
|
59 |
-
<rect
|
60 |
-
opacity="0.4"
|
61 |
-
x="7.38477"
|
62 |
-
y="27.0781"
|
63 |
-
width="4.92308"
|
64 |
-
height="2.46154"
|
65 |
-
fill="#5F4CD9"
|
66 |
-
></rect>
|
67 |
-
<rect
|
68 |
-
opacity="0.7"
|
69 |
-
y="22.1562"
|
70 |
-
width="14.7692"
|
71 |
-
height="2.46154"
|
72 |
-
fill="#5F4CD9"
|
73 |
-
></rect>
|
74 |
-
<rect
|
75 |
-
opacity="0.5"
|
76 |
-
x="7.38477"
|
77 |
-
y="24.6133"
|
78 |
-
width="7.38462"
|
79 |
-
height="2.46154"
|
80 |
-
fill="#5F4CD9"
|
81 |
-
></rect>
|
82 |
-
<rect
|
83 |
-
opacity="0.22"
|
84 |
-
x="7.38477"
|
85 |
-
y="12.3086"
|
86 |
-
width="2.46154"
|
87 |
-
height="2.46154"
|
88 |
-
fill="#5F4CD9"
|
89 |
-
></rect>
|
90 |
-
<rect
|
91 |
-
opacity="0.85"
|
92 |
-
x="2.46094"
|
93 |
-
y="2.46094"
|
94 |
-
width="12.3077"
|
95 |
-
height="2.46154"
|
96 |
-
fill="#5F4CD9"
|
97 |
-
></rect>
|
98 |
-
<rect x="4.92383" width="9.84615" height="2.46154" fill="#5F4CD9"></rect>
|
99 |
-
<rect
|
100 |
-
opacity="0.4"
|
101 |
-
x="7.38477"
|
102 |
-
y="9.84375"
|
103 |
-
width="4.92308"
|
104 |
-
height="2.46154"
|
105 |
-
fill="#5F4CD9"
|
106 |
-
></rect>
|
107 |
-
<rect
|
108 |
-
opacity="0.7"
|
109 |
-
y="4.92188"
|
110 |
-
width="14.7692"
|
111 |
-
height="2.46154"
|
112 |
-
fill="#5F4CD9"
|
113 |
-
></rect>
|
114 |
-
<rect
|
115 |
-
opacity="0.5"
|
116 |
-
x="7.38477"
|
117 |
-
y="7.38281"
|
118 |
-
width="7.38462"
|
119 |
-
height="2.46154"
|
120 |
-
fill="#5F4CD9"
|
121 |
-
></rect>
|
122 |
-
<rect
|
123 |
-
opacity="0.22"
|
124 |
-
x="24.6152"
|
125 |
-
y="29.5391"
|
126 |
-
width="2.46154"
|
127 |
-
height="2.46154"
|
128 |
-
fill="#5F4CD9"
|
129 |
-
></rect>
|
130 |
-
<rect
|
131 |
-
opacity="0.85"
|
132 |
-
x="19.6914"
|
133 |
-
y="19.6914"
|
134 |
-
width="12.3077"
|
135 |
-
height="2.46154"
|
136 |
-
fill="#5F4CD9"
|
137 |
-
></rect>
|
138 |
-
<rect
|
139 |
-
x="22.1543"
|
140 |
-
y="17.2305"
|
141 |
-
width="9.84615"
|
142 |
-
height="2.46154"
|
143 |
-
fill="#5F4CD9"
|
144 |
-
></rect>
|
145 |
-
<rect
|
146 |
-
opacity="0.4"
|
147 |
-
x="24.6152"
|
148 |
-
y="27.0781"
|
149 |
-
width="4.92308"
|
150 |
-
height="2.46154"
|
151 |
-
fill="#5F4CD9"
|
152 |
-
></rect>
|
153 |
-
<rect
|
154 |
-
opacity="0.7"
|
155 |
-
x="17.2305"
|
156 |
-
y="22.1562"
|
157 |
-
width="14.7692"
|
158 |
-
height="2.46154"
|
159 |
-
fill="#5F4CD9"
|
160 |
-
></rect>
|
161 |
-
<rect
|
162 |
-
opacity="0.5"
|
163 |
-
x="24.6152"
|
164 |
-
y="24.6133"
|
165 |
-
width="7.38462"
|
166 |
-
height="2.46154"
|
167 |
-
fill="#5F4CD9"
|
168 |
-
></rect>
|
169 |
-
<rect
|
170 |
-
opacity="0.22"
|
171 |
-
x="24.6152"
|
172 |
-
y="12.3086"
|
173 |
-
width="2.46154"
|
174 |
-
height="2.46154"
|
175 |
-
fill="#5F4CD9"
|
176 |
-
></rect>
|
177 |
-
<rect
|
178 |
-
opacity="0.85"
|
179 |
-
x="19.6914"
|
180 |
-
y="2.46094"
|
181 |
-
width="12.3077"
|
182 |
-
height="2.46154"
|
183 |
-
fill="#5F4CD9"
|
184 |
-
></rect>
|
185 |
-
<rect x="22.1543" width="9.84615" height="2.46154" fill="#5F4CD9"></rect>
|
186 |
-
<rect
|
187 |
-
opacity="0.4"
|
188 |
-
x="24.6152"
|
189 |
-
y="9.84375"
|
190 |
-
width="4.92308"
|
191 |
-
height="2.46154"
|
192 |
-
fill="#5F4CD9"
|
193 |
-
></rect>
|
194 |
-
<rect
|
195 |
-
opacity="0.7"
|
196 |
-
x="17.2305"
|
197 |
-
y="4.92188"
|
198 |
-
width="14.7692"
|
199 |
-
height="2.46154"
|
200 |
-
fill="#5F4CD9"
|
201 |
-
></rect>
|
202 |
-
<rect
|
203 |
-
opacity="0.5"
|
204 |
-
x="24.6152"
|
205 |
-
y="7.38281"
|
206 |
-
width="7.38462"
|
207 |
-
height="2.46154"
|
208 |
-
fill="#5F4CD9"
|
209 |
-
></rect>
|
210 |
-
</svg>
|
211 |
-
"""
|
|
|
1 |
+
from os import environ
|
|
|
2 |
|
3 |
+
APP_VERSION = "v1.0.0 beta 23"
|
4 |
+
LCM_DEFAULT_MODEL = "SimianLuo/LCM_Dreamshaper_v7"
|
5 |
+
LCM_DEFAULT_MODEL_OPENVINO = "rupeshs/LCM-dreamshaper-v7-openvino"
|
6 |
+
APP_NAME = "FastSD CPU"
|
7 |
+
APP_SETTINGS_FILE = "settings.yaml"
|
8 |
+
RESULTS_DIRECTORY = "results"
|
9 |
+
CONFIG_DIRECTORY = "configs"
|
10 |
+
DEVICE = environ.get("DEVICE", "cpu")
|
11 |
+
SD_MODELS_FILE = "stable-diffusion-models.txt"
|
12 |
+
LCM_LORA_MODELS_FILE = "lcm-lora-models.txt"
|
13 |
+
OPENVINO_LCM_MODELS_FILE = "openvino-lcm-models.txt"
|
14 |
+
TAESD_MODEL = "madebyollin/taesd"
|
15 |
+
TAESDXL_MODEL = "madebyollin/taesdxl"
|
16 |
+
TAESD_MODEL_OPENVINO = "deinferno/taesd-openvino"
|
17 |
+
LCM_MODELS_FILE = "lcm-models.txt"
|
18 |
+
TAESDXL_MODEL_OPENVINO = "rupeshs/taesdxl-openvino"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
context.py
ADDED
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from typing import Any
|
2 |
+
from app_settings import Settings
|
3 |
+
from models.interface_types import InterfaceType
|
4 |
+
from backend.lcm_text_to_image import LCMTextToImage
|
5 |
+
from time import perf_counter
|
6 |
+
from backend.image_saver import ImageSaver
|
7 |
+
from pprint import pprint
|
8 |
+
|
9 |
+
|
10 |
+
class Context:
|
11 |
+
def __init__(
|
12 |
+
self,
|
13 |
+
interface_type: InterfaceType,
|
14 |
+
device="cpu",
|
15 |
+
):
|
16 |
+
self.interface_type = interface_type
|
17 |
+
self.lcm_text_to_image = LCMTextToImage(device)
|
18 |
+
|
19 |
+
def generate_text_to_image(
|
20 |
+
self,
|
21 |
+
settings: Settings,
|
22 |
+
reshape: bool = False,
|
23 |
+
device: str = "cpu",
|
24 |
+
) -> Any:
|
25 |
+
tick = perf_counter()
|
26 |
+
from state import get_settings
|
27 |
+
|
28 |
+
get_settings().save()
|
29 |
+
pprint(settings.lcm_diffusion_setting.model_dump())
|
30 |
+
if not settings.lcm_diffusion_setting.lcm_lora:
|
31 |
+
return None
|
32 |
+
self.lcm_text_to_image.init(
|
33 |
+
device,
|
34 |
+
settings.lcm_diffusion_setting,
|
35 |
+
)
|
36 |
+
images = self.lcm_text_to_image.generate(
|
37 |
+
settings.lcm_diffusion_setting,
|
38 |
+
reshape,
|
39 |
+
)
|
40 |
+
elapsed = perf_counter() - tick
|
41 |
+
ImageSaver.save_images(
|
42 |
+
settings.results_path,
|
43 |
+
images=images,
|
44 |
+
lcm_diffusion_setting=settings.lcm_diffusion_setting,
|
45 |
+
)
|
46 |
+
print(f"Latency : {elapsed:.2f} seconds")
|
47 |
+
return images
|
frontend/gui/app_window.py
ADDED
@@ -0,0 +1,604 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from PyQt5.QtWidgets import (
|
2 |
+
QWidget,
|
3 |
+
QPushButton,
|
4 |
+
QHBoxLayout,
|
5 |
+
QVBoxLayout,
|
6 |
+
QLabel,
|
7 |
+
QLineEdit,
|
8 |
+
QMainWindow,
|
9 |
+
QSlider,
|
10 |
+
QTabWidget,
|
11 |
+
QSpacerItem,
|
12 |
+
QSizePolicy,
|
13 |
+
QComboBox,
|
14 |
+
QCheckBox,
|
15 |
+
QTextEdit,
|
16 |
+
QToolButton,
|
17 |
+
QFileDialog,
|
18 |
+
)
|
19 |
+
from PyQt5 import QtWidgets, QtCore
|
20 |
+
from PyQt5.QtGui import QPixmap, QDesktopServices
|
21 |
+
from PyQt5.QtCore import QSize, QThreadPool, Qt, QUrl
|
22 |
+
|
23 |
+
from PIL.ImageQt import ImageQt
|
24 |
+
from constants import (
|
25 |
+
LCM_DEFAULT_MODEL,
|
26 |
+
LCM_DEFAULT_MODEL_OPENVINO,
|
27 |
+
APP_NAME,
|
28 |
+
APP_VERSION,
|
29 |
+
)
|
30 |
+
from frontend.gui.image_generator_worker import ImageGeneratorWorker
|
31 |
+
from app_settings import AppSettings
|
32 |
+
from paths import FastStableDiffusionPaths
|
33 |
+
from frontend.utils import is_reshape_required
|
34 |
+
from context import Context
|
35 |
+
from models.interface_types import InterfaceType
|
36 |
+
from constants import DEVICE
|
37 |
+
from frontend.utils import enable_openvino_controls, get_valid_model_id
|
38 |
+
from backend.models.lcmdiffusion_setting import DiffusionTask
|
39 |
+
|
40 |
+
# DPI scale fix
|
41 |
+
QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling, True)
|
42 |
+
QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps, True)
|
43 |
+
|
44 |
+
|
45 |
+
class MainWindow(QMainWindow):
|
46 |
+
def __init__(self, config: AppSettings):
|
47 |
+
super().__init__()
|
48 |
+
self.config = config
|
49 |
+
self.setWindowTitle(APP_NAME)
|
50 |
+
self.setFixedSize(QSize(600, 670))
|
51 |
+
self.init_ui()
|
52 |
+
self.pipeline = None
|
53 |
+
self.threadpool = QThreadPool()
|
54 |
+
self.device = "cpu"
|
55 |
+
self.previous_width = 0
|
56 |
+
self.previous_height = 0
|
57 |
+
self.previous_model = ""
|
58 |
+
self.previous_num_of_images = 0
|
59 |
+
self.context = Context(InterfaceType.GUI)
|
60 |
+
self.init_ui_values()
|
61 |
+
self.gen_images = []
|
62 |
+
self.image_index = 0
|
63 |
+
print(f"Output path : { self.config.settings.results_path}")
|
64 |
+
|
65 |
+
def init_ui_values(self):
|
66 |
+
self.lcm_model.setEnabled(
|
67 |
+
not self.config.settings.lcm_diffusion_setting.use_openvino
|
68 |
+
)
|
69 |
+
self.guidance.setValue(
|
70 |
+
int(self.config.settings.lcm_diffusion_setting.guidance_scale * 10)
|
71 |
+
)
|
72 |
+
self.seed_value.setEnabled(self.config.settings.lcm_diffusion_setting.use_seed)
|
73 |
+
self.safety_checker.setChecked(
|
74 |
+
self.config.settings.lcm_diffusion_setting.use_safety_checker
|
75 |
+
)
|
76 |
+
self.use_openvino_check.setChecked(
|
77 |
+
self.config.settings.lcm_diffusion_setting.use_openvino
|
78 |
+
)
|
79 |
+
self.width.setCurrentText(
|
80 |
+
str(self.config.settings.lcm_diffusion_setting.image_width)
|
81 |
+
)
|
82 |
+
self.height.setCurrentText(
|
83 |
+
str(self.config.settings.lcm_diffusion_setting.image_height)
|
84 |
+
)
|
85 |
+
self.inference_steps.setValue(
|
86 |
+
int(self.config.settings.lcm_diffusion_setting.inference_steps)
|
87 |
+
)
|
88 |
+
self.seed_check.setChecked(self.config.settings.lcm_diffusion_setting.use_seed)
|
89 |
+
self.seed_value.setText(str(self.config.settings.lcm_diffusion_setting.seed))
|
90 |
+
self.use_local_model_folder.setChecked(
|
91 |
+
self.config.settings.lcm_diffusion_setting.use_offline_model
|
92 |
+
)
|
93 |
+
self.results_path.setText(self.config.settings.results_path)
|
94 |
+
self.num_images.setValue(
|
95 |
+
self.config.settings.lcm_diffusion_setting.number_of_images
|
96 |
+
)
|
97 |
+
self.use_tae_sd.setChecked(
|
98 |
+
self.config.settings.lcm_diffusion_setting.use_tiny_auto_encoder
|
99 |
+
)
|
100 |
+
self.use_lcm_lora.setChecked(
|
101 |
+
self.config.settings.lcm_diffusion_setting.use_lcm_lora
|
102 |
+
)
|
103 |
+
self.lcm_model.setCurrentText(
|
104 |
+
get_valid_model_id(
|
105 |
+
self.config.lcm_models,
|
106 |
+
self.config.settings.lcm_diffusion_setting.lcm_model_id,
|
107 |
+
LCM_DEFAULT_MODEL,
|
108 |
+
)
|
109 |
+
)
|
110 |
+
self.base_model_id.setCurrentText(
|
111 |
+
get_valid_model_id(
|
112 |
+
self.config.stable_diffsuion_models,
|
113 |
+
self.config.settings.lcm_diffusion_setting.lcm_lora.base_model_id,
|
114 |
+
)
|
115 |
+
)
|
116 |
+
self.lcm_lora_id.setCurrentText(
|
117 |
+
get_valid_model_id(
|
118 |
+
self.config.lcm_lora_models,
|
119 |
+
self.config.settings.lcm_diffusion_setting.lcm_lora.lcm_lora_id,
|
120 |
+
)
|
121 |
+
)
|
122 |
+
self.openvino_lcm_model_id.setCurrentText(
|
123 |
+
get_valid_model_id(
|
124 |
+
self.config.openvino_lcm_models,
|
125 |
+
self.config.settings.lcm_diffusion_setting.openvino_lcm_model_id,
|
126 |
+
LCM_DEFAULT_MODEL_OPENVINO,
|
127 |
+
)
|
128 |
+
)
|
129 |
+
self.neg_prompt.setEnabled(
|
130 |
+
self.config.settings.lcm_diffusion_setting.use_lcm_lora
|
131 |
+
or self.config.settings.lcm_diffusion_setting.use_openvino
|
132 |
+
)
|
133 |
+
self.openvino_lcm_model_id.setEnabled(
|
134 |
+
self.config.settings.lcm_diffusion_setting.use_openvino
|
135 |
+
)
|
136 |
+
|
137 |
+
def init_ui(self):
|
138 |
+
self.create_main_tab()
|
139 |
+
self.create_settings_tab()
|
140 |
+
self.create_about_tab()
|
141 |
+
self.show()
|
142 |
+
|
143 |
+
def create_main_tab(self):
|
144 |
+
self.img = QLabel("<<Image>>")
|
145 |
+
self.img.setAlignment(Qt.AlignCenter)
|
146 |
+
self.img.setFixedSize(QSize(512, 512))
|
147 |
+
self.vspacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
|
148 |
+
|
149 |
+
self.prompt = QTextEdit()
|
150 |
+
self.prompt.setPlaceholderText("A fantasy landscape")
|
151 |
+
self.prompt.setAcceptRichText(False)
|
152 |
+
self.neg_prompt = QTextEdit()
|
153 |
+
self.neg_prompt.setPlaceholderText("")
|
154 |
+
self.neg_prompt.setAcceptRichText(False)
|
155 |
+
self.neg_prompt_label = QLabel("Negative prompt (Set guidance scale > 1.0):")
|
156 |
+
self.generate = QPushButton("Generate")
|
157 |
+
self.generate.clicked.connect(self.text_to_image)
|
158 |
+
self.prompt.setFixedHeight(40)
|
159 |
+
self.neg_prompt.setFixedHeight(35)
|
160 |
+
self.browse_results = QPushButton("...")
|
161 |
+
self.browse_results.setFixedWidth(30)
|
162 |
+
self.browse_results.clicked.connect(self.on_open_results_folder)
|
163 |
+
self.browse_results.setToolTip("Open output folder")
|
164 |
+
|
165 |
+
hlayout = QHBoxLayout()
|
166 |
+
hlayout.addWidget(self.neg_prompt)
|
167 |
+
hlayout.addWidget(self.generate)
|
168 |
+
hlayout.addWidget(self.browse_results)
|
169 |
+
|
170 |
+
self.previous_img_btn = QToolButton()
|
171 |
+
self.previous_img_btn.setText("<")
|
172 |
+
self.previous_img_btn.clicked.connect(self.on_show_previous_image)
|
173 |
+
self.next_img_btn = QToolButton()
|
174 |
+
self.next_img_btn.setText(">")
|
175 |
+
self.next_img_btn.clicked.connect(self.on_show_next_image)
|
176 |
+
hlayout_nav = QHBoxLayout()
|
177 |
+
hlayout_nav.addWidget(self.previous_img_btn)
|
178 |
+
hlayout_nav.addWidget(self.img)
|
179 |
+
hlayout_nav.addWidget(self.next_img_btn)
|
180 |
+
|
181 |
+
vlayout = QVBoxLayout()
|
182 |
+
vlayout.addLayout(hlayout_nav)
|
183 |
+
vlayout.addItem(self.vspacer)
|
184 |
+
vlayout.addWidget(self.prompt)
|
185 |
+
vlayout.addWidget(self.neg_prompt_label)
|
186 |
+
vlayout.addLayout(hlayout)
|
187 |
+
|
188 |
+
self.tab_widget = QTabWidget(self)
|
189 |
+
self.tab_main = QWidget()
|
190 |
+
self.tab_settings = QWidget()
|
191 |
+
self.tab_about = QWidget()
|
192 |
+
self.tab_main.setLayout(vlayout)
|
193 |
+
|
194 |
+
self.tab_widget.addTab(self.tab_main, "Text to Image")
|
195 |
+
self.tab_widget.addTab(self.tab_settings, "Settings")
|
196 |
+
self.tab_widget.addTab(self.tab_about, "About")
|
197 |
+
|
198 |
+
self.setCentralWidget(self.tab_widget)
|
199 |
+
self.use_seed = False
|
200 |
+
|
201 |
+
def create_settings_tab(self):
|
202 |
+
self.lcm_model_label = QLabel("Latent Consistency Model:")
|
203 |
+
# self.lcm_model = QLineEdit(LCM_DEFAULT_MODEL)
|
204 |
+
self.lcm_model = QComboBox(self)
|
205 |
+
self.lcm_model.addItems(self.config.lcm_models)
|
206 |
+
self.lcm_model.currentIndexChanged.connect(self.on_lcm_model_changed)
|
207 |
+
|
208 |
+
self.use_lcm_lora = QCheckBox("Use LCM LoRA")
|
209 |
+
self.use_lcm_lora.setChecked(False)
|
210 |
+
self.use_lcm_lora.stateChanged.connect(self.use_lcm_lora_changed)
|
211 |
+
|
212 |
+
self.lora_base_model_id_label = QLabel("Lora base model ID :")
|
213 |
+
self.base_model_id = QComboBox(self)
|
214 |
+
self.base_model_id.addItems(self.config.stable_diffsuion_models)
|
215 |
+
self.base_model_id.currentIndexChanged.connect(self.on_base_model_id_changed)
|
216 |
+
|
217 |
+
self.lcm_lora_model_id_label = QLabel("LCM LoRA model ID :")
|
218 |
+
self.lcm_lora_id = QComboBox(self)
|
219 |
+
self.lcm_lora_id.addItems(self.config.lcm_lora_models)
|
220 |
+
self.lcm_lora_id.currentIndexChanged.connect(self.on_lcm_lora_id_changed)
|
221 |
+
|
222 |
+
self.inference_steps_value = QLabel("Number of inference steps: 4")
|
223 |
+
self.inference_steps = QSlider(orientation=Qt.Orientation.Horizontal)
|
224 |
+
self.inference_steps.setMaximum(25)
|
225 |
+
self.inference_steps.setMinimum(1)
|
226 |
+
self.inference_steps.setValue(4)
|
227 |
+
self.inference_steps.valueChanged.connect(self.update_steps_label)
|
228 |
+
|
229 |
+
self.num_images_value = QLabel("Number of images: 1")
|
230 |
+
self.num_images = QSlider(orientation=Qt.Orientation.Horizontal)
|
231 |
+
self.num_images.setMaximum(100)
|
232 |
+
self.num_images.setMinimum(1)
|
233 |
+
self.num_images.setValue(1)
|
234 |
+
self.num_images.valueChanged.connect(self.update_num_images_label)
|
235 |
+
|
236 |
+
self.guidance_value = QLabel("Guidance scale: 1")
|
237 |
+
self.guidance = QSlider(orientation=Qt.Orientation.Horizontal)
|
238 |
+
self.guidance.setMaximum(20)
|
239 |
+
self.guidance.setMinimum(10)
|
240 |
+
self.guidance.setValue(10)
|
241 |
+
self.guidance.valueChanged.connect(self.update_guidance_label)
|
242 |
+
|
243 |
+
self.width_value = QLabel("Width :")
|
244 |
+
self.width = QComboBox(self)
|
245 |
+
self.width.addItem("256")
|
246 |
+
self.width.addItem("512")
|
247 |
+
self.width.addItem("768")
|
248 |
+
self.width.addItem("1024")
|
249 |
+
self.width.setCurrentText("512")
|
250 |
+
self.width.currentIndexChanged.connect(self.on_width_changed)
|
251 |
+
|
252 |
+
self.height_value = QLabel("Height :")
|
253 |
+
self.height = QComboBox(self)
|
254 |
+
self.height.addItem("256")
|
255 |
+
self.height.addItem("512")
|
256 |
+
self.height.addItem("768")
|
257 |
+
self.height.addItem("1024")
|
258 |
+
self.height.setCurrentText("512")
|
259 |
+
self.height.currentIndexChanged.connect(self.on_height_changed)
|
260 |
+
|
261 |
+
self.seed_check = QCheckBox("Use seed")
|
262 |
+
self.seed_value = QLineEdit()
|
263 |
+
self.seed_value.setInputMask("9999999999")
|
264 |
+
self.seed_value.setText("123123")
|
265 |
+
self.seed_check.stateChanged.connect(self.seed_changed)
|
266 |
+
|
267 |
+
self.safety_checker = QCheckBox("Use safety checker")
|
268 |
+
self.safety_checker.setChecked(True)
|
269 |
+
self.safety_checker.stateChanged.connect(self.use_safety_checker_changed)
|
270 |
+
|
271 |
+
self.use_openvino_check = QCheckBox("Use OpenVINO")
|
272 |
+
self.use_openvino_check.setChecked(False)
|
273 |
+
self.openvino_model_label = QLabel("OpenVINO LCM model:")
|
274 |
+
self.use_local_model_folder = QCheckBox(
|
275 |
+
"Use locally cached model or downloaded model folder(offline)"
|
276 |
+
)
|
277 |
+
self.openvino_lcm_model_id = QComboBox(self)
|
278 |
+
self.openvino_lcm_model_id.addItems(self.config.openvino_lcm_models)
|
279 |
+
self.openvino_lcm_model_id.currentIndexChanged.connect(
|
280 |
+
self.on_openvino_lcm_model_id_changed
|
281 |
+
)
|
282 |
+
|
283 |
+
self.use_openvino_check.setEnabled(enable_openvino_controls())
|
284 |
+
self.use_local_model_folder.setChecked(False)
|
285 |
+
self.use_local_model_folder.stateChanged.connect(self.use_offline_model_changed)
|
286 |
+
self.use_openvino_check.stateChanged.connect(self.use_openvino_changed)
|
287 |
+
|
288 |
+
self.use_tae_sd = QCheckBox(
|
289 |
+
"Use Tiny Auto Encoder - TAESD (Fast, moderate quality)"
|
290 |
+
)
|
291 |
+
self.use_tae_sd.setChecked(False)
|
292 |
+
self.use_tae_sd.stateChanged.connect(self.use_tae_sd_changed)
|
293 |
+
|
294 |
+
hlayout = QHBoxLayout()
|
295 |
+
hlayout.addWidget(self.seed_check)
|
296 |
+
hlayout.addWidget(self.seed_value)
|
297 |
+
hspacer = QSpacerItem(20, 10, QSizePolicy.Expanding, QSizePolicy.Minimum)
|
298 |
+
slider_hspacer = QSpacerItem(20, 10, QSizePolicy.Expanding, QSizePolicy.Minimum)
|
299 |
+
|
300 |
+
self.results_path_label = QLabel("Output path:")
|
301 |
+
self.results_path = QLineEdit()
|
302 |
+
self.results_path.textChanged.connect(self.on_path_changed)
|
303 |
+
self.browse_folder_btn = QToolButton()
|
304 |
+
self.browse_folder_btn.setText("...")
|
305 |
+
self.browse_folder_btn.clicked.connect(self.on_browse_folder)
|
306 |
+
|
307 |
+
self.reset = QPushButton("Reset All")
|
308 |
+
self.reset.clicked.connect(self.reset_all_settings)
|
309 |
+
|
310 |
+
vlayout = QVBoxLayout()
|
311 |
+
vspacer = QSpacerItem(20, 20, QSizePolicy.Minimum, QSizePolicy.Expanding)
|
312 |
+
vlayout.addItem(hspacer)
|
313 |
+
vlayout.setSpacing(3)
|
314 |
+
vlayout.addWidget(self.lcm_model_label)
|
315 |
+
vlayout.addWidget(self.lcm_model)
|
316 |
+
vlayout.addWidget(self.use_local_model_folder)
|
317 |
+
vlayout.addWidget(self.use_lcm_lora)
|
318 |
+
vlayout.addWidget(self.lora_base_model_id_label)
|
319 |
+
vlayout.addWidget(self.base_model_id)
|
320 |
+
vlayout.addWidget(self.lcm_lora_model_id_label)
|
321 |
+
vlayout.addWidget(self.lcm_lora_id)
|
322 |
+
vlayout.addWidget(self.use_openvino_check)
|
323 |
+
vlayout.addWidget(self.openvino_model_label)
|
324 |
+
vlayout.addWidget(self.openvino_lcm_model_id)
|
325 |
+
vlayout.addWidget(self.use_tae_sd)
|
326 |
+
vlayout.addItem(slider_hspacer)
|
327 |
+
vlayout.addWidget(self.inference_steps_value)
|
328 |
+
vlayout.addWidget(self.inference_steps)
|
329 |
+
vlayout.addWidget(self.num_images_value)
|
330 |
+
vlayout.addWidget(self.num_images)
|
331 |
+
vlayout.addWidget(self.width_value)
|
332 |
+
vlayout.addWidget(self.width)
|
333 |
+
vlayout.addWidget(self.height_value)
|
334 |
+
vlayout.addWidget(self.height)
|
335 |
+
vlayout.addWidget(self.guidance_value)
|
336 |
+
vlayout.addWidget(self.guidance)
|
337 |
+
vlayout.addLayout(hlayout)
|
338 |
+
vlayout.addWidget(self.safety_checker)
|
339 |
+
|
340 |
+
vlayout.addWidget(self.results_path_label)
|
341 |
+
hlayout_path = QHBoxLayout()
|
342 |
+
hlayout_path.addWidget(self.results_path)
|
343 |
+
hlayout_path.addWidget(self.browse_folder_btn)
|
344 |
+
vlayout.addLayout(hlayout_path)
|
345 |
+
self.tab_settings.setLayout(vlayout)
|
346 |
+
hlayout_reset = QHBoxLayout()
|
347 |
+
hspacer = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
|
348 |
+
hlayout_reset.addItem(hspacer)
|
349 |
+
hlayout_reset.addWidget(self.reset)
|
350 |
+
vlayout.addLayout(hlayout_reset)
|
351 |
+
vlayout.addItem(vspacer)
|
352 |
+
|
353 |
+
def create_about_tab(self):
|
354 |
+
self.label = QLabel()
|
355 |
+
self.label.setAlignment(Qt.AlignCenter)
|
356 |
+
self.label.setText(
|
357 |
+
f"""<h1>FastSD CPU {APP_VERSION}</h1>
|
358 |
+
<h3>(c)2023 - Rupesh Sreeraman</h3>
|
359 |
+
<h3>Faster stable diffusion on CPU</h3>
|
360 |
+
<h3>Based on Latent Consistency Models</h3>
|
361 |
+
<h3>GitHub : https://github.com/rupeshs/fastsdcpu/</h3>"""
|
362 |
+
)
|
363 |
+
|
364 |
+
vlayout = QVBoxLayout()
|
365 |
+
vlayout.addWidget(self.label)
|
366 |
+
self.tab_about.setLayout(vlayout)
|
367 |
+
|
368 |
+
def show_image(self, pixmap):
|
369 |
+
image_width = self.config.settings.lcm_diffusion_setting.image_width
|
370 |
+
image_height = self.config.settings.lcm_diffusion_setting.image_height
|
371 |
+
if image_width > 512 or image_height > 512:
|
372 |
+
new_width = 512 if image_width > 512 else image_width
|
373 |
+
new_height = 512 if image_height > 512 else image_height
|
374 |
+
self.img.setPixmap(
|
375 |
+
pixmap.scaled(
|
376 |
+
new_width,
|
377 |
+
new_height,
|
378 |
+
Qt.KeepAspectRatio,
|
379 |
+
)
|
380 |
+
)
|
381 |
+
else:
|
382 |
+
self.img.setPixmap(pixmap)
|
383 |
+
|
384 |
+
def on_show_next_image(self):
|
385 |
+
if self.image_index != len(self.gen_images) - 1 and len(self.gen_images) > 0:
|
386 |
+
self.previous_img_btn.setEnabled(True)
|
387 |
+
self.image_index += 1
|
388 |
+
self.show_image(self.gen_images[self.image_index])
|
389 |
+
if self.image_index == len(self.gen_images) - 1:
|
390 |
+
self.next_img_btn.setEnabled(False)
|
391 |
+
|
392 |
+
def on_open_results_folder(self):
|
393 |
+
QDesktopServices.openUrl(QUrl.fromLocalFile(self.config.settings.results_path))
|
394 |
+
|
395 |
+
def on_show_previous_image(self):
|
396 |
+
if self.image_index != 0:
|
397 |
+
self.next_img_btn.setEnabled(True)
|
398 |
+
self.image_index -= 1
|
399 |
+
self.show_image(self.gen_images[self.image_index])
|
400 |
+
if self.image_index == 0:
|
401 |
+
self.previous_img_btn.setEnabled(False)
|
402 |
+
|
403 |
+
def on_path_changed(self, text):
|
404 |
+
self.config.settings.results_path = text
|
405 |
+
|
406 |
+
def on_browse_folder(self):
|
407 |
+
options = QFileDialog.Options()
|
408 |
+
options |= QFileDialog.ShowDirsOnly
|
409 |
+
|
410 |
+
folder_path = QFileDialog.getExistingDirectory(
|
411 |
+
self, "Select a Folder", "", options=options
|
412 |
+
)
|
413 |
+
|
414 |
+
if folder_path:
|
415 |
+
self.config.settings.results_path = folder_path
|
416 |
+
self.results_path.setText(folder_path)
|
417 |
+
|
418 |
+
def on_width_changed(self, index):
|
419 |
+
width_txt = self.width.itemText(index)
|
420 |
+
self.config.settings.lcm_diffusion_setting.image_width = int(width_txt)
|
421 |
+
|
422 |
+
def on_height_changed(self, index):
|
423 |
+
height_txt = self.height.itemText(index)
|
424 |
+
self.config.settings.lcm_diffusion_setting.image_height = int(height_txt)
|
425 |
+
|
426 |
+
def on_lcm_model_changed(self, index):
|
427 |
+
model_id = self.lcm_model.itemText(index)
|
428 |
+
self.config.settings.lcm_diffusion_setting.lcm_model_id = model_id
|
429 |
+
|
430 |
+
def on_base_model_id_changed(self, index):
|
431 |
+
model_id = self.base_model_id.itemText(index)
|
432 |
+
self.config.settings.lcm_diffusion_setting.lcm_lora.base_model_id = model_id
|
433 |
+
|
434 |
+
def on_lcm_lora_id_changed(self, index):
|
435 |
+
model_id = self.lcm_lora_id.itemText(index)
|
436 |
+
self.config.settings.lcm_diffusion_setting.lcm_lora.lcm_lora_id = model_id
|
437 |
+
|
438 |
+
def on_openvino_lcm_model_id_changed(self, index):
|
439 |
+
model_id = self.openvino_lcm_model_id.itemText(index)
|
440 |
+
self.config.settings.lcm_diffusion_setting.openvino_lcm_model_id = model_id
|
441 |
+
|
442 |
+
def use_openvino_changed(self, state):
|
443 |
+
if state == 2:
|
444 |
+
self.lcm_model.setEnabled(False)
|
445 |
+
self.use_lcm_lora.setEnabled(False)
|
446 |
+
self.lcm_lora_id.setEnabled(False)
|
447 |
+
self.base_model_id.setEnabled(False)
|
448 |
+
self.neg_prompt.setEnabled(True)
|
449 |
+
self.openvino_lcm_model_id.setEnabled(True)
|
450 |
+
self.config.settings.lcm_diffusion_setting.use_openvino = True
|
451 |
+
else:
|
452 |
+
self.lcm_model.setEnabled(True)
|
453 |
+
self.use_lcm_lora.setEnabled(True)
|
454 |
+
self.lcm_lora_id.setEnabled(True)
|
455 |
+
self.base_model_id.setEnabled(True)
|
456 |
+
self.neg_prompt.setEnabled(False)
|
457 |
+
self.openvino_lcm_model_id.setEnabled(False)
|
458 |
+
self.config.settings.lcm_diffusion_setting.use_openvino = False
|
459 |
+
|
460 |
+
def use_tae_sd_changed(self, state):
|
461 |
+
if state == 2:
|
462 |
+
self.config.settings.lcm_diffusion_setting.use_tiny_auto_encoder = True
|
463 |
+
else:
|
464 |
+
self.config.settings.lcm_diffusion_setting.use_tiny_auto_encoder = False
|
465 |
+
|
466 |
+
def use_offline_model_changed(self, state):
|
467 |
+
if state == 2:
|
468 |
+
self.config.settings.lcm_diffusion_setting.use_offline_model = True
|
469 |
+
else:
|
470 |
+
self.config.settings.lcm_diffusion_setting.use_offline_model = False
|
471 |
+
|
472 |
+
def use_lcm_lora_changed(self, state):
|
473 |
+
if state == 2:
|
474 |
+
self.lcm_model.setEnabled(False)
|
475 |
+
self.lcm_lora_id.setEnabled(True)
|
476 |
+
self.base_model_id.setEnabled(True)
|
477 |
+
self.neg_prompt.setEnabled(True)
|
478 |
+
self.config.settings.lcm_diffusion_setting.use_lcm_lora = True
|
479 |
+
else:
|
480 |
+
self.lcm_model.setEnabled(True)
|
481 |
+
self.lcm_lora_id.setEnabled(False)
|
482 |
+
self.base_model_id.setEnabled(False)
|
483 |
+
self.neg_prompt.setEnabled(False)
|
484 |
+
self.config.settings.lcm_diffusion_setting.use_lcm_lora = False
|
485 |
+
|
486 |
+
def use_safety_checker_changed(self, state):
|
487 |
+
if state == 2:
|
488 |
+
self.config.settings.lcm_diffusion_setting.use_safety_checker = True
|
489 |
+
else:
|
490 |
+
self.config.settings.lcm_diffusion_setting.use_safety_checker = False
|
491 |
+
|
492 |
+
def update_steps_label(self, value):
|
493 |
+
self.inference_steps_value.setText(f"Number of inference steps: {value}")
|
494 |
+
self.config.settings.lcm_diffusion_setting.inference_steps = value
|
495 |
+
|
496 |
+
def update_num_images_label(self, value):
|
497 |
+
self.num_images_value.setText(f"Number of images: {value}")
|
498 |
+
self.config.settings.lcm_diffusion_setting.number_of_images = value
|
499 |
+
|
500 |
+
def update_guidance_label(self, value):
|
501 |
+
val = round(int(value) / 10, 1)
|
502 |
+
self.guidance_value.setText(f"Guidance scale: {val}")
|
503 |
+
self.config.settings.lcm_diffusion_setting.guidance_scale = val
|
504 |
+
|
505 |
+
def seed_changed(self, state):
|
506 |
+
if state == 2:
|
507 |
+
self.seed_value.setEnabled(True)
|
508 |
+
self.config.settings.lcm_diffusion_setting.use_seed = True
|
509 |
+
else:
|
510 |
+
self.seed_value.setEnabled(False)
|
511 |
+
self.config.settings.lcm_diffusion_setting.use_seed = False
|
512 |
+
|
513 |
+
def get_seed_value(self) -> int:
|
514 |
+
use_seed = self.config.settings.lcm_diffusion_setting.use_seed
|
515 |
+
seed_value = int(self.seed_value.text()) if use_seed else -1
|
516 |
+
return seed_value
|
517 |
+
|
518 |
+
def generate_image(self):
|
519 |
+
self.config.settings.lcm_diffusion_setting.seed = self.get_seed_value()
|
520 |
+
self.config.settings.lcm_diffusion_setting.prompt = self.prompt.toPlainText()
|
521 |
+
self.config.settings.lcm_diffusion_setting.negative_prompt = (
|
522 |
+
self.neg_prompt.toPlainText()
|
523 |
+
)
|
524 |
+
self.config.settings.lcm_diffusion_setting.lcm_lora.lcm_lora_id = (
|
525 |
+
self.lcm_lora_id.currentText()
|
526 |
+
)
|
527 |
+
self.config.settings.lcm_diffusion_setting.lcm_lora.base_model_id = (
|
528 |
+
self.base_model_id.currentText()
|
529 |
+
)
|
530 |
+
|
531 |
+
if self.config.settings.lcm_diffusion_setting.use_openvino:
|
532 |
+
model_id = self.openvino_lcm_model_id.currentText()
|
533 |
+
else:
|
534 |
+
model_id = self.lcm_model.currentText()
|
535 |
+
|
536 |
+
self.config.settings.lcm_diffusion_setting.lcm_model_id = model_id
|
537 |
+
|
538 |
+
reshape_required = False
|
539 |
+
if self.config.settings.lcm_diffusion_setting.use_openvino:
|
540 |
+
# Detect dimension change
|
541 |
+
reshape_required = is_reshape_required(
|
542 |
+
self.previous_width,
|
543 |
+
self.config.settings.lcm_diffusion_setting.image_width,
|
544 |
+
self.previous_height,
|
545 |
+
self.config.settings.lcm_diffusion_setting.image_height,
|
546 |
+
self.previous_model,
|
547 |
+
model_id,
|
548 |
+
self.previous_num_of_images,
|
549 |
+
self.config.settings.lcm_diffusion_setting.number_of_images,
|
550 |
+
)
|
551 |
+
self.config.settings.lcm_diffusion_setting.diffusion_task = (
|
552 |
+
DiffusionTask.text_to_image.value
|
553 |
+
)
|
554 |
+
images = self.context.generate_text_to_image(
|
555 |
+
self.config.settings,
|
556 |
+
reshape_required,
|
557 |
+
DEVICE,
|
558 |
+
)
|
559 |
+
self.image_index = 0
|
560 |
+
self.gen_images = []
|
561 |
+
for img in images:
|
562 |
+
im = ImageQt(img).copy()
|
563 |
+
pixmap = QPixmap.fromImage(im)
|
564 |
+
self.gen_images.append(pixmap)
|
565 |
+
|
566 |
+
if len(self.gen_images) > 1:
|
567 |
+
self.next_img_btn.setEnabled(True)
|
568 |
+
self.previous_img_btn.setEnabled(False)
|
569 |
+
else:
|
570 |
+
self.next_img_btn.setEnabled(False)
|
571 |
+
self.previous_img_btn.setEnabled(False)
|
572 |
+
|
573 |
+
self.show_image(self.gen_images[0])
|
574 |
+
|
575 |
+
self.previous_width = self.config.settings.lcm_diffusion_setting.image_width
|
576 |
+
self.previous_height = self.config.settings.lcm_diffusion_setting.image_height
|
577 |
+
self.previous_model = model_id
|
578 |
+
self.previous_num_of_images = (
|
579 |
+
self.config.settings.lcm_diffusion_setting.number_of_images
|
580 |
+
)
|
581 |
+
|
582 |
+
def text_to_image(self):
|
583 |
+
self.img.setText("Please wait...")
|
584 |
+
worker = ImageGeneratorWorker(self.generate_image)
|
585 |
+
self.threadpool.start(worker)
|
586 |
+
|
587 |
+
def closeEvent(self, event):
|
588 |
+
self.config.settings.lcm_diffusion_setting.seed = self.get_seed_value()
|
589 |
+
print(self.config.settings.lcm_diffusion_setting)
|
590 |
+
print("Saving settings")
|
591 |
+
self.config.save()
|
592 |
+
|
593 |
+
def reset_all_settings(self):
|
594 |
+
self.use_local_model_folder.setChecked(False)
|
595 |
+
self.width.setCurrentText("512")
|
596 |
+
self.height.setCurrentText("512")
|
597 |
+
self.inference_steps.setValue(4)
|
598 |
+
self.guidance.setValue(10)
|
599 |
+
self.use_openvino_check.setChecked(False)
|
600 |
+
self.seed_check.setChecked(False)
|
601 |
+
self.safety_checker.setChecked(False)
|
602 |
+
self.results_path.setText(FastStableDiffusionPaths().get_results_path())
|
603 |
+
self.use_tae_sd.setChecked(False)
|
604 |
+
self.use_lcm_lora.setChecked(False)
|
frontend/gui/image_generator_worker.py
ADDED
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from PyQt5.QtCore import (
|
2 |
+
pyqtSlot,
|
3 |
+
QRunnable,
|
4 |
+
pyqtSignal,
|
5 |
+
pyqtSlot,
|
6 |
+
)
|
7 |
+
from PyQt5.QtCore import QObject
|
8 |
+
import traceback
|
9 |
+
import sys
|
10 |
+
|
11 |
+
|
12 |
+
class WorkerSignals(QObject):
|
13 |
+
finished = pyqtSignal()
|
14 |
+
error = pyqtSignal(tuple)
|
15 |
+
result = pyqtSignal(object)
|
16 |
+
|
17 |
+
|
18 |
+
class ImageGeneratorWorker(QRunnable):
|
19 |
+
def __init__(self, fn, *args, **kwargs):
|
20 |
+
super(ImageGeneratorWorker, self).__init__()
|
21 |
+
self.fn = fn
|
22 |
+
self.args = args
|
23 |
+
self.kwargs = kwargs
|
24 |
+
self.signals = WorkerSignals()
|
25 |
+
|
26 |
+
@pyqtSlot()
|
27 |
+
def run(self):
|
28 |
+
try:
|
29 |
+
result = self.fn(*self.args, **self.kwargs)
|
30 |
+
except:
|
31 |
+
traceback.print_exc()
|
32 |
+
exctype, value = sys.exc_info()[:2]
|
33 |
+
self.signals.error.emit((exctype, value, traceback.format_exc()))
|
34 |
+
else:
|
35 |
+
self.signals.result.emit(result)
|
36 |
+
finally:
|
37 |
+
self.signals.finished.emit()
|
frontend/gui/ui.py
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from typing import List
|
2 |
+
from frontend.gui.app_window import MainWindow
|
3 |
+
from PyQt5.QtWidgets import QApplication
|
4 |
+
import sys
|
5 |
+
from app_settings import AppSettings
|
6 |
+
|
7 |
+
|
8 |
+
def start_gui(
|
9 |
+
argv: List[str],
|
10 |
+
app_settings: AppSettings,
|
11 |
+
):
|
12 |
+
app = QApplication(sys.argv)
|
13 |
+
window = MainWindow(app_settings)
|
14 |
+
window.show()
|
15 |
+
app.exec()
|
frontend/utils.py
ADDED
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from constants import DEVICE
|
2 |
+
from typing import List
|
3 |
+
import platform
|
4 |
+
from backend.device import is_openvino_device
|
5 |
+
|
6 |
+
|
7 |
+
def is_reshape_required(
|
8 |
+
prev_width: int,
|
9 |
+
cur_width: int,
|
10 |
+
prev_height: int,
|
11 |
+
cur_height: int,
|
12 |
+
prev_model: int,
|
13 |
+
cur_model: int,
|
14 |
+
prev_num_of_images: int,
|
15 |
+
cur_num_of_images: int,
|
16 |
+
) -> bool:
|
17 |
+
reshape_required = False
|
18 |
+
if (
|
19 |
+
prev_width != cur_width
|
20 |
+
or prev_height != cur_height
|
21 |
+
or prev_model != cur_model
|
22 |
+
or prev_num_of_images != cur_num_of_images
|
23 |
+
):
|
24 |
+
print("Reshape and compile")
|
25 |
+
reshape_required = True
|
26 |
+
|
27 |
+
return reshape_required
|
28 |
+
|
29 |
+
|
30 |
+
def enable_openvino_controls() -> bool:
|
31 |
+
return is_openvino_device() and platform.system().lower() != "darwin"
|
32 |
+
|
33 |
+
|
34 |
+
def get_valid_model_id(
|
35 |
+
models: List,
|
36 |
+
model_id: str,
|
37 |
+
default_model: str = "",
|
38 |
+
) -> str:
|
39 |
+
if len(models) == 0:
|
40 |
+
print("Error: model configuration file is empty,please add some models.")
|
41 |
+
return ""
|
42 |
+
if model_id == "":
|
43 |
+
if default_model:
|
44 |
+
return default_model
|
45 |
+
else:
|
46 |
+
return models[0]
|
47 |
+
|
48 |
+
if model_id in models:
|
49 |
+
return model_id
|
50 |
+
else:
|
51 |
+
print(
|
52 |
+
f"Error:{model_id} Model not found in configuration file,so using first model : {models[0]}"
|
53 |
+
)
|
54 |
+
return models[0]
|
frontend/webui/css/style.css
ADDED
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
footer {
|
2 |
+
visibility: hidden
|
3 |
+
}
|
4 |
+
|
5 |
+
#generate_button {
|
6 |
+
color: white;
|
7 |
+
border-color: #007bff;
|
8 |
+
background: #2563eb;
|
9 |
+
|
10 |
+
}
|
11 |
+
|
12 |
+
#save_button {
|
13 |
+
color: white;
|
14 |
+
border-color: #028b40;
|
15 |
+
background: #01b97c;
|
16 |
+
width: 200px;
|
17 |
+
}
|
18 |
+
|
19 |
+
#settings_header {
|
20 |
+
background: rgb(245, 105, 105);
|
21 |
+
|
22 |
+
}
|
frontend/webui/generation_settings_ui.py
ADDED
@@ -0,0 +1,140 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
from state import get_settings
|
3 |
+
|
4 |
+
app_settings = get_settings()
|
5 |
+
|
6 |
+
|
7 |
+
def on_change_inference_steps(steps):
|
8 |
+
app_settings.settings.lcm_diffusion_setting.inference_steps = steps
|
9 |
+
|
10 |
+
|
11 |
+
def on_change_image_width(img_width):
|
12 |
+
app_settings.settings.lcm_diffusion_setting.image_width = img_width
|
13 |
+
|
14 |
+
|
15 |
+
def on_change_image_height(img_height):
|
16 |
+
app_settings.settings.lcm_diffusion_setting.image_height = img_height
|
17 |
+
|
18 |
+
|
19 |
+
def on_change_num_images(num_images):
|
20 |
+
app_settings.settings.lcm_diffusion_setting.number_of_images = num_images
|
21 |
+
|
22 |
+
|
23 |
+
def on_change_guidance_scale(guidance_scale):
|
24 |
+
app_settings.settings.lcm_diffusion_setting.guidance_scale = guidance_scale
|
25 |
+
|
26 |
+
|
27 |
+
def on_change_seed_value(seed):
|
28 |
+
app_settings.settings.lcm_diffusion_setting.seed = seed
|
29 |
+
|
30 |
+
|
31 |
+
def on_change_seed_checkbox(seed_checkbox):
|
32 |
+
app_settings.settings.lcm_diffusion_setting.use_seed = seed_checkbox
|
33 |
+
|
34 |
+
|
35 |
+
def on_change_safety_checker_checkbox(safety_checker_checkbox):
|
36 |
+
app_settings.settings.lcm_diffusion_setting.use_safety_checker = (
|
37 |
+
safety_checker_checkbox
|
38 |
+
)
|
39 |
+
|
40 |
+
|
41 |
+
def on_change_tiny_auto_encoder_checkbox(tiny_auto_encoder_checkbox):
|
42 |
+
app_settings.settings.lcm_diffusion_setting.use_tiny_auto_encoder = (
|
43 |
+
tiny_auto_encoder_checkbox
|
44 |
+
)
|
45 |
+
|
46 |
+
|
47 |
+
def on_offline_checkbox(offline_checkbox):
|
48 |
+
app_settings.settings.lcm_diffusion_setting.use_offline_model = offline_checkbox
|
49 |
+
|
50 |
+
|
51 |
+
def get_generation_settings_ui() -> None:
|
52 |
+
with gr.Blocks():
|
53 |
+
with gr.Row():
|
54 |
+
with gr.Column():
|
55 |
+
num_inference_steps = gr.Slider(
|
56 |
+
1,
|
57 |
+
25,
|
58 |
+
value=app_settings.settings.lcm_diffusion_setting.inference_steps,
|
59 |
+
step=1,
|
60 |
+
label="Inference Steps",
|
61 |
+
interactive=True,
|
62 |
+
)
|
63 |
+
|
64 |
+
image_height = gr.Slider(
|
65 |
+
256,
|
66 |
+
1024,
|
67 |
+
value=app_settings.settings.lcm_diffusion_setting.image_height,
|
68 |
+
step=256,
|
69 |
+
label="Image Height",
|
70 |
+
interactive=True,
|
71 |
+
)
|
72 |
+
image_width = gr.Slider(
|
73 |
+
256,
|
74 |
+
1024,
|
75 |
+
value=app_settings.settings.lcm_diffusion_setting.image_width,
|
76 |
+
step=256,
|
77 |
+
label="Image Width",
|
78 |
+
interactive=True,
|
79 |
+
)
|
80 |
+
num_images = gr.Slider(
|
81 |
+
1,
|
82 |
+
50,
|
83 |
+
value=app_settings.settings.lcm_diffusion_setting.number_of_images,
|
84 |
+
step=1,
|
85 |
+
label="Number of images to generate",
|
86 |
+
interactive=True,
|
87 |
+
)
|
88 |
+
guidance_scale = gr.Slider(
|
89 |
+
1.0,
|
90 |
+
2.0,
|
91 |
+
value=app_settings.settings.lcm_diffusion_setting.guidance_scale,
|
92 |
+
step=0.1,
|
93 |
+
label="Guidance Scale",
|
94 |
+
interactive=True,
|
95 |
+
)
|
96 |
+
|
97 |
+
seed = gr.Slider(
|
98 |
+
value=app_settings.settings.lcm_diffusion_setting.seed,
|
99 |
+
minimum=0,
|
100 |
+
maximum=999999999,
|
101 |
+
label="Seed",
|
102 |
+
step=1,
|
103 |
+
interactive=True,
|
104 |
+
)
|
105 |
+
seed_checkbox = gr.Checkbox(
|
106 |
+
label="Use seed",
|
107 |
+
value=app_settings.settings.lcm_diffusion_setting.use_seed,
|
108 |
+
interactive=True,
|
109 |
+
)
|
110 |
+
|
111 |
+
safety_checker_checkbox = gr.Checkbox(
|
112 |
+
label="Use Safety Checker",
|
113 |
+
value=app_settings.settings.lcm_diffusion_setting.use_safety_checker,
|
114 |
+
interactive=True,
|
115 |
+
)
|
116 |
+
tiny_auto_encoder_checkbox = gr.Checkbox(
|
117 |
+
label="Use tiny auto encoder for SD",
|
118 |
+
value=app_settings.settings.lcm_diffusion_setting.use_tiny_auto_encoder,
|
119 |
+
interactive=True,
|
120 |
+
)
|
121 |
+
offline_checkbox = gr.Checkbox(
|
122 |
+
label="Use locally cached model or downloaded model folder(offline)",
|
123 |
+
value=app_settings.settings.lcm_diffusion_setting.use_offline_model,
|
124 |
+
interactive=True,
|
125 |
+
)
|
126 |
+
|
127 |
+
num_inference_steps.change(on_change_inference_steps, num_inference_steps)
|
128 |
+
image_height.change(on_change_image_height, image_height)
|
129 |
+
image_width.change(on_change_image_width, image_width)
|
130 |
+
num_images.change(on_change_num_images, num_images)
|
131 |
+
guidance_scale.change(on_change_guidance_scale, guidance_scale)
|
132 |
+
seed.change(on_change_seed_value, seed)
|
133 |
+
seed_checkbox.change(on_change_seed_checkbox, seed_checkbox)
|
134 |
+
safety_checker_checkbox.change(
|
135 |
+
on_change_safety_checker_checkbox, safety_checker_checkbox
|
136 |
+
)
|
137 |
+
tiny_auto_encoder_checkbox.change(
|
138 |
+
on_change_tiny_auto_encoder_checkbox, tiny_auto_encoder_checkbox
|
139 |
+
)
|
140 |
+
offline_checkbox.change(on_offline_checkbox, offline_checkbox)
|
frontend/webui/image_to_image_ui.py
ADDED
@@ -0,0 +1,123 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from typing import Any
|
2 |
+
import gradio as gr
|
3 |
+
from backend.models.lcmdiffusion_setting import DiffusionTask
|
4 |
+
from models.interface_types import InterfaceType
|
5 |
+
from frontend.utils import is_reshape_required
|
6 |
+
from constants import DEVICE
|
7 |
+
from state import get_settings, get_context
|
8 |
+
from concurrent.futures import ThreadPoolExecutor
|
9 |
+
|
10 |
+
app_settings = get_settings()
|
11 |
+
|
12 |
+
context = get_context(InterfaceType.WEBUI)
|
13 |
+
previous_width = 0
|
14 |
+
previous_height = 0
|
15 |
+
previous_model_id = ""
|
16 |
+
previous_num_of_images = 0
|
17 |
+
|
18 |
+
|
19 |
+
def generate_image_to_image(
|
20 |
+
prompt,
|
21 |
+
negative_prompt,
|
22 |
+
init_image,
|
23 |
+
strength,
|
24 |
+
) -> Any:
|
25 |
+
global previous_height, previous_width, previous_model_id, previous_num_of_images, app_settings
|
26 |
+
|
27 |
+
app_settings.settings.lcm_diffusion_setting.prompt = prompt
|
28 |
+
app_settings.settings.lcm_diffusion_setting.negative_prompt = negative_prompt
|
29 |
+
app_settings.settings.lcm_diffusion_setting.init_image = init_image
|
30 |
+
app_settings.settings.lcm_diffusion_setting.strength = strength
|
31 |
+
|
32 |
+
app_settings.settings.lcm_diffusion_setting.diffusion_task = (
|
33 |
+
DiffusionTask.image_to_image.value
|
34 |
+
)
|
35 |
+
model_id = app_settings.settings.lcm_diffusion_setting.openvino_lcm_model_id
|
36 |
+
reshape = False
|
37 |
+
image_width = app_settings.settings.lcm_diffusion_setting.image_width
|
38 |
+
image_height = app_settings.settings.lcm_diffusion_setting.image_height
|
39 |
+
num_images = app_settings.settings.lcm_diffusion_setting.number_of_images
|
40 |
+
if app_settings.settings.lcm_diffusion_setting.use_openvino:
|
41 |
+
reshape = is_reshape_required(
|
42 |
+
previous_width,
|
43 |
+
image_width,
|
44 |
+
previous_height,
|
45 |
+
image_height,
|
46 |
+
previous_model_id,
|
47 |
+
model_id,
|
48 |
+
previous_num_of_images,
|
49 |
+
num_images,
|
50 |
+
)
|
51 |
+
|
52 |
+
with ThreadPoolExecutor(max_workers=1) as executor:
|
53 |
+
future = executor.submit(
|
54 |
+
context.generate_text_to_image,
|
55 |
+
app_settings.settings,
|
56 |
+
reshape,
|
57 |
+
DEVICE,
|
58 |
+
)
|
59 |
+
images = future.result()
|
60 |
+
# images = context.generate_text_to_image(
|
61 |
+
# app_settings.settings,
|
62 |
+
# reshape,
|
63 |
+
# DEVICE,
|
64 |
+
# )
|
65 |
+
previous_width = image_width
|
66 |
+
previous_height = image_height
|
67 |
+
previous_model_id = model_id
|
68 |
+
previous_num_of_images = num_images
|
69 |
+
return images
|
70 |
+
|
71 |
+
|
72 |
+
def get_image_to_image_ui() -> None:
|
73 |
+
with gr.Blocks():
|
74 |
+
with gr.Row():
|
75 |
+
with gr.Column():
|
76 |
+
input_image = gr.Image(label="Init image", type="pil")
|
77 |
+
with gr.Row():
|
78 |
+
prompt = gr.Textbox(
|
79 |
+
show_label=False,
|
80 |
+
lines=3,
|
81 |
+
placeholder="A fantasy landscape",
|
82 |
+
container=False,
|
83 |
+
)
|
84 |
+
|
85 |
+
generate_btn = gr.Button(
|
86 |
+
"Generate",
|
87 |
+
elem_id="generate_button",
|
88 |
+
scale=0,
|
89 |
+
)
|
90 |
+
negative_prompt = gr.Textbox(
|
91 |
+
label="Negative prompt (Works in LCM-LoRA mode, set guidance > 1.0):",
|
92 |
+
lines=1,
|
93 |
+
placeholder="",
|
94 |
+
)
|
95 |
+
strength = gr.Slider(
|
96 |
+
0.1,
|
97 |
+
1,
|
98 |
+
value=app_settings.settings.lcm_diffusion_setting.strength,
|
99 |
+
step=0.01,
|
100 |
+
label="Strength",
|
101 |
+
)
|
102 |
+
|
103 |
+
input_params = [
|
104 |
+
prompt,
|
105 |
+
negative_prompt,
|
106 |
+
input_image,
|
107 |
+
strength,
|
108 |
+
]
|
109 |
+
|
110 |
+
with gr.Column():
|
111 |
+
output = gr.Gallery(
|
112 |
+
label="Generated images",
|
113 |
+
show_label=True,
|
114 |
+
elem_id="gallery",
|
115 |
+
columns=2,
|
116 |
+
height=512,
|
117 |
+
)
|
118 |
+
|
119 |
+
generate_btn.click(
|
120 |
+
fn=generate_image_to_image,
|
121 |
+
inputs=input_params,
|
122 |
+
outputs=output,
|
123 |
+
)
|
frontend/webui/image_variations_ui.py
ADDED
@@ -0,0 +1,105 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from typing import Any
|
2 |
+
import gradio as gr
|
3 |
+
from backend.models.lcmdiffusion_setting import DiffusionTask
|
4 |
+
from context import Context
|
5 |
+
from models.interface_types import InterfaceType
|
6 |
+
from frontend.utils import is_reshape_required
|
7 |
+
from constants import DEVICE
|
8 |
+
from state import get_settings, get_context
|
9 |
+
from concurrent.futures import ThreadPoolExecutor
|
10 |
+
|
11 |
+
app_settings = get_settings()
|
12 |
+
|
13 |
+
context = get_context(InterfaceType.WEBUI)
|
14 |
+
previous_width = 0
|
15 |
+
previous_height = 0
|
16 |
+
previous_model_id = ""
|
17 |
+
previous_num_of_images = 0
|
18 |
+
|
19 |
+
|
20 |
+
def generate_image_variations(
|
21 |
+
init_image,
|
22 |
+
variation_strength,
|
23 |
+
) -> Any:
|
24 |
+
global previous_height, previous_width, previous_model_id, previous_num_of_images, app_settings
|
25 |
+
|
26 |
+
app_settings.settings.lcm_diffusion_setting.init_image = init_image
|
27 |
+
app_settings.settings.lcm_diffusion_setting.strength = variation_strength
|
28 |
+
app_settings.settings.lcm_diffusion_setting.prompt = ""
|
29 |
+
app_settings.settings.lcm_diffusion_setting.negative_prompt = ""
|
30 |
+
|
31 |
+
app_settings.settings.lcm_diffusion_setting.diffusion_task = (
|
32 |
+
DiffusionTask.image_to_image.value
|
33 |
+
)
|
34 |
+
model_id = app_settings.settings.lcm_diffusion_setting.openvino_lcm_model_id
|
35 |
+
reshape = False
|
36 |
+
image_width = app_settings.settings.lcm_diffusion_setting.image_width
|
37 |
+
image_height = app_settings.settings.lcm_diffusion_setting.image_height
|
38 |
+
num_images = app_settings.settings.lcm_diffusion_setting.number_of_images
|
39 |
+
if app_settings.settings.lcm_diffusion_setting.use_openvino:
|
40 |
+
reshape = is_reshape_required(
|
41 |
+
previous_width,
|
42 |
+
image_width,
|
43 |
+
previous_height,
|
44 |
+
image_height,
|
45 |
+
previous_model_id,
|
46 |
+
model_id,
|
47 |
+
previous_num_of_images,
|
48 |
+
num_images,
|
49 |
+
)
|
50 |
+
|
51 |
+
with ThreadPoolExecutor(max_workers=1) as executor:
|
52 |
+
future = executor.submit(
|
53 |
+
context.generate_text_to_image,
|
54 |
+
app_settings.settings,
|
55 |
+
reshape,
|
56 |
+
DEVICE,
|
57 |
+
)
|
58 |
+
images = future.result()
|
59 |
+
|
60 |
+
previous_width = image_width
|
61 |
+
previous_height = image_height
|
62 |
+
previous_model_id = model_id
|
63 |
+
previous_num_of_images = num_images
|
64 |
+
return images
|
65 |
+
|
66 |
+
|
67 |
+
def get_image_variations_ui() -> None:
|
68 |
+
with gr.Blocks():
|
69 |
+
with gr.Row():
|
70 |
+
with gr.Column():
|
71 |
+
input_image = gr.Image(label="Init image", type="pil")
|
72 |
+
with gr.Row():
|
73 |
+
generate_btn = gr.Button(
|
74 |
+
"Generate",
|
75 |
+
elem_id="generate_button",
|
76 |
+
scale=0,
|
77 |
+
)
|
78 |
+
|
79 |
+
variation_strength = gr.Slider(
|
80 |
+
0.1,
|
81 |
+
1,
|
82 |
+
value=0.4,
|
83 |
+
step=0.01,
|
84 |
+
label="Variations Strength",
|
85 |
+
)
|
86 |
+
|
87 |
+
input_params = [
|
88 |
+
input_image,
|
89 |
+
variation_strength,
|
90 |
+
]
|
91 |
+
|
92 |
+
with gr.Column():
|
93 |
+
output = gr.Gallery(
|
94 |
+
label="Generated images",
|
95 |
+
show_label=True,
|
96 |
+
elem_id="gallery",
|
97 |
+
columns=2,
|
98 |
+
height=512,
|
99 |
+
)
|
100 |
+
|
101 |
+
generate_btn.click(
|
102 |
+
fn=generate_image_variations,
|
103 |
+
inputs=input_params,
|
104 |
+
outputs=output,
|
105 |
+
)
|
frontend/webui/models_ui.py
ADDED
@@ -0,0 +1,85 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from app_settings import AppSettings
|
2 |
+
from typing import Any
|
3 |
+
import gradio as gr
|
4 |
+
from constants import LCM_DEFAULT_MODEL, LCM_DEFAULT_MODEL_OPENVINO
|
5 |
+
from state import get_settings
|
6 |
+
from frontend.utils import get_valid_model_id
|
7 |
+
|
8 |
+
app_settings = get_settings()
|
9 |
+
app_settings.settings.lcm_diffusion_setting.openvino_lcm_model_id = get_valid_model_id(
|
10 |
+
app_settings.openvino_lcm_models,
|
11 |
+
app_settings.settings.lcm_diffusion_setting.openvino_lcm_model_id,
|
12 |
+
)
|
13 |
+
|
14 |
+
|
15 |
+
def change_lcm_model_id(model_id):
|
16 |
+
app_settings.settings.lcm_diffusion_setting.lcm_model_id = model_id
|
17 |
+
|
18 |
+
|
19 |
+
def change_lcm_lora_model_id(model_id):
|
20 |
+
app_settings.settings.lcm_diffusion_setting.lcm_lora.lcm_lora_id = model_id
|
21 |
+
|
22 |
+
|
23 |
+
def change_lcm_lora_base_model_id(model_id):
|
24 |
+
app_settings.settings.lcm_diffusion_setting.lcm_lora.base_model_id = model_id
|
25 |
+
|
26 |
+
|
27 |
+
def change_openvino_lcm_model_id(model_id):
|
28 |
+
app_settings.settings.lcm_diffusion_setting.openvino_lcm_model_id = model_id
|
29 |
+
|
30 |
+
|
31 |
+
def get_models_ui() -> None:
|
32 |
+
with gr.Blocks():
|
33 |
+
with gr.Row():
|
34 |
+
lcm_model_id = gr.Dropdown(
|
35 |
+
app_settings.lcm_models,
|
36 |
+
label="LCM model",
|
37 |
+
info="Diffusers LCM model ID",
|
38 |
+
value=get_valid_model_id(
|
39 |
+
app_settings.lcm_models,
|
40 |
+
app_settings.settings.lcm_diffusion_setting.lcm_model_id,
|
41 |
+
LCM_DEFAULT_MODEL,
|
42 |
+
),
|
43 |
+
interactive=True,
|
44 |
+
)
|
45 |
+
with gr.Row():
|
46 |
+
lcm_lora_model_id = gr.Dropdown(
|
47 |
+
app_settings.lcm_lora_models,
|
48 |
+
label="LCM LoRA model",
|
49 |
+
info="Diffusers LCM LoRA model ID",
|
50 |
+
value=get_valid_model_id(
|
51 |
+
app_settings.lcm_lora_models,
|
52 |
+
app_settings.settings.lcm_diffusion_setting.lcm_lora.lcm_lora_id,
|
53 |
+
),
|
54 |
+
interactive=True,
|
55 |
+
)
|
56 |
+
lcm_lora_base_model_id = gr.Dropdown(
|
57 |
+
app_settings.stable_diffsuion_models,
|
58 |
+
label="LCM LoRA base model",
|
59 |
+
info="Diffusers LCM LoRA base model ID",
|
60 |
+
value=get_valid_model_id(
|
61 |
+
app_settings.stable_diffsuion_models,
|
62 |
+
app_settings.settings.lcm_diffusion_setting.lcm_lora.base_model_id,
|
63 |
+
),
|
64 |
+
interactive=True,
|
65 |
+
)
|
66 |
+
with gr.Row():
|
67 |
+
lcm_openvino_model_id = gr.Dropdown(
|
68 |
+
app_settings.openvino_lcm_models,
|
69 |
+
label="LCM OpenVINO model",
|
70 |
+
info="OpenVINO LCM-LoRA fused model ID",
|
71 |
+
value=get_valid_model_id(
|
72 |
+
app_settings.openvino_lcm_models,
|
73 |
+
app_settings.settings.lcm_diffusion_setting.openvino_lcm_model_id,
|
74 |
+
),
|
75 |
+
interactive=True,
|
76 |
+
)
|
77 |
+
|
78 |
+
lcm_model_id.change(change_lcm_model_id, lcm_model_id)
|
79 |
+
lcm_lora_model_id.change(change_lcm_lora_model_id, lcm_lora_model_id)
|
80 |
+
lcm_lora_base_model_id.change(
|
81 |
+
change_lcm_lora_base_model_id, lcm_lora_base_model_id
|
82 |
+
)
|
83 |
+
lcm_openvino_model_id.change(
|
84 |
+
change_openvino_lcm_model_id, lcm_openvino_model_id
|
85 |
+
)
|
frontend/webui/realtime_ui.py
ADDED
@@ -0,0 +1,144 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
from backend.lcm_text_to_image import LCMTextToImage
|
3 |
+
from backend.models.lcmdiffusion_setting import LCMLora, LCMDiffusionSetting
|
4 |
+
from constants import DEVICE, LCM_DEFAULT_MODEL_OPENVINO
|
5 |
+
from time import perf_counter
|
6 |
+
import numpy as np
|
7 |
+
from cv2 import imencode
|
8 |
+
import base64
|
9 |
+
from backend.device import get_device_name
|
10 |
+
from constants import APP_VERSION
|
11 |
+
from backend.device import is_openvino_device
|
12 |
+
|
13 |
+
lcm_text_to_image = LCMTextToImage()
|
14 |
+
lcm_lora = LCMLora(
|
15 |
+
base_model_id="Lykon/dreamshaper-8",
|
16 |
+
lcm_lora_id="latent-consistency/lcm-lora-sdv1-5",
|
17 |
+
)
|
18 |
+
|
19 |
+
|
20 |
+
# https://github.com/gradio-app/gradio/issues/2635#issuecomment-1423531319
|
21 |
+
def encode_pil_to_base64_new(pil_image):
|
22 |
+
image_arr = np.asarray(pil_image)[:, :, ::-1]
|
23 |
+
_, byte_data = imencode(".png", image_arr)
|
24 |
+
base64_data = base64.b64encode(byte_data)
|
25 |
+
base64_string_opencv = base64_data.decode("utf-8")
|
26 |
+
return "data:image/png;base64," + base64_string_opencv
|
27 |
+
|
28 |
+
|
29 |
+
# monkey patching encode pil
|
30 |
+
gr.processing_utils.encode_pil_to_base64 = encode_pil_to_base64_new
|
31 |
+
|
32 |
+
|
33 |
+
def predict(
|
34 |
+
prompt,
|
35 |
+
steps,
|
36 |
+
seed,
|
37 |
+
):
|
38 |
+
lcm_diffusion_setting = LCMDiffusionSetting()
|
39 |
+
lcm_diffusion_setting.openvino_lcm_model_id = "rupeshs/LCM-dreamshaper-v7-openvino"
|
40 |
+
lcm_diffusion_setting.prompt = prompt
|
41 |
+
lcm_diffusion_setting.guidance_scale = 1.0
|
42 |
+
lcm_diffusion_setting.inference_steps = steps
|
43 |
+
lcm_diffusion_setting.seed = seed
|
44 |
+
lcm_diffusion_setting.use_seed = True
|
45 |
+
lcm_diffusion_setting.image_width = 256 if is_openvino_device() else 512
|
46 |
+
lcm_diffusion_setting.image_height = 256 if is_openvino_device() else 512
|
47 |
+
lcm_diffusion_setting.use_openvino = True if is_openvino_device() else False
|
48 |
+
lcm_text_to_image.init(
|
49 |
+
DEVICE,
|
50 |
+
lcm_diffusion_setting,
|
51 |
+
)
|
52 |
+
start = perf_counter()
|
53 |
+
|
54 |
+
images = lcm_text_to_image.generate(lcm_diffusion_setting)
|
55 |
+
latency = perf_counter() - start
|
56 |
+
print(f"Latency: {latency:.2f} seconds")
|
57 |
+
return images[0]
|
58 |
+
|
59 |
+
|
60 |
+
css = """
|
61 |
+
#container{
|
62 |
+
margin: 0 auto;
|
63 |
+
max-width: 40rem;
|
64 |
+
}
|
65 |
+
#intro{
|
66 |
+
max-width: 100%;
|
67 |
+
text-align: center;
|
68 |
+
margin: 0 auto;
|
69 |
+
}
|
70 |
+
#generate_button {
|
71 |
+
color: white;
|
72 |
+
border-color: #007bff;
|
73 |
+
background: #007bff;
|
74 |
+
width: 200px;
|
75 |
+
height: 50px;
|
76 |
+
}
|
77 |
+
footer {
|
78 |
+
visibility: hidden
|
79 |
+
}
|
80 |
+
"""
|
81 |
+
|
82 |
+
|
83 |
+
def _get_footer_message() -> str:
|
84 |
+
version = f"<center><p> {APP_VERSION} "
|
85 |
+
footer_msg = version + (
|
86 |
+
' © 2023 <a href="https://github.com/rupeshs">'
|
87 |
+
" Rupesh Sreeraman</a></p></center>"
|
88 |
+
)
|
89 |
+
return footer_msg
|
90 |
+
|
91 |
+
|
92 |
+
with gr.Blocks(css=css) as demo:
|
93 |
+
with gr.Column(elem_id="container"):
|
94 |
+
use_openvino = "- OpenVINO" if is_openvino_device() else ""
|
95 |
+
gr.Markdown(
|
96 |
+
f"""# Realtime FastSD CPU {use_openvino}
|
97 |
+
**Device : {DEVICE} , {get_device_name()}**
|
98 |
+
""",
|
99 |
+
elem_id="intro",
|
100 |
+
)
|
101 |
+
|
102 |
+
with gr.Row():
|
103 |
+
with gr.Row():
|
104 |
+
prompt = gr.Textbox(
|
105 |
+
placeholder="Describe the image you'd like to see",
|
106 |
+
scale=5,
|
107 |
+
container=False,
|
108 |
+
)
|
109 |
+
generate_btn = gr.Button(
|
110 |
+
"Generate",
|
111 |
+
scale=1,
|
112 |
+
elem_id="generate_button",
|
113 |
+
)
|
114 |
+
|
115 |
+
image = gr.Image(type="filepath")
|
116 |
+
with gr.Accordion("Advanced options", open=False):
|
117 |
+
steps = gr.Slider(
|
118 |
+
label="Steps",
|
119 |
+
value=4 if is_openvino_device() else 3,
|
120 |
+
minimum=1,
|
121 |
+
maximum=6,
|
122 |
+
step=1,
|
123 |
+
)
|
124 |
+
seed = gr.Slider(
|
125 |
+
randomize=True,
|
126 |
+
minimum=0,
|
127 |
+
maximum=999999999,
|
128 |
+
label="Seed",
|
129 |
+
step=1,
|
130 |
+
)
|
131 |
+
gr.HTML(_get_footer_message())
|
132 |
+
|
133 |
+
inputs = [prompt, steps, seed]
|
134 |
+
prompt.input(fn=predict, inputs=inputs, outputs=image, show_progress=False)
|
135 |
+
generate_btn.click(
|
136 |
+
fn=predict, inputs=inputs, outputs=image, show_progress=False
|
137 |
+
)
|
138 |
+
steps.change(fn=predict, inputs=inputs, outputs=image, show_progress=False)
|
139 |
+
seed.change(fn=predict, inputs=inputs, outputs=image, show_progress=False)
|
140 |
+
|
141 |
+
|
142 |
+
def start_realtime_text_to_image(share=False):
|
143 |
+
demo.queue()
|
144 |
+
demo.launch(share=share)
|
frontend/webui/text_to_image_ui.py
ADDED
@@ -0,0 +1,103 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
from typing import Any
|
3 |
+
from backend.models.lcmdiffusion_setting import DiffusionTask
|
4 |
+
from models.interface_types import InterfaceType
|
5 |
+
from constants import DEVICE
|
6 |
+
from state import get_settings, get_context
|
7 |
+
from frontend.utils import is_reshape_required
|
8 |
+
from concurrent.futures import ThreadPoolExecutor
|
9 |
+
from pprint import pprint
|
10 |
+
|
11 |
+
app_settings = get_settings()
|
12 |
+
context = get_context(InterfaceType.WEBUI)
|
13 |
+
previous_width = 0
|
14 |
+
previous_height = 0
|
15 |
+
previous_model_id = ""
|
16 |
+
previous_num_of_images = 0
|
17 |
+
|
18 |
+
|
19 |
+
def generate_text_to_image(
|
20 |
+
prompt,
|
21 |
+
neg_prompt,
|
22 |
+
) -> Any:
|
23 |
+
global previous_height, previous_width, previous_model_id, previous_num_of_images, app_settings
|
24 |
+
app_settings.settings.lcm_diffusion_setting.prompt = prompt
|
25 |
+
app_settings.settings.lcm_diffusion_setting.negative_prompt = neg_prompt
|
26 |
+
app_settings.settings.lcm_diffusion_setting.diffusion_task = (
|
27 |
+
DiffusionTask.text_to_image.value
|
28 |
+
)
|
29 |
+
model_id = app_settings.settings.lcm_diffusion_setting.openvino_lcm_model_id
|
30 |
+
reshape = False
|
31 |
+
image_width = app_settings.settings.lcm_diffusion_setting.image_width
|
32 |
+
image_height = app_settings.settings.lcm_diffusion_setting.image_height
|
33 |
+
num_images = app_settings.settings.lcm_diffusion_setting.number_of_images
|
34 |
+
if app_settings.settings.lcm_diffusion_setting.use_openvino:
|
35 |
+
reshape = is_reshape_required(
|
36 |
+
previous_width,
|
37 |
+
image_width,
|
38 |
+
previous_height,
|
39 |
+
image_height,
|
40 |
+
previous_model_id,
|
41 |
+
model_id,
|
42 |
+
previous_num_of_images,
|
43 |
+
num_images,
|
44 |
+
)
|
45 |
+
|
46 |
+
with ThreadPoolExecutor(max_workers=1) as executor:
|
47 |
+
future = executor.submit(
|
48 |
+
context.generate_text_to_image,
|
49 |
+
app_settings.settings,
|
50 |
+
reshape,
|
51 |
+
DEVICE,
|
52 |
+
)
|
53 |
+
images = future.result()
|
54 |
+
# images = context.generate_text_to_image(
|
55 |
+
# app_settings.settings,
|
56 |
+
# reshape,
|
57 |
+
# DEVICE,
|
58 |
+
# )
|
59 |
+
previous_width = image_width
|
60 |
+
previous_height = image_height
|
61 |
+
previous_model_id = model_id
|
62 |
+
previous_num_of_images = num_images
|
63 |
+
return images
|
64 |
+
|
65 |
+
|
66 |
+
def get_text_to_image_ui() -> None:
|
67 |
+
with gr.Blocks():
|
68 |
+
with gr.Row():
|
69 |
+
with gr.Column():
|
70 |
+
with gr.Row():
|
71 |
+
prompt = gr.Textbox(
|
72 |
+
show_label=False,
|
73 |
+
lines=3,
|
74 |
+
placeholder="A fantasy landscape",
|
75 |
+
container=False,
|
76 |
+
)
|
77 |
+
|
78 |
+
generate_btn = gr.Button(
|
79 |
+
"Generate",
|
80 |
+
elem_id="generate_button",
|
81 |
+
scale=0,
|
82 |
+
)
|
83 |
+
negative_prompt = gr.Textbox(
|
84 |
+
label="Negative prompt (Works in LCM-LoRA mode, set guidance > 1.0) :",
|
85 |
+
lines=1,
|
86 |
+
placeholder="",
|
87 |
+
)
|
88 |
+
|
89 |
+
input_params = [prompt, negative_prompt]
|
90 |
+
|
91 |
+
with gr.Column():
|
92 |
+
output = gr.Gallery(
|
93 |
+
label="Generated images",
|
94 |
+
show_label=True,
|
95 |
+
elem_id="gallery",
|
96 |
+
columns=2,
|
97 |
+
height=512,
|
98 |
+
)
|
99 |
+
generate_btn.click(
|
100 |
+
fn=generate_text_to_image,
|
101 |
+
inputs=input_params,
|
102 |
+
outputs=output,
|
103 |
+
)
|
frontend/webui/ui.py
ADDED
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
from constants import APP_VERSION
|
3 |
+
from frontend.webui.text_to_image_ui import get_text_to_image_ui
|
4 |
+
from frontend.webui.image_to_image_ui import get_image_to_image_ui
|
5 |
+
from frontend.webui.generation_settings_ui import get_generation_settings_ui
|
6 |
+
from frontend.webui.models_ui import get_models_ui
|
7 |
+
from frontend.webui.image_variations_ui import get_image_variations_ui
|
8 |
+
from paths import FastStableDiffusionPaths
|
9 |
+
from state import get_settings
|
10 |
+
|
11 |
+
app_settings = get_settings()
|
12 |
+
|
13 |
+
|
14 |
+
def _get_footer_message() -> str:
|
15 |
+
version = f"<center><p> {APP_VERSION} "
|
16 |
+
footer_msg = version + (
|
17 |
+
' © 2023 <a href="https://github.com/rupeshs">'
|
18 |
+
" Rupesh Sreeraman</a></p></center>"
|
19 |
+
)
|
20 |
+
return footer_msg
|
21 |
+
|
22 |
+
|
23 |
+
def get_web_ui() -> gr.Blocks:
|
24 |
+
def change_mode(mode):
|
25 |
+
global app_settings
|
26 |
+
app_settings.settings.lcm_diffusion_setting.use_lcm_lora = False
|
27 |
+
app_settings.settings.lcm_diffusion_setting.use_openvino = False
|
28 |
+
if mode == "LCM-LoRA":
|
29 |
+
app_settings.settings.lcm_diffusion_setting.use_lcm_lora = True
|
30 |
+
elif mode == "LCM-OpenVINO":
|
31 |
+
app_settings.settings.lcm_diffusion_setting.use_openvino = True
|
32 |
+
|
33 |
+
with gr.Blocks(
|
34 |
+
css=FastStableDiffusionPaths.get_css_path(),
|
35 |
+
title="FastSD CPU",
|
36 |
+
) as fastsd_web_ui:
|
37 |
+
gr.HTML("<center><H1>FastSD CPU</H1></center>")
|
38 |
+
current_mode = "LCM"
|
39 |
+
if app_settings.settings.lcm_diffusion_setting.use_openvino:
|
40 |
+
current_mode = "LCM-OpenVINO"
|
41 |
+
elif app_settings.settings.lcm_diffusion_setting.use_lcm_lora:
|
42 |
+
current_mode = "LCM-LoRA"
|
43 |
+
|
44 |
+
mode = gr.Radio(
|
45 |
+
["LCM", "LCM-LoRA", "LCM-OpenVINO"],
|
46 |
+
label="Mode",
|
47 |
+
info="Current working mode",
|
48 |
+
value=current_mode,
|
49 |
+
)
|
50 |
+
mode.change(change_mode, inputs=mode)
|
51 |
+
|
52 |
+
with gr.Tabs():
|
53 |
+
with gr.TabItem("Text to Image"):
|
54 |
+
get_text_to_image_ui()
|
55 |
+
with gr.TabItem("Image to Image"):
|
56 |
+
get_image_to_image_ui()
|
57 |
+
with gr.TabItem("Image Variations"):
|
58 |
+
get_image_variations_ui()
|
59 |
+
with gr.TabItem("Generation Settings"):
|
60 |
+
get_generation_settings_ui()
|
61 |
+
with gr.TabItem("Models"):
|
62 |
+
get_models_ui()
|
63 |
+
|
64 |
+
gr.HTML(_get_footer_message())
|
65 |
+
|
66 |
+
return fastsd_web_ui
|
67 |
+
|
68 |
+
|
69 |
+
def start_webui(
|
70 |
+
share: bool = False,
|
71 |
+
):
|
72 |
+
webui = get_web_ui()
|
73 |
+
webui.launch(share=share)
|
image_ops.py
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from PIL import Image
|
2 |
+
|
3 |
+
|
4 |
+
def resize_pil_image(
|
5 |
+
pil_image: Image,
|
6 |
+
image_width,
|
7 |
+
image_height,
|
8 |
+
):
|
9 |
+
return pil_image.convert("RGB").resize(
|
10 |
+
(
|
11 |
+
image_width,
|
12 |
+
image_height,
|
13 |
+
),
|
14 |
+
Image.Resampling.LANCZOS,
|
15 |
+
)
|
main.py
CHANGED
@@ -1,3 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
|
2 |
from fastapi import FastAPI,Body
|
3 |
|
@@ -6,26 +17,187 @@ import json
|
|
6 |
import logging
|
7 |
from PIL import Image
|
8 |
import time
|
9 |
-
|
10 |
-
from model import get_pipeline
|
11 |
-
from utils import replace_background
|
12 |
from diffusers.utils import load_image
|
13 |
import base64
|
14 |
import io
|
15 |
from datetime import datetime
|
16 |
|
17 |
-
|
18 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
|
20 |
-
|
21 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
@app.get("/")
|
23 |
def root():
|
24 |
-
return {"API": "
|
25 |
-
|
26 |
@app.post("/img2img")
|
27 |
-
async def predict(prompt=Body(...),imgbase64data=Body(...),userId=Body(None)):
|
28 |
-
pipeline = get_pipeline()
|
29 |
MAX_QUEUE_SIZE = 4
|
30 |
start = time.time()
|
31 |
print("参数",imgbase64data,prompt)
|
@@ -40,17 +212,47 @@ async def predict(prompt=Body(...),imgbase64data=Body(...),userId=Body(None)):
|
|
40 |
print(now)
|
41 |
print("图像:", img.size)
|
42 |
print("加载管道:", end1 - start)
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
52 |
)
|
53 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
54 |
end2 = time.time()
|
55 |
print("测试",output_image)
|
56 |
print("s生成完成:", end2 - end1)
|
@@ -64,12 +266,9 @@ async def predict(prompt=Body(...),imgbase64data=Body(...),userId=Body(None)):
|
|
64 |
image_data_bytes = image_data.getvalue()
|
65 |
output_image_base64 = base64.b64encode(image_data_bytes).decode('utf-8')
|
66 |
print("完成的图片:", output_image_base64)
|
67 |
-
logger = logging.getLogger('')
|
68 |
-
logger.info(output_image_base64)
|
69 |
return output_image_base64
|
70 |
|
71 |
|
72 |
@app.post("/predict")
|
73 |
async def predict(prompt=Body(...)):
|
74 |
return f"您好,{prompt}"
|
75 |
-
|
|
|
1 |
+
from app_settings import AppSettings
|
2 |
+
from utils import show_system_info
|
3 |
+
import constants
|
4 |
+
from argparse import ArgumentParser
|
5 |
+
from context import Context
|
6 |
+
from constants import APP_VERSION, LCM_DEFAULT_MODEL_OPENVINO
|
7 |
+
from models.interface_types import InterfaceType
|
8 |
+
from constants import DEVICE
|
9 |
+
from state import get_settings
|
10 |
+
import traceback
|
11 |
+
|
12 |
|
13 |
from fastapi import FastAPI,Body
|
14 |
|
|
|
17 |
import logging
|
18 |
from PIL import Image
|
19 |
import time
|
20 |
+
|
|
|
|
|
21 |
from diffusers.utils import load_image
|
22 |
import base64
|
23 |
import io
|
24 |
from datetime import datetime
|
25 |
|
26 |
+
from typing import Any
|
27 |
+
from backend.models.lcmdiffusion_setting import DiffusionTask
|
28 |
+
|
29 |
+
from frontend.utils import is_reshape_required
|
30 |
+
from concurrent.futures import ThreadPoolExecutor
|
31 |
+
|
32 |
+
|
33 |
+
context = Context(InterfaceType.WEBUI)
|
34 |
+
previous_width = 0
|
35 |
+
previous_height = 0
|
36 |
+
previous_model_id = ""
|
37 |
+
previous_num_of_images = 0
|
38 |
+
|
39 |
+
parser = ArgumentParser(description=f"FAST SD CPU {constants.APP_VERSION}")
|
40 |
+
parser.add_argument(
|
41 |
+
"-s",
|
42 |
+
"--share",
|
43 |
+
action="store_true",
|
44 |
+
help="Create sharable link(Web UI)",
|
45 |
+
required=False,
|
46 |
+
)
|
47 |
+
group = parser.add_mutually_exclusive_group(required=False)
|
48 |
+
group.add_argument(
|
49 |
+
"-g",
|
50 |
+
"--gui",
|
51 |
+
action="store_true",
|
52 |
+
help="Start desktop GUI",
|
53 |
+
)
|
54 |
+
group.add_argument(
|
55 |
+
"-w",
|
56 |
+
"--webui",
|
57 |
+
action="store_true",
|
58 |
+
help="Start Web UI",
|
59 |
+
)
|
60 |
+
group.add_argument(
|
61 |
+
"-r",
|
62 |
+
"--realtime",
|
63 |
+
action="store_true",
|
64 |
+
help="Start realtime inference UI(experimental)",
|
65 |
+
)
|
66 |
+
group.add_argument(
|
67 |
+
"-v",
|
68 |
+
"--version",
|
69 |
+
action="store_true",
|
70 |
+
help="Version",
|
71 |
+
)
|
72 |
+
parser.add_argument(
|
73 |
+
"--lcm_model_id",
|
74 |
+
type=str,
|
75 |
+
help="Model ID or path,Default SimianLuo/LCM_Dreamshaper_v7",
|
76 |
+
default="SimianLuo/LCM_Dreamshaper_v7",
|
77 |
+
)
|
78 |
+
parser.add_argument(
|
79 |
+
"--prompt",
|
80 |
+
type=str,
|
81 |
+
help="Describe the image you want to generate",
|
82 |
+
)
|
83 |
+
parser.add_argument(
|
84 |
+
"--image_height",
|
85 |
+
type=int,
|
86 |
+
help="Height of the image",
|
87 |
+
default=512,
|
88 |
+
)
|
89 |
+
parser.add_argument(
|
90 |
+
"--image_width",
|
91 |
+
type=int,
|
92 |
+
help="Width of the image",
|
93 |
+
default=512,
|
94 |
+
)
|
95 |
+
parser.add_argument(
|
96 |
+
"--inference_steps",
|
97 |
+
type=int,
|
98 |
+
help="Number of steps,default : 4",
|
99 |
+
default=4,
|
100 |
+
)
|
101 |
+
parser.add_argument(
|
102 |
+
"--guidance_scale",
|
103 |
+
type=int,
|
104 |
+
help="Guidance scale,default : 1.0",
|
105 |
+
default=1.0,
|
106 |
+
)
|
107 |
+
|
108 |
+
parser.add_argument(
|
109 |
+
"--number_of_images",
|
110 |
+
type=int,
|
111 |
+
help="Number of images to generate ,default : 1",
|
112 |
+
default=1,
|
113 |
+
)
|
114 |
+
parser.add_argument(
|
115 |
+
"--seed",
|
116 |
+
type=int,
|
117 |
+
help="Seed,default : -1 (disabled) ",
|
118 |
+
default=-1,
|
119 |
+
)
|
120 |
+
parser.add_argument(
|
121 |
+
"--use_openvino",
|
122 |
+
action="store_true",
|
123 |
+
help="Use OpenVINO model",
|
124 |
+
)
|
125 |
+
|
126 |
+
parser.add_argument(
|
127 |
+
"--use_offline_model",
|
128 |
+
action="store_true",
|
129 |
+
help="Use offline model",
|
130 |
+
)
|
131 |
+
parser.add_argument(
|
132 |
+
"--use_safety_checker",
|
133 |
+
action="store_false",
|
134 |
+
help="Use safety checker",
|
135 |
+
)
|
136 |
+
parser.add_argument(
|
137 |
+
"--use_lcm_lora",
|
138 |
+
action="store_true",
|
139 |
+
help="Use LCM-LoRA",
|
140 |
+
)
|
141 |
+
parser.add_argument(
|
142 |
+
"--base_model_id",
|
143 |
+
type=str,
|
144 |
+
help="LCM LoRA base model ID,Default Lykon/dreamshaper-8",
|
145 |
+
default="Lykon/dreamshaper-8",
|
146 |
+
)
|
147 |
+
parser.add_argument(
|
148 |
+
"--lcm_lora_id",
|
149 |
+
type=str,
|
150 |
+
help="LCM LoRA model ID,Default latent-consistency/lcm-lora-sdv1-5",
|
151 |
+
default="latent-consistency/lcm-lora-sdv1-5",
|
152 |
+
)
|
153 |
+
parser.add_argument(
|
154 |
+
"-i",
|
155 |
+
"--interactive",
|
156 |
+
action="store_true",
|
157 |
+
help="Interactive CLI mode",
|
158 |
+
)
|
159 |
+
parser.add_argument(
|
160 |
+
"--use_tiny_auto_encoder",
|
161 |
+
action="store_true",
|
162 |
+
help="Use tiny auto encoder for SD (TAESD)",
|
163 |
+
)
|
164 |
+
args = parser.parse_args()
|
165 |
+
|
166 |
+
if args.version:
|
167 |
+
print(APP_VERSION)
|
168 |
+
exit()
|
169 |
+
|
170 |
+
# parser.print_help()
|
171 |
+
show_system_info()
|
172 |
+
print(f"Using device : {constants.DEVICE}")
|
173 |
+
app_settings = get_settings()
|
174 |
|
175 |
+
print(f"Found {len(app_settings.lcm_models)} LCM models in config/lcm-models.txt")
|
176 |
+
print(
|
177 |
+
f"Found {len(app_settings.stable_diffsuion_models)} stable diffusion models in config/stable-diffusion-models.txt"
|
178 |
+
)
|
179 |
+
print(
|
180 |
+
f"Found {len(app_settings.lcm_lora_models)} LCM-LoRA models in config/lcm-lora-models.txt"
|
181 |
+
)
|
182 |
+
print(
|
183 |
+
f"Found {len(app_settings.openvino_lcm_models)} OpenVINO LCM models in config/openvino-lcm-models.txt"
|
184 |
+
)
|
185 |
+
app_settings.settings.lcm_diffusion_setting.use_openvino = True
|
186 |
+
# from frontend.webui.ui import start_webui
|
187 |
+
|
188 |
+
# print("Starting web UI mode")
|
189 |
+
# start_webui(
|
190 |
+
# args.share,
|
191 |
+
# )
|
192 |
+
|
193 |
+
app = FastAPI(name="mutilParam")
|
194 |
+
print("我执行了")
|
195 |
@app.get("/")
|
196 |
def root():
|
197 |
+
return {"API": "hello"}
|
198 |
+
|
199 |
@app.post("/img2img")
|
200 |
+
async def predict(prompt=Body(...),imgbase64data=Body(...),negative_prompt=Body(None),userId=Body(None)):
|
|
|
201 |
MAX_QUEUE_SIZE = 4
|
202 |
start = time.time()
|
203 |
print("参数",imgbase64data,prompt)
|
|
|
212 |
print(now)
|
213 |
print("图像:", img.size)
|
214 |
print("加载管道:", end1 - start)
|
215 |
+
global previous_height, previous_width, previous_model_id, previous_num_of_images, app_settings
|
216 |
+
|
217 |
+
app_settings.settings.lcm_diffusion_setting.prompt = prompt
|
218 |
+
app_settings.settings.lcm_diffusion_setting.negative_prompt = negative_prompt
|
219 |
+
app_settings.settings.lcm_diffusion_setting.init_image = img
|
220 |
+
app_settings.settings.lcm_diffusion_setting.strength = 0.6
|
221 |
+
|
222 |
+
app_settings.settings.lcm_diffusion_setting.diffusion_task = (
|
223 |
+
DiffusionTask.image_to_image.value
|
224 |
+
)
|
225 |
+
model_id = app_settings.settings.lcm_diffusion_setting.openvino_lcm_model_id
|
226 |
+
reshape = False
|
227 |
+
app_settings.settings.lcm_diffusion_setting.image_height=newH
|
228 |
+
image_width = app_settings.settings.lcm_diffusion_setting.image_width
|
229 |
+
image_height = app_settings.settings.lcm_diffusion_setting.image_height
|
230 |
+
num_images = app_settings.settings.lcm_diffusion_setting.number_of_images
|
231 |
+
reshape = is_reshape_required(
|
232 |
+
previous_width,
|
233 |
+
image_width,
|
234 |
+
previous_height,
|
235 |
+
image_height,
|
236 |
+
previous_model_id,
|
237 |
+
model_id,
|
238 |
+
previous_num_of_images,
|
239 |
+
num_images,
|
240 |
)
|
241 |
+
|
242 |
+
|
243 |
+
with ThreadPoolExecutor(max_workers=1) as executor:
|
244 |
+
future = executor.submit(
|
245 |
+
context.generate_text_to_image,
|
246 |
+
app_settings.settings,
|
247 |
+
reshape,
|
248 |
+
DEVICE,
|
249 |
+
)
|
250 |
+
images = future.result()
|
251 |
+
previous_width = image_width
|
252 |
+
previous_height = image_height
|
253 |
+
previous_model_id = model_id
|
254 |
+
previous_num_of_images = num_images
|
255 |
+
output_image = images[0]
|
256 |
end2 = time.time()
|
257 |
print("测试",output_image)
|
258 |
print("s生成完成:", end2 - end1)
|
|
|
266 |
image_data_bytes = image_data.getvalue()
|
267 |
output_image_base64 = base64.b64encode(image_data_bytes).decode('utf-8')
|
268 |
print("完成的图片:", output_image_base64)
|
|
|
|
|
269 |
return output_image_base64
|
270 |
|
271 |
|
272 |
@app.post("/predict")
|
273 |
async def predict(prompt=Body(...)):
|
274 |
return f"您好,{prompt}"
|
|
models/interface_types.py
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from enum import Enum
|
2 |
+
|
3 |
+
|
4 |
+
class InterfaceType(Enum):
|
5 |
+
WEBUI = "Web User Interface"
|
6 |
+
GUI = "Graphical User Interface"
|
7 |
+
CLI = "Command Line Interface"
|
models/settings.py
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from pydantic import BaseModel
|
2 |
+
from backend.models.lcmdiffusion_setting import LCMDiffusionSetting, LCMLora
|
3 |
+
from paths import FastStableDiffusionPaths
|
4 |
+
|
5 |
+
|
6 |
+
class Settings(BaseModel):
|
7 |
+
results_path: str = FastStableDiffusionPaths().get_results_path()
|
8 |
+
lcm_diffusion_setting: LCMDiffusionSetting = LCMDiffusionSetting(lcm_lora=LCMLora())
|
paths.py
ADDED
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import constants
|
3 |
+
|
4 |
+
|
5 |
+
def join_paths(
|
6 |
+
first_path: str,
|
7 |
+
second_path: str,
|
8 |
+
) -> str:
|
9 |
+
return os.path.join(first_path, second_path)
|
10 |
+
|
11 |
+
|
12 |
+
def get_app_path() -> str:
|
13 |
+
app_dir = os.path.dirname(__file__)
|
14 |
+
work_dir = os.path.dirname(app_dir)+'/app/'
|
15 |
+
return work_dir
|
16 |
+
|
17 |
+
|
18 |
+
def get_configs_path() -> str:
|
19 |
+
config_path = join_paths(get_app_path(), constants.CONFIG_DIRECTORY)
|
20 |
+
return config_path
|
21 |
+
|
22 |
+
|
23 |
+
class FastStableDiffusionPaths:
|
24 |
+
@staticmethod
|
25 |
+
def get_app_settings_path() -> str:
|
26 |
+
configs_path = get_configs_path()
|
27 |
+
settings_path = join_paths(
|
28 |
+
configs_path,
|
29 |
+
constants.APP_SETTINGS_FILE,
|
30 |
+
)
|
31 |
+
return settings_path
|
32 |
+
|
33 |
+
@staticmethod
|
34 |
+
def get_results_path() -> str:
|
35 |
+
results_path = join_paths(get_app_path(), constants.RESULTS_DIRECTORY)
|
36 |
+
return results_path
|
37 |
+
|
38 |
+
@staticmethod
|
39 |
+
def get_css_path() -> str:
|
40 |
+
app_dir = os.path.dirname(__file__)
|
41 |
+
css_path = os.path.join(
|
42 |
+
app_dir,
|
43 |
+
"frontend",
|
44 |
+
"webui",
|
45 |
+
"css",
|
46 |
+
"style.css",
|
47 |
+
)
|
48 |
+
return css_path
|
49 |
+
|
50 |
+
@staticmethod
|
51 |
+
def get_models_config_path(model_config_file: str) -> str:
|
52 |
+
configs_path = get_configs_path()
|
53 |
+
models_path = join_paths(
|
54 |
+
configs_path,
|
55 |
+
model_config_file,
|
56 |
+
)
|
57 |
+
return models_path
|
58 |
+
|
59 |
+
|
60 |
+
def get_base_folder_name(path: str) -> str:
|
61 |
+
return os.path.basename(path)
|
requirements.txt
CHANGED
@@ -1,6 +1,18 @@
|
|
1 |
fastapi[all]
|
2 |
uvicorn[standard]
|
3 |
-
accelerate
|
4 |
-
diffusers
|
5 |
-
transformers
|
6 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
fastapi[all]
|
2 |
uvicorn[standard]
|
3 |
+
accelerate==0.23.0
|
4 |
+
diffusers==0.23.0
|
5 |
+
transformers==4.35.0
|
6 |
+
PyQt5
|
7 |
+
Pillow==9.4.0
|
8 |
+
openvino==2023.2.0
|
9 |
+
optimum==1.14.0
|
10 |
+
optimum-intel==1.12.1
|
11 |
+
onnx==1.15.0
|
12 |
+
onnxruntime==1.16.1
|
13 |
+
pydantic==2.4.2
|
14 |
+
typing-extensions==4.8.0
|
15 |
+
pyyaml==6.0.1
|
16 |
+
gradio==3.39.0
|
17 |
+
peft==0.6.1
|
18 |
+
opencv-python==4.8.1.78
|
state.py
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from app_settings import AppSettings
|
2 |
+
from typing import Optional
|
3 |
+
|
4 |
+
from context import Context
|
5 |
+
from models.interface_types import InterfaceType
|
6 |
+
|
7 |
+
|
8 |
+
class _AppState:
|
9 |
+
_instance: Optional["_AppState"] = None
|
10 |
+
settings: Optional[AppSettings] = None
|
11 |
+
context: Optional[Context] = None
|
12 |
+
|
13 |
+
|
14 |
+
def get_state() -> _AppState:
|
15 |
+
if _AppState._instance is None:
|
16 |
+
_AppState._instance = _AppState()
|
17 |
+
return _AppState._instance
|
18 |
+
|
19 |
+
|
20 |
+
def get_settings(skip_file: bool = False) -> AppSettings:
|
21 |
+
state = get_state()
|
22 |
+
if state.settings is None:
|
23 |
+
state.settings = AppSettings()
|
24 |
+
state.settings.load(skip_file)
|
25 |
+
return state.settings
|
26 |
+
|
27 |
+
|
28 |
+
def get_context(interface_type: InterfaceType) -> Context:
|
29 |
+
state = get_state()
|
30 |
+
if state.context is None:
|
31 |
+
state.context = Context(interface_type)
|
32 |
+
return state.context
|
utils.py
CHANGED
@@ -1,15 +1,21 @@
|
|
1 |
-
|
2 |
-
|
3 |
|
4 |
|
5 |
-
def
|
6 |
-
|
|
|
|
|
|
|
|
|
|
|
7 |
|
8 |
-
white_threshold = 255 * 3
|
9 |
-
white_pixels = np.sum(image_np, axis=-1) == white_threshold
|
10 |
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
|
|
|
|
|
|
|
1 |
+
import platform
|
2 |
+
from typing import List
|
3 |
|
4 |
|
5 |
+
def show_system_info():
|
6 |
+
try:
|
7 |
+
print(f"Running on {platform.system()} platform")
|
8 |
+
print(f"OS: {platform.platform()}")
|
9 |
+
print(f"Processor: {platform.processor()}")
|
10 |
+
except Exception as ex:
|
11 |
+
print(f"Error ocurred while getting system information {ex}")
|
12 |
|
|
|
|
|
13 |
|
14 |
+
def get_models_from_text_file(file_path: str) -> List:
|
15 |
+
models = []
|
16 |
+
with open(file_path, "r") as file:
|
17 |
+
lines = file.readlines()
|
18 |
+
for repo_id in lines:
|
19 |
+
if repo_id.strip() != "":
|
20 |
+
models.append(repo_id.strip())
|
21 |
+
return models
|