diff --git a/.gitattributes b/.gitattributes
index a6344aac8c09253b3b630fb776ae94478aa0275b..53a815fef21c3a483affb06b81916540fbd5ad50 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -33,3 +33,8 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
*.zip filter=lfs diff=lfs merge=lfs -text
*.zst filter=lfs diff=lfs merge=lfs -text
*tfevents* filter=lfs diff=lfs merge=lfs -text
+*.jpg filter=lfs diff=lfs merge=lfs -text
+*.jpeg filter=lfs diff=lfs merge=lfs -text
+*.ong filter=lfs diff=lfs merge=lfs -text
+*.png filter=lfs diff=lfs merge=lfs -text
+*.webp filter=lfs diff=lfs merge=lfs -text
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..0744d0d7b460a6d2943d7f5a43385353bf1a77cc
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,162 @@
+*.safetensors
+
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+wheels/
+share/python-wheels/
+*.egg-info/
+.installed.cfg
+*.egg
+MANIFEST
+
+# PyInstaller
+# Usually these files are written by a python script from a template
+# before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.nox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*.cover
+*.py,cover
+.hypothesis/
+.pytest_cache/
+cover/
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+local_settings.py
+db.sqlite3
+db.sqlite3-journal
+
+# Flask stuff:
+instance/
+.webassets-cache
+
+# Scrapy stuff:
+.scrapy
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+.pybuilder/
+target/
+
+# Jupyter Notebook
+.ipynb_checkpoints
+
+# IPython
+profile_default/
+ipython_config.py
+
+# pyenv
+# For a library or package, you might want to ignore these files since the code is
+# intended to run in multiple environments; otherwise, check them in:
+# .python-version
+
+# pipenv
+# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
+# However, in case of collaboration, if having platform-specific dependencies or dependencies
+# having no cross-platform support, pipenv may install dependencies that don't work, or not
+# install all needed dependencies.
+#Pipfile.lock
+
+# poetry
+# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
+# This is especially recommended for binary packages to ensure reproducibility, and is more
+# commonly ignored for libraries.
+# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
+#poetry.lock
+
+# pdm
+# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
+#pdm.lock
+# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
+# in version control.
+# https://pdm.fming.dev/#use-with-ide
+.pdm.toml
+
+# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
+__pypackages__/
+
+# Celery stuff
+celerybeat-schedule
+celerybeat.pid
+
+# SageMath parsed files
+*.sage.py
+
+# Environments
+.env
+.venv
+env/
+venv/
+ENV/
+env.bak/
+venv.bak/
+
+# Spyder project settings
+.spyderproject
+.spyproject
+
+# Rope project settings
+.ropeproject
+
+# mkdocs documentation
+/site
+
+# mypy
+.mypy_cache/
+.dmypy.json
+dmypy.json
+
+# Pyre type checker
+.pyre/
+
+# pytype static type analyzer
+.pytype/
+
+# Cython debug symbols
+cython_debug/
+
+# PyCharm
+# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
+# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
+# and can be added to the global gitignore or merged into this file. For a more nuclear
+# option (not recommended) you can uncomment the following to ignore the entire idea folder.
+.idea/
diff --git a/.idea/.gitignore b/.idea/.gitignore
deleted file mode 100644
index 13566b81b018ad684f3a35fee301741b2734c8f4..0000000000000000000000000000000000000000
--- a/.idea/.gitignore
+++ /dev/null
@@ -1,8 +0,0 @@
-# Default ignored files
-/shelf/
-/workspace.xml
-# Editor-based HTTP Client requests
-/httpRequests/
-# Datasource local storage ignored files
-/dataSources/
-/dataSources.local.xml
diff --git a/.idea/IC-Light.iml b/.idea/IC-Light.iml
deleted file mode 100644
index f4d77fe59ff723034b349d8cffe4ea0f320d2b60..0000000000000000000000000000000000000000
--- a/.idea/IC-Light.iml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/deployment.xml b/.idea/deployment.xml
deleted file mode 100644
index 81a1fd47a2e75327ebe2f2ddbd275a43d25b5d81..0000000000000000000000000000000000000000
--- a/.idea/deployment.xml
+++ /dev/null
@@ -1,70 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
deleted file mode 100644
index 80a79460fe6efb5e5448aecaf0d88affc48eb8bc..0000000000000000000000000000000000000000
--- a/.idea/inspectionProfiles/Project_Default.xml
+++ /dev/null
@@ -1,84 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
deleted file mode 100644
index 105ce2da2d6447d11dfe32bfb846c3d5b199fc99..0000000000000000000000000000000000000000
--- a/.idea/inspectionProfiles/profiles_settings.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
deleted file mode 100644
index 655480b620e3440d19ad4171b4f0080d17a1020c..0000000000000000000000000000000000000000
--- a/.idea/misc.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
deleted file mode 100644
index 0f2cb7f9c7064527e361b0e5cb45e7344d244280..0000000000000000000000000000000000000000
--- a/.idea/modules.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
deleted file mode 100644
index 35eb1ddfbbc029bcab630581847471d7f238ec53..0000000000000000000000000000000000000000
--- a/.idea/vcs.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app.py b/app.py
index 0222e096cee2aab2efc4ca11b0900d54688bf611..e2b7bc5fd66878048d60f80863342b2debee2dce 100644
--- a/app.py
+++ b/app.py
@@ -1,13 +1,429 @@
+import math
+import gradio as gr
+import numpy as np
import torch
-print(f"Is CUDA available: {torch.cuda.is_available()}")
-# True
-print(f"CUDA device: {torch.cuda.get_device_name(torch.cuda.current_device())}")
-# Tesla T4
+import safetensors.torch as sf
+import db_examples
-import gradio as gr
+from PIL import Image
+from diffusers import StableDiffusionPipeline, StableDiffusionImg2ImgPipeline
+from diffusers import AutoencoderKL, UNet2DConditionModel, DDIMScheduler, EulerAncestralDiscreteScheduler, DPMSolverMultistepScheduler
+from diffusers.models.attention_processor import AttnProcessor2_0
+from transformers import CLIPTextModel, CLIPTokenizer
+from briarmbg import BriaRMBG
+from enum import Enum
+from torch.hub import download_url_to_file
+
+
+# 'stablediffusionapi/realistic-vision-v51'
+# 'runwayml/stable-diffusion-v1-5'
+sd15_name = 'stablediffusionapi/realistic-vision-v51'
+tokenizer = CLIPTokenizer.from_pretrained(sd15_name, subfolder="tokenizer")
+text_encoder = CLIPTextModel.from_pretrained(sd15_name, subfolder="text_encoder")
+vae = AutoencoderKL.from_pretrained(sd15_name, subfolder="vae")
+unet = UNet2DConditionModel.from_pretrained(sd15_name, subfolder="unet")
+rmbg = BriaRMBG.from_pretrained("briaai/RMBG-1.4")
+
+# Change UNet
+
+with torch.no_grad():
+ new_conv_in = torch.nn.Conv2d(8, unet.conv_in.out_channels, unet.conv_in.kernel_size, unet.conv_in.stride, unet.conv_in.padding)
+ new_conv_in.weight.zero_()
+ new_conv_in.weight[:, :4, :, :].copy_(unet.conv_in.weight)
+ new_conv_in.bias = unet.conv_in.bias
+ unet.conv_in = new_conv_in
+
+unet_original_forward = unet.forward
+
+
+def hooked_unet_forward(sample, timestep, encoder_hidden_states, **kwargs):
+ c_concat = kwargs['cross_attention_kwargs']['concat_conds'].to(sample)
+ c_concat = torch.cat([c_concat] * (sample.shape[0] // c_concat.shape[0]), dim=0)
+ new_sample = torch.cat([sample, c_concat], dim=1)
+ kwargs['cross_attention_kwargs'] = {}
+ return unet_original_forward(new_sample, timestep, encoder_hidden_states, **kwargs)
+
+
+unet.forward = hooked_unet_forward
+
+# Load
+
+model_path = './models/iclight_sd15_fc.safetensors'
+download_url_to_file(url='https://huggingface.co/lllyasviel/ic-light/resolve/main/iclight_sd15_fc.safetensors', dst=model_path)
+sd_offset = sf.load_file(model_path)
+sd_origin = unet.state_dict()
+keys = sd_origin.keys()
+sd_merged = {k: sd_origin[k] + sd_offset[k] for k in sd_origin.keys()}
+unet.load_state_dict(sd_merged, strict=True)
+del sd_offset, sd_origin, sd_merged, keys
+
+# Device
+
+device = torch.device('cuda')
+text_encoder = text_encoder.to(device=device, dtype=torch.float16)
+vae = vae.to(device=device, dtype=torch.bfloat16)
+unet = unet.to(device=device, dtype=torch.float16)
+rmbg = rmbg.to(device=device, dtype=torch.float32)
+
+# SDP
+
+unet.set_attn_processor(AttnProcessor2_0())
+vae.set_attn_processor(AttnProcessor2_0())
+
+# Samplers
+
+ddim_scheduler = DDIMScheduler(
+ num_train_timesteps=1000,
+ beta_start=0.00085,
+ beta_end=0.012,
+ beta_schedule="scaled_linear",
+ clip_sample=False,
+ set_alpha_to_one=False,
+ steps_offset=1,
+)
+
+euler_a_scheduler = EulerAncestralDiscreteScheduler(
+ num_train_timesteps=1000,
+ beta_start=0.00085,
+ beta_end=0.012,
+ steps_offset=1
+)
+
+dpmpp_2m_sde_karras_scheduler = DPMSolverMultistepScheduler(
+ num_train_timesteps=1000,
+ beta_start=0.00085,
+ beta_end=0.012,
+ algorithm_type="sde-dpmsolver++",
+ use_karras_sigmas=True,
+ steps_offset=1
+)
+
+# Pipelines
+
+t2i_pipe = StableDiffusionPipeline(
+ vae=vae,
+ text_encoder=text_encoder,
+ tokenizer=tokenizer,
+ unet=unet,
+ scheduler=dpmpp_2m_sde_karras_scheduler,
+ safety_checker=None,
+ requires_safety_checker=False,
+ feature_extractor=None,
+ image_encoder=None
+)
+
+i2i_pipe = StableDiffusionImg2ImgPipeline(
+ vae=vae,
+ text_encoder=text_encoder,
+ tokenizer=tokenizer,
+ unet=unet,
+ scheduler=dpmpp_2m_sde_karras_scheduler,
+ safety_checker=None,
+ requires_safety_checker=False,
+ feature_extractor=None,
+ image_encoder=None
+)
+
+
+@torch.inference_mode()
+def encode_prompt_inner(txt: str):
+ max_length = tokenizer.model_max_length
+ chunk_length = tokenizer.model_max_length - 2
+ id_start = tokenizer.bos_token_id
+ id_end = tokenizer.eos_token_id
+ id_pad = id_end
+
+ def pad(x, p, i):
+ return x[:i] if len(x) >= i else x + [p] * (i - len(x))
+
+ tokens = tokenizer(txt, truncation=False, add_special_tokens=False)["input_ids"]
+ chunks = [[id_start] + tokens[i: i + chunk_length] + [id_end] for i in range(0, len(tokens), chunk_length)]
+ chunks = [pad(ck, id_pad, max_length) for ck in chunks]
+
+ token_ids = torch.tensor(chunks).to(device=device, dtype=torch.int64)
+ conds = text_encoder(token_ids).last_hidden_state
+
+ return conds
+
+
+@torch.inference_mode()
+def encode_prompt_pair(positive_prompt, negative_prompt):
+ c = encode_prompt_inner(positive_prompt)
+ uc = encode_prompt_inner(negative_prompt)
+
+ c_len = float(len(c))
+ uc_len = float(len(uc))
+ max_count = max(c_len, uc_len)
+ c_repeat = int(math.ceil(max_count / c_len))
+ uc_repeat = int(math.ceil(max_count / uc_len))
+ max_chunk = max(len(c), len(uc))
+
+ c = torch.cat([c] * c_repeat, dim=0)[:max_chunk]
+ uc = torch.cat([uc] * uc_repeat, dim=0)[:max_chunk]
+
+ c = torch.cat([p[None, ...] for p in c], dim=1)
+ uc = torch.cat([p[None, ...] for p in uc], dim=1)
+
+ return c, uc
+
+
+@torch.inference_mode()
+def pytorch2numpy(imgs, quant=True):
+ results = []
+ for x in imgs:
+ y = x.movedim(0, -1)
+
+ if quant:
+ y = y * 127.5 + 127.5
+ y = y.detach().float().cpu().numpy().clip(0, 255).astype(np.uint8)
+ else:
+ y = y * 0.5 + 0.5
+ y = y.detach().float().cpu().numpy().clip(0, 1).astype(np.float32)
+
+ results.append(y)
+ return results
+
+
+@torch.inference_mode()
+def numpy2pytorch(imgs):
+ h = torch.from_numpy(np.stack(imgs, axis=0)).float() / 127.0 - 1.0 # so that 127 must be strictly 0.0
+ h = h.movedim(-1, 1)
+ return h
+
+
+def resize_and_center_crop(image, target_width, target_height):
+ pil_image = Image.fromarray(image)
+ original_width, original_height = pil_image.size
+ scale_factor = max(target_width / original_width, target_height / original_height)
+ resized_width = int(round(original_width * scale_factor))
+ resized_height = int(round(original_height * scale_factor))
+ resized_image = pil_image.resize((resized_width, resized_height), Image.LANCZOS)
+ left = (resized_width - target_width) / 2
+ top = (resized_height - target_height) / 2
+ right = (resized_width + target_width) / 2
+ bottom = (resized_height + target_height) / 2
+ cropped_image = resized_image.crop((left, top, right, bottom))
+ return np.array(cropped_image)
+
+
+def resize_without_crop(image, target_width, target_height):
+ pil_image = Image.fromarray(image)
+ resized_image = pil_image.resize((target_width, target_height), Image.LANCZOS)
+ return np.array(resized_image)
+
+
+@torch.inference_mode()
+def run_rmbg(img, sigma=0.0):
+ H, W, C = img.shape
+ assert C == 3
+ k = (256.0 / float(H * W)) ** 0.5
+ feed = resize_without_crop(img, int(64 * round(W * k)), int(64 * round(H * k)))
+ feed = numpy2pytorch([feed]).to(device=device, dtype=torch.float32)
+ alpha = rmbg(feed)[0][0]
+ alpha = torch.nn.functional.interpolate(alpha, size=(H, W), mode="bilinear")
+ alpha = alpha.movedim(1, -1)[0]
+ alpha = alpha.detach().float().cpu().numpy().clip(0, 1)
+ result = 127 + (img.astype(np.float32) - 127 + sigma) * alpha
+ return result.clip(0, 255).astype(np.uint8), alpha
+
+
+@torch.inference_mode()
+def process(input_fg, prompt, image_width, image_height, num_samples, seed, steps, a_prompt, n_prompt, cfg, highres_scale, highres_denoise, lowres_denoise, bg_source):
+ bg_source = BGSource(bg_source)
+ input_bg = None
+
+ if bg_source == BGSource.NONE:
+ pass
+ elif bg_source == BGSource.LEFT:
+ gradient = np.linspace(255, 0, image_width)
+ image = np.tile(gradient, (image_height, 1))
+ input_bg = np.stack((image,) * 3, axis=-1).astype(np.uint8)
+ elif bg_source == BGSource.RIGHT:
+ gradient = np.linspace(0, 255, image_width)
+ image = np.tile(gradient, (image_height, 1))
+ input_bg = np.stack((image,) * 3, axis=-1).astype(np.uint8)
+ elif bg_source == BGSource.TOP:
+ gradient = np.linspace(255, 0, image_height)[:, None]
+ image = np.tile(gradient, (1, image_width))
+ input_bg = np.stack((image,) * 3, axis=-1).astype(np.uint8)
+ elif bg_source == BGSource.BOTTOM:
+ gradient = np.linspace(0, 255, image_height)[:, None]
+ image = np.tile(gradient, (1, image_width))
+ input_bg = np.stack((image,) * 3, axis=-1).astype(np.uint8)
+ else:
+ raise 'Wrong initial latent!'
+
+ rng = torch.Generator(device=device).manual_seed(int(seed))
+
+ fg = resize_and_center_crop(input_fg, image_width, image_height)
+
+ concat_conds = numpy2pytorch([fg]).to(device=vae.device, dtype=vae.dtype)
+ concat_conds = vae.encode(concat_conds).latent_dist.mode() * vae.config.scaling_factor
+
+ conds, unconds = encode_prompt_pair(positive_prompt=prompt + ', ' + a_prompt, negative_prompt=n_prompt)
+
+ if input_bg is None:
+ latents = t2i_pipe(
+ prompt_embeds=conds,
+ negative_prompt_embeds=unconds,
+ width=image_width,
+ height=image_height,
+ num_inference_steps=steps,
+ num_images_per_prompt=num_samples,
+ generator=rng,
+ output_type='latent',
+ guidance_scale=cfg,
+ cross_attention_kwargs={'concat_conds': concat_conds},
+ ).images.to(vae.dtype) / vae.config.scaling_factor
+ else:
+ bg = resize_and_center_crop(input_bg, image_width, image_height)
+ bg_latent = numpy2pytorch([bg]).to(device=vae.device, dtype=vae.dtype)
+ bg_latent = vae.encode(bg_latent).latent_dist.mode() * vae.config.scaling_factor
+ latents = i2i_pipe(
+ image=bg_latent,
+ strength=lowres_denoise,
+ prompt_embeds=conds,
+ negative_prompt_embeds=unconds,
+ width=image_width,
+ height=image_height,
+ num_inference_steps=int(round(steps / lowres_denoise)),
+ num_images_per_prompt=num_samples,
+ generator=rng,
+ output_type='latent',
+ guidance_scale=cfg,
+ cross_attention_kwargs={'concat_conds': concat_conds},
+ ).images.to(vae.dtype) / vae.config.scaling_factor
+
+ pixels = vae.decode(latents).sample
+ pixels = pytorch2numpy(pixels)
+ pixels = [resize_without_crop(
+ image=p,
+ target_width=int(round(image_width * highres_scale / 64.0) * 64),
+ target_height=int(round(image_height * highres_scale / 64.0) * 64))
+ for p in pixels]
+
+ pixels = numpy2pytorch(pixels).to(device=vae.device, dtype=vae.dtype)
+ latents = vae.encode(pixels).latent_dist.mode() * vae.config.scaling_factor
+ latents = latents.to(device=unet.device, dtype=unet.dtype)
+
+ image_height, image_width = latents.shape[2] * 8, latents.shape[3] * 8
+
+ fg = resize_and_center_crop(input_fg, image_width, image_height)
+ concat_conds = numpy2pytorch([fg]).to(device=vae.device, dtype=vae.dtype)
+ concat_conds = vae.encode(concat_conds).latent_dist.mode() * vae.config.scaling_factor
+
+ latents = i2i_pipe(
+ image=latents,
+ strength=highres_denoise,
+ prompt_embeds=conds,
+ negative_prompt_embeds=unconds,
+ width=image_width,
+ height=image_height,
+ num_inference_steps=int(round(steps / highres_denoise)),
+ num_images_per_prompt=num_samples,
+ generator=rng,
+ output_type='latent',
+ guidance_scale=cfg,
+ cross_attention_kwargs={'concat_conds': concat_conds},
+ ).images.to(vae.dtype) / vae.config.scaling_factor
+
+ pixels = vae.decode(latents).sample
+
+ return pytorch2numpy(pixels)
+
+
+@torch.inference_mode()
+def process_relight(input_fg, prompt, image_width, image_height, num_samples, seed, steps, a_prompt, n_prompt, cfg, highres_scale, highres_denoise, lowres_denoise, bg_source):
+ input_fg, matting = run_rmbg(input_fg)
+ results = process(input_fg, prompt, image_width, image_height, num_samples, seed, steps, a_prompt, n_prompt, cfg, highres_scale, highres_denoise, lowres_denoise, bg_source)
+ return input_fg, results
+
+
+quick_prompts = [
+ 'sunshine from window',
+ 'neon light, city',
+ 'sunset over sea',
+ 'golden time',
+ 'sci-fi RGB glowing, cyberpunk',
+ 'natural lighting',
+ 'warm atmosphere, at home, bedroom',
+ 'magic lit',
+ 'evil, gothic, Yharnam',
+ 'light and shadow',
+ 'shadow from window',
+ 'soft studio lighting',
+ 'home atmosphere, cozy bedroom illumination',
+ 'neon, Wong Kar-wai, warm'
+]
+quick_prompts = [[x] for x in quick_prompts]
+
+
+quick_subjects = [
+ 'beautiful woman, detailed face',
+ 'handsome man, detailed face',
+]
+quick_subjects = [[x] for x in quick_subjects]
+
+
+class BGSource(Enum):
+ NONE = "None"
+ LEFT = "Left Light"
+ RIGHT = "Right Light"
+ TOP = "Top Light"
+ BOTTOM = "Bottom Light"
+
+
+block = gr.Blocks().queue()
+with block:
+ with gr.Row():
+ gr.Markdown("## IC-Light (Relighting with Foreground Condition)")
+ with gr.Row():
+ with gr.Column():
+ with gr.Row():
+ input_fg = gr.Image(source='upload', type="numpy", label="Image", height=480)
+ output_bg = gr.Image(type="numpy", label="Preprocessed Foreground", height=480)
+ prompt = gr.Textbox(label="Prompt")
+ bg_source = gr.Radio(choices=[e.value for e in BGSource],
+ value=BGSource.NONE.value,
+ label="Lighting Preference (Initial Latent)", type='value')
+ example_quick_subjects = gr.Dataset(samples=quick_subjects, label='Subject Quick List', samples_per_page=1000, components=[prompt])
+ example_quick_prompts = gr.Dataset(samples=quick_prompts, label='Lighting Quick List', samples_per_page=1000, components=[prompt])
+ relight_button = gr.Button(value="Relight")
+
+ with gr.Group():
+ with gr.Row():
+ num_samples = gr.Slider(label="Images", minimum=1, maximum=12, value=1, step=1)
+ seed = gr.Number(label="Seed", value=12345, precision=0)
+
+ with gr.Row():
+ image_width = gr.Slider(label="Image Width", minimum=256, maximum=1024, value=512, step=64)
+ image_height = gr.Slider(label="Image Height", minimum=256, maximum=1024, value=640, step=64)
+
+ with gr.Accordion("Advanced options", open=False):
+ steps = gr.Slider(label="Steps", minimum=1, maximum=100, value=25, step=1)
+ cfg = gr.Slider(label="CFG Scale", minimum=1.0, maximum=32.0, value=2, step=0.01)
+ lowres_denoise = gr.Slider(label="Lowres Denoise (for initial latent)", minimum=0.1, maximum=1.0, value=0.9, step=0.01)
+ highres_scale = gr.Slider(label="Highres Scale", minimum=1.0, maximum=3.0, value=1.5, step=0.01)
+ highres_denoise = gr.Slider(label="Highres Denoise", minimum=0.1, maximum=1.0, value=0.5, step=0.01)
+ a_prompt = gr.Textbox(label="Added Prompt", value='best quality')
+ n_prompt = gr.Textbox(label="Negative Prompt", value='lowres, bad anatomy, bad hands, cropped, worst quality')
+ with gr.Column():
+ result_gallery = gr.Gallery(height=832, object_fit='contain', label='Outputs')
+ with gr.Row():
+ dummy_image_for_outputs = gr.Image(visible=False, label='Result')
+ gr.Examples(
+ fn=lambda *args: ([args[-1]], None),
+ examples=db_examples.foreground_conditioned_examples,
+ inputs=[
+ input_fg, prompt, bg_source, image_width, image_height, seed, dummy_image_for_outputs
+ ],
+ outputs=[result_gallery, output_bg],
+ run_on_click=True, examples_per_page=1024
+ )
+ ips = [input_fg, prompt, image_width, image_height, num_samples, seed, steps, a_prompt, n_prompt, cfg, highres_scale, highres_denoise, lowres_denoise, bg_source]
+ relight_button.click(fn=process_relight, inputs=ips, outputs=[output_bg, result_gallery])
+ example_quick_prompts.click(lambda x, y: ', '.join(y.split(', ')[:2] + [x[0]]), inputs=[example_quick_prompts, prompt], outputs=prompt, show_progress=False, queue=False)
+ example_quick_subjects.click(lambda x: x[0], inputs=example_quick_subjects, outputs=prompt, show_progress=False, queue=False)
-def greet(name):
- return "Hello " + name + "!!"
-demo = gr.Interface(fn=greet, inputs="text", outputs="text")
-demo.launch()
+block.launch(server_name='0.0.0.0')
diff --git a/briarmbg.py b/briarmbg.py
new file mode 100644
index 0000000000000000000000000000000000000000..1cc74718cc70c62550b203b586144249d47f1883
--- /dev/null
+++ b/briarmbg.py
@@ -0,0 +1,462 @@
+# RMBG1.4 (diffusers implementation)
+# Found on huggingface space of several projects
+# Not sure which project is the source of this file
+
+import torch
+import torch.nn as nn
+import torch.nn.functional as F
+from huggingface_hub import PyTorchModelHubMixin
+
+
+class REBNCONV(nn.Module):
+ def __init__(self, in_ch=3, out_ch=3, dirate=1, stride=1):
+ super(REBNCONV, self).__init__()
+
+ self.conv_s1 = nn.Conv2d(
+ in_ch, out_ch, 3, padding=1 * dirate, dilation=1 * dirate, stride=stride
+ )
+ self.bn_s1 = nn.BatchNorm2d(out_ch)
+ self.relu_s1 = nn.ReLU(inplace=True)
+
+ def forward(self, x):
+ hx = x
+ xout = self.relu_s1(self.bn_s1(self.conv_s1(hx)))
+
+ return xout
+
+
+def _upsample_like(src, tar):
+ src = F.interpolate(src, size=tar.shape[2:], mode="bilinear")
+ return src
+
+
+### RSU-7 ###
+class RSU7(nn.Module):
+ def __init__(self, in_ch=3, mid_ch=12, out_ch=3, img_size=512):
+ super(RSU7, self).__init__()
+
+ self.in_ch = in_ch
+ self.mid_ch = mid_ch
+ self.out_ch = out_ch
+
+ self.rebnconvin = REBNCONV(in_ch, out_ch, dirate=1) ## 1 -> 1/2
+
+ self.rebnconv1 = REBNCONV(out_ch, mid_ch, dirate=1)
+ self.pool1 = nn.MaxPool2d(2, stride=2, ceil_mode=True)
+
+ self.rebnconv2 = REBNCONV(mid_ch, mid_ch, dirate=1)
+ self.pool2 = nn.MaxPool2d(2, stride=2, ceil_mode=True)
+
+ self.rebnconv3 = REBNCONV(mid_ch, mid_ch, dirate=1)
+ self.pool3 = nn.MaxPool2d(2, stride=2, ceil_mode=True)
+
+ self.rebnconv4 = REBNCONV(mid_ch, mid_ch, dirate=1)
+ self.pool4 = nn.MaxPool2d(2, stride=2, ceil_mode=True)
+
+ self.rebnconv5 = REBNCONV(mid_ch, mid_ch, dirate=1)
+ self.pool5 = nn.MaxPool2d(2, stride=2, ceil_mode=True)
+
+ self.rebnconv6 = REBNCONV(mid_ch, mid_ch, dirate=1)
+
+ self.rebnconv7 = REBNCONV(mid_ch, mid_ch, dirate=2)
+
+ self.rebnconv6d = REBNCONV(mid_ch * 2, mid_ch, dirate=1)
+ self.rebnconv5d = REBNCONV(mid_ch * 2, mid_ch, dirate=1)
+ self.rebnconv4d = REBNCONV(mid_ch * 2, mid_ch, dirate=1)
+ self.rebnconv3d = REBNCONV(mid_ch * 2, mid_ch, dirate=1)
+ self.rebnconv2d = REBNCONV(mid_ch * 2, mid_ch, dirate=1)
+ self.rebnconv1d = REBNCONV(mid_ch * 2, out_ch, dirate=1)
+
+ def forward(self, x):
+ b, c, h, w = x.shape
+
+ hx = x
+ hxin = self.rebnconvin(hx)
+
+ hx1 = self.rebnconv1(hxin)
+ hx = self.pool1(hx1)
+
+ hx2 = self.rebnconv2(hx)
+ hx = self.pool2(hx2)
+
+ hx3 = self.rebnconv3(hx)
+ hx = self.pool3(hx3)
+
+ hx4 = self.rebnconv4(hx)
+ hx = self.pool4(hx4)
+
+ hx5 = self.rebnconv5(hx)
+ hx = self.pool5(hx5)
+
+ hx6 = self.rebnconv6(hx)
+
+ hx7 = self.rebnconv7(hx6)
+
+ hx6d = self.rebnconv6d(torch.cat((hx7, hx6), 1))
+ hx6dup = _upsample_like(hx6d, hx5)
+
+ hx5d = self.rebnconv5d(torch.cat((hx6dup, hx5), 1))
+ hx5dup = _upsample_like(hx5d, hx4)
+
+ hx4d = self.rebnconv4d(torch.cat((hx5dup, hx4), 1))
+ hx4dup = _upsample_like(hx4d, hx3)
+
+ hx3d = self.rebnconv3d(torch.cat((hx4dup, hx3), 1))
+ hx3dup = _upsample_like(hx3d, hx2)
+
+ hx2d = self.rebnconv2d(torch.cat((hx3dup, hx2), 1))
+ hx2dup = _upsample_like(hx2d, hx1)
+
+ hx1d = self.rebnconv1d(torch.cat((hx2dup, hx1), 1))
+
+ return hx1d + hxin
+
+
+### RSU-6 ###
+class RSU6(nn.Module):
+ def __init__(self, in_ch=3, mid_ch=12, out_ch=3):
+ super(RSU6, self).__init__()
+
+ self.rebnconvin = REBNCONV(in_ch, out_ch, dirate=1)
+
+ self.rebnconv1 = REBNCONV(out_ch, mid_ch, dirate=1)
+ self.pool1 = nn.MaxPool2d(2, stride=2, ceil_mode=True)
+
+ self.rebnconv2 = REBNCONV(mid_ch, mid_ch, dirate=1)
+ self.pool2 = nn.MaxPool2d(2, stride=2, ceil_mode=True)
+
+ self.rebnconv3 = REBNCONV(mid_ch, mid_ch, dirate=1)
+ self.pool3 = nn.MaxPool2d(2, stride=2, ceil_mode=True)
+
+ self.rebnconv4 = REBNCONV(mid_ch, mid_ch, dirate=1)
+ self.pool4 = nn.MaxPool2d(2, stride=2, ceil_mode=True)
+
+ self.rebnconv5 = REBNCONV(mid_ch, mid_ch, dirate=1)
+
+ self.rebnconv6 = REBNCONV(mid_ch, mid_ch, dirate=2)
+
+ self.rebnconv5d = REBNCONV(mid_ch * 2, mid_ch, dirate=1)
+ self.rebnconv4d = REBNCONV(mid_ch * 2, mid_ch, dirate=1)
+ self.rebnconv3d = REBNCONV(mid_ch * 2, mid_ch, dirate=1)
+ self.rebnconv2d = REBNCONV(mid_ch * 2, mid_ch, dirate=1)
+ self.rebnconv1d = REBNCONV(mid_ch * 2, out_ch, dirate=1)
+
+ def forward(self, x):
+ hx = x
+
+ hxin = self.rebnconvin(hx)
+
+ hx1 = self.rebnconv1(hxin)
+ hx = self.pool1(hx1)
+
+ hx2 = self.rebnconv2(hx)
+ hx = self.pool2(hx2)
+
+ hx3 = self.rebnconv3(hx)
+ hx = self.pool3(hx3)
+
+ hx4 = self.rebnconv4(hx)
+ hx = self.pool4(hx4)
+
+ hx5 = self.rebnconv5(hx)
+
+ hx6 = self.rebnconv6(hx5)
+
+ hx5d = self.rebnconv5d(torch.cat((hx6, hx5), 1))
+ hx5dup = _upsample_like(hx5d, hx4)
+
+ hx4d = self.rebnconv4d(torch.cat((hx5dup, hx4), 1))
+ hx4dup = _upsample_like(hx4d, hx3)
+
+ hx3d = self.rebnconv3d(torch.cat((hx4dup, hx3), 1))
+ hx3dup = _upsample_like(hx3d, hx2)
+
+ hx2d = self.rebnconv2d(torch.cat((hx3dup, hx2), 1))
+ hx2dup = _upsample_like(hx2d, hx1)
+
+ hx1d = self.rebnconv1d(torch.cat((hx2dup, hx1), 1))
+
+ return hx1d + hxin
+
+
+### RSU-5 ###
+class RSU5(nn.Module):
+ def __init__(self, in_ch=3, mid_ch=12, out_ch=3):
+ super(RSU5, self).__init__()
+
+ self.rebnconvin = REBNCONV(in_ch, out_ch, dirate=1)
+
+ self.rebnconv1 = REBNCONV(out_ch, mid_ch, dirate=1)
+ self.pool1 = nn.MaxPool2d(2, stride=2, ceil_mode=True)
+
+ self.rebnconv2 = REBNCONV(mid_ch, mid_ch, dirate=1)
+ self.pool2 = nn.MaxPool2d(2, stride=2, ceil_mode=True)
+
+ self.rebnconv3 = REBNCONV(mid_ch, mid_ch, dirate=1)
+ self.pool3 = nn.MaxPool2d(2, stride=2, ceil_mode=True)
+
+ self.rebnconv4 = REBNCONV(mid_ch, mid_ch, dirate=1)
+
+ self.rebnconv5 = REBNCONV(mid_ch, mid_ch, dirate=2)
+
+ self.rebnconv4d = REBNCONV(mid_ch * 2, mid_ch, dirate=1)
+ self.rebnconv3d = REBNCONV(mid_ch * 2, mid_ch, dirate=1)
+ self.rebnconv2d = REBNCONV(mid_ch * 2, mid_ch, dirate=1)
+ self.rebnconv1d = REBNCONV(mid_ch * 2, out_ch, dirate=1)
+
+ def forward(self, x):
+ hx = x
+
+ hxin = self.rebnconvin(hx)
+
+ hx1 = self.rebnconv1(hxin)
+ hx = self.pool1(hx1)
+
+ hx2 = self.rebnconv2(hx)
+ hx = self.pool2(hx2)
+
+ hx3 = self.rebnconv3(hx)
+ hx = self.pool3(hx3)
+
+ hx4 = self.rebnconv4(hx)
+
+ hx5 = self.rebnconv5(hx4)
+
+ hx4d = self.rebnconv4d(torch.cat((hx5, hx4), 1))
+ hx4dup = _upsample_like(hx4d, hx3)
+
+ hx3d = self.rebnconv3d(torch.cat((hx4dup, hx3), 1))
+ hx3dup = _upsample_like(hx3d, hx2)
+
+ hx2d = self.rebnconv2d(torch.cat((hx3dup, hx2), 1))
+ hx2dup = _upsample_like(hx2d, hx1)
+
+ hx1d = self.rebnconv1d(torch.cat((hx2dup, hx1), 1))
+
+ return hx1d + hxin
+
+
+### RSU-4 ###
+class RSU4(nn.Module):
+ def __init__(self, in_ch=3, mid_ch=12, out_ch=3):
+ super(RSU4, self).__init__()
+
+ self.rebnconvin = REBNCONV(in_ch, out_ch, dirate=1)
+
+ self.rebnconv1 = REBNCONV(out_ch, mid_ch, dirate=1)
+ self.pool1 = nn.MaxPool2d(2, stride=2, ceil_mode=True)
+
+ self.rebnconv2 = REBNCONV(mid_ch, mid_ch, dirate=1)
+ self.pool2 = nn.MaxPool2d(2, stride=2, ceil_mode=True)
+
+ self.rebnconv3 = REBNCONV(mid_ch, mid_ch, dirate=1)
+
+ self.rebnconv4 = REBNCONV(mid_ch, mid_ch, dirate=2)
+
+ self.rebnconv3d = REBNCONV(mid_ch * 2, mid_ch, dirate=1)
+ self.rebnconv2d = REBNCONV(mid_ch * 2, mid_ch, dirate=1)
+ self.rebnconv1d = REBNCONV(mid_ch * 2, out_ch, dirate=1)
+
+ def forward(self, x):
+ hx = x
+
+ hxin = self.rebnconvin(hx)
+
+ hx1 = self.rebnconv1(hxin)
+ hx = self.pool1(hx1)
+
+ hx2 = self.rebnconv2(hx)
+ hx = self.pool2(hx2)
+
+ hx3 = self.rebnconv3(hx)
+
+ hx4 = self.rebnconv4(hx3)
+
+ hx3d = self.rebnconv3d(torch.cat((hx4, hx3), 1))
+ hx3dup = _upsample_like(hx3d, hx2)
+
+ hx2d = self.rebnconv2d(torch.cat((hx3dup, hx2), 1))
+ hx2dup = _upsample_like(hx2d, hx1)
+
+ hx1d = self.rebnconv1d(torch.cat((hx2dup, hx1), 1))
+
+ return hx1d + hxin
+
+
+### RSU-4F ###
+class RSU4F(nn.Module):
+ def __init__(self, in_ch=3, mid_ch=12, out_ch=3):
+ super(RSU4F, self).__init__()
+
+ self.rebnconvin = REBNCONV(in_ch, out_ch, dirate=1)
+
+ self.rebnconv1 = REBNCONV(out_ch, mid_ch, dirate=1)
+ self.rebnconv2 = REBNCONV(mid_ch, mid_ch, dirate=2)
+ self.rebnconv3 = REBNCONV(mid_ch, mid_ch, dirate=4)
+
+ self.rebnconv4 = REBNCONV(mid_ch, mid_ch, dirate=8)
+
+ self.rebnconv3d = REBNCONV(mid_ch * 2, mid_ch, dirate=4)
+ self.rebnconv2d = REBNCONV(mid_ch * 2, mid_ch, dirate=2)
+ self.rebnconv1d = REBNCONV(mid_ch * 2, out_ch, dirate=1)
+
+ def forward(self, x):
+ hx = x
+
+ hxin = self.rebnconvin(hx)
+
+ hx1 = self.rebnconv1(hxin)
+ hx2 = self.rebnconv2(hx1)
+ hx3 = self.rebnconv3(hx2)
+
+ hx4 = self.rebnconv4(hx3)
+
+ hx3d = self.rebnconv3d(torch.cat((hx4, hx3), 1))
+ hx2d = self.rebnconv2d(torch.cat((hx3d, hx2), 1))
+ hx1d = self.rebnconv1d(torch.cat((hx2d, hx1), 1))
+
+ return hx1d + hxin
+
+
+class myrebnconv(nn.Module):
+ def __init__(
+ self,
+ in_ch=3,
+ out_ch=1,
+ kernel_size=3,
+ stride=1,
+ padding=1,
+ dilation=1,
+ groups=1,
+ ):
+ super(myrebnconv, self).__init__()
+
+ self.conv = nn.Conv2d(
+ in_ch,
+ out_ch,
+ kernel_size=kernel_size,
+ stride=stride,
+ padding=padding,
+ dilation=dilation,
+ groups=groups,
+ )
+ self.bn = nn.BatchNorm2d(out_ch)
+ self.rl = nn.ReLU(inplace=True)
+
+ def forward(self, x):
+ return self.rl(self.bn(self.conv(x)))
+
+
+class BriaRMBG(nn.Module, PyTorchModelHubMixin):
+ def __init__(self, config: dict = {"in_ch": 3, "out_ch": 1}):
+ super(BriaRMBG, self).__init__()
+ in_ch = config["in_ch"]
+ out_ch = config["out_ch"]
+ self.conv_in = nn.Conv2d(in_ch, 64, 3, stride=2, padding=1)
+ self.pool_in = nn.MaxPool2d(2, stride=2, ceil_mode=True)
+
+ self.stage1 = RSU7(64, 32, 64)
+ self.pool12 = nn.MaxPool2d(2, stride=2, ceil_mode=True)
+
+ self.stage2 = RSU6(64, 32, 128)
+ self.pool23 = nn.MaxPool2d(2, stride=2, ceil_mode=True)
+
+ self.stage3 = RSU5(128, 64, 256)
+ self.pool34 = nn.MaxPool2d(2, stride=2, ceil_mode=True)
+
+ self.stage4 = RSU4(256, 128, 512)
+ self.pool45 = nn.MaxPool2d(2, stride=2, ceil_mode=True)
+
+ self.stage5 = RSU4F(512, 256, 512)
+ self.pool56 = nn.MaxPool2d(2, stride=2, ceil_mode=True)
+
+ self.stage6 = RSU4F(512, 256, 512)
+
+ # decoder
+ self.stage5d = RSU4F(1024, 256, 512)
+ self.stage4d = RSU4(1024, 128, 256)
+ self.stage3d = RSU5(512, 64, 128)
+ self.stage2d = RSU6(256, 32, 64)
+ self.stage1d = RSU7(128, 16, 64)
+
+ self.side1 = nn.Conv2d(64, out_ch, 3, padding=1)
+ self.side2 = nn.Conv2d(64, out_ch, 3, padding=1)
+ self.side3 = nn.Conv2d(128, out_ch, 3, padding=1)
+ self.side4 = nn.Conv2d(256, out_ch, 3, padding=1)
+ self.side5 = nn.Conv2d(512, out_ch, 3, padding=1)
+ self.side6 = nn.Conv2d(512, out_ch, 3, padding=1)
+
+ # self.outconv = nn.Conv2d(6*out_ch,out_ch,1)
+
+ def forward(self, x):
+ hx = x
+
+ hxin = self.conv_in(hx)
+ # hx = self.pool_in(hxin)
+
+ # stage 1
+ hx1 = self.stage1(hxin)
+ hx = self.pool12(hx1)
+
+ # stage 2
+ hx2 = self.stage2(hx)
+ hx = self.pool23(hx2)
+
+ # stage 3
+ hx3 = self.stage3(hx)
+ hx = self.pool34(hx3)
+
+ # stage 4
+ hx4 = self.stage4(hx)
+ hx = self.pool45(hx4)
+
+ # stage 5
+ hx5 = self.stage5(hx)
+ hx = self.pool56(hx5)
+
+ # stage 6
+ hx6 = self.stage6(hx)
+ hx6up = _upsample_like(hx6, hx5)
+
+ # -------------------- decoder --------------------
+ hx5d = self.stage5d(torch.cat((hx6up, hx5), 1))
+ hx5dup = _upsample_like(hx5d, hx4)
+
+ hx4d = self.stage4d(torch.cat((hx5dup, hx4), 1))
+ hx4dup = _upsample_like(hx4d, hx3)
+
+ hx3d = self.stage3d(torch.cat((hx4dup, hx3), 1))
+ hx3dup = _upsample_like(hx3d, hx2)
+
+ hx2d = self.stage2d(torch.cat((hx3dup, hx2), 1))
+ hx2dup = _upsample_like(hx2d, hx1)
+
+ hx1d = self.stage1d(torch.cat((hx2dup, hx1), 1))
+
+ # side output
+ d1 = self.side1(hx1d)
+ d1 = _upsample_like(d1, x)
+
+ d2 = self.side2(hx2d)
+ d2 = _upsample_like(d2, x)
+
+ d3 = self.side3(hx3d)
+ d3 = _upsample_like(d3, x)
+
+ d4 = self.side4(hx4d)
+ d4 = _upsample_like(d4, x)
+
+ d5 = self.side5(hx5d)
+ d5 = _upsample_like(d5, x)
+
+ d6 = self.side6(hx6)
+ d6 = _upsample_like(d6, x)
+
+ return [
+ F.sigmoid(d1),
+ F.sigmoid(d2),
+ F.sigmoid(d3),
+ F.sigmoid(d4),
+ F.sigmoid(d5),
+ F.sigmoid(d6),
+ ], [hx1d, hx2d, hx3d, hx4d, hx5d, hx6]
diff --git a/db_examples.py b/db_examples.py
new file mode 100644
index 0000000000000000000000000000000000000000..9af7291494999e3d6eba081b7e5fe84425a84f37
--- /dev/null
+++ b/db_examples.py
@@ -0,0 +1,217 @@
+foreground_conditioned_examples = [
+ [
+ "imgs/i1.webp",
+ "beautiful woman, detailed face, sunshine, outdoor, warm atmosphere",
+ "Right Light",
+ 512,
+ 960,
+ 12345,
+ "imgs/o1.png",
+ ],
+ [
+ "imgs/i1.webp",
+ "beautiful woman, detailed face, sunshine, outdoor, warm atmosphere",
+ "Left Light",
+ 512,
+ 960,
+ 50,
+ "imgs/o2.png",
+ ],
+ [
+ "imgs/i3.png",
+ "beautiful woman, detailed face, neon, Wong Kar-wai, warm",
+ "Left Light",
+ 512,
+ 768,
+ 12345,
+ "imgs/o3.png",
+ ],
+ [
+ "imgs/i3.png",
+ "beautiful woman, detailed face, sunshine from window",
+ "Left Light",
+ 512,
+ 768,
+ 12345,
+ "imgs/o4.png",
+ ],
+ [
+ "imgs/i5.png",
+ "beautiful woman, detailed face, warm atmosphere, at home, bedroom",
+ "Left Light",
+ 512,
+ 768,
+ 123,
+ "imgs/o5.png",
+ ],
+ [
+ "imgs/i6.jpg",
+ "beautiful woman, detailed face, sunshine from window",
+ "Right Light",
+ 512,
+ 768,
+ 42,
+ "imgs/o6.png",
+ ],
+ [
+ "imgs/i7.jpg",
+ "beautiful woman, detailed face, shadow from window",
+ "Left Light",
+ 512,
+ 768,
+ 8888,
+ "imgs/o7.png",
+ ],
+ [
+ "imgs/i8.webp",
+ "beautiful woman, detailed face, sunset over sea",
+ "Right Light",
+ 512,
+ 640,
+ 42,
+ "imgs/o8.png",
+ ],
+ [
+ "imgs/i9.png",
+ "handsome boy, detailed face, neon light, city",
+ "Left Light",
+ 512,
+ 640,
+ 12345,
+ "imgs/o9.png",
+ ],
+ [
+ "imgs/i10.png",
+ "beautiful woman, detailed face, light and shadow",
+ "Left Light",
+ 512,
+ 960,
+ 8888,
+ "imgs/o10.png",
+ ],
+ [
+ "imgs/i11.png",
+ "Buddha, detailed face, sci-fi RGB glowing, cyberpunk",
+ "Left Light",
+ 512,
+ 768,
+ 8888,
+ "imgs/o11.png",
+ ],
+ [
+ "imgs/i11.png",
+ "Buddha, detailed face, natural lighting",
+ "Left Light",
+ 512,
+ 768,
+ 12345,
+ "imgs/o12.png",
+ ],
+ [
+ "imgs/i13.png",
+ "toy, detailed face, shadow from window",
+ "Bottom Light",
+ 512,
+ 704,
+ 12345,
+ "imgs/o13.png",
+ ],
+ [
+ "imgs/i14.png",
+ "toy, detailed face, sunset over sea",
+ "Right Light",
+ 512,
+ 704,
+ 100,
+ "imgs/o14.png",
+ ],
+ [
+ "imgs/i15.png",
+ "dog, magic lit, sci-fi RGB glowing, studio lighting",
+ "Bottom Light",
+ 512,
+ 768,
+ 12345,
+ "imgs/o15.png",
+ ],
+ [
+ "imgs/i16.png",
+ "mysteriou human, warm atmosphere, warm atmosphere, at home, bedroom",
+ "Right Light",
+ 512,
+ 768,
+ 100,
+ "imgs/o16.png",
+ ],
+]
+
+bg_samples = [
+ 'imgs/bgs/1.webp',
+ 'imgs/bgs/2.webp',
+ 'imgs/bgs/3.webp',
+ 'imgs/bgs/4.webp',
+ 'imgs/bgs/5.webp',
+ 'imgs/bgs/6.webp',
+ 'imgs/bgs/7.webp',
+ 'imgs/bgs/8.webp',
+ 'imgs/bgs/9.webp',
+ 'imgs/bgs/10.webp',
+ 'imgs/bgs/11.png',
+ 'imgs/bgs/12.png',
+ 'imgs/bgs/13.png',
+ 'imgs/bgs/14.png',
+ 'imgs/bgs/15.png',
+]
+
+background_conditioned_examples = [
+ [
+ "imgs/alter/i3.png",
+ "imgs/bgs/7.webp",
+ "beautiful woman, cinematic lighting",
+ "Use Background Image",
+ 512,
+ 768,
+ 12345,
+ "imgs/alter/o1.png",
+ ],
+ [
+ "imgs/alter/i2.png",
+ "imgs/bgs/11.png",
+ "statue of an angel, natural lighting",
+ "Use Flipped Background Image",
+ 512,
+ 768,
+ 12345,
+ "imgs/alter/o2.png",
+ ],
+ [
+ "imgs/alter/i1.jpeg",
+ "imgs/bgs/2.webp",
+ "beautiful woman, cinematic lighting",
+ "Use Background Image",
+ 512,
+ 768,
+ 12345,
+ "imgs/alter/o3.png",
+ ],
+ [
+ "imgs/alter/i1.jpeg",
+ "imgs/bgs/3.webp",
+ "beautiful woman, cinematic lighting",
+ "Use Background Image",
+ 512,
+ 768,
+ 12345,
+ "imgs/alter/o4.png",
+ ],
+ [
+ "imgs/alter/i6.webp",
+ "imgs/bgs/15.png",
+ "handsome man, cinematic lighting",
+ "Use Background Image",
+ 512,
+ 768,
+ 12345,
+ "imgs/alter/o5.png",
+ ],
+]
diff --git a/imgs/alter/i1.jpeg b/imgs/alter/i1.jpeg
new file mode 100644
index 0000000000000000000000000000000000000000..4087d24913dd34d1290dc85308fe82a6570ba30a
--- /dev/null
+++ b/imgs/alter/i1.jpeg
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:a5ce193eeb8d1e013ab4c1090a1e46cdfc58b7f6b806b8ff0d8205ccf1530cb3
+size 137060
diff --git a/imgs/alter/i2.png b/imgs/alter/i2.png
new file mode 100644
index 0000000000000000000000000000000000000000..dca019d9572941b52cfe8de6620b43c6ba1146d2
--- /dev/null
+++ b/imgs/alter/i2.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:d56225cf4087d40c3b0effe7a7fb3a919591dbd94f1c6d6b434762a1f5be1000
+size 2467409
diff --git a/imgs/alter/i3.png b/imgs/alter/i3.png
new file mode 100644
index 0000000000000000000000000000000000000000..d83a5866a04038e56668df7b3f2eb41f012626c3
--- /dev/null
+++ b/imgs/alter/i3.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:94d4834f1469e7bc346686fa0cfcb61628566dcccb444ad120b1ed4f4103d642
+size 1353288
diff --git a/imgs/alter/i4.png b/imgs/alter/i4.png
new file mode 100644
index 0000000000000000000000000000000000000000..12355f016fdbe84fd90c14d691129e88908b9835
--- /dev/null
+++ b/imgs/alter/i4.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:bac675fea0d42d321641e56d42a6a93e420f76977cd9c52298f2c426eaa8c606
+size 1529969
diff --git a/imgs/alter/i5.png b/imgs/alter/i5.png
new file mode 100644
index 0000000000000000000000000000000000000000..3428b1042f68cc46433f381c84f65274a11bd88f
--- /dev/null
+++ b/imgs/alter/i5.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:10d51dac93c5fb4b6b1ac37bf6b2eb4d5c4ea46e22fb8c1175e5c2023e53d2f0
+size 3928047
diff --git a/imgs/alter/i6.webp b/imgs/alter/i6.webp
new file mode 100644
index 0000000000000000000000000000000000000000..4f8fb3521c1d27add1bc93a64b96ba5ae468614d
--- /dev/null
+++ b/imgs/alter/i6.webp
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:dd9e318ae549860e9132c5d97d9fa29703364b1835292ea1efd2942f2f309c44
+size 409926
diff --git a/imgs/alter/o1.png b/imgs/alter/o1.png
new file mode 100644
index 0000000000000000000000000000000000000000..94010b713a7fd5b24b6337a658133d93770548d9
--- /dev/null
+++ b/imgs/alter/o1.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:24d541c89a08fb6f669884b602303967dbafe0eb3b80544a34f61347b2c177ed
+size 1330947
diff --git a/imgs/alter/o2.png b/imgs/alter/o2.png
new file mode 100644
index 0000000000000000000000000000000000000000..99af238471cabd3c653a61c600aae95c06e4eca4
--- /dev/null
+++ b/imgs/alter/o2.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:96bfcd8127c649b63aa1bc139edae4e2960ac24bb61f58c9e293e51da8570fea
+size 1282250
diff --git a/imgs/alter/o3.png b/imgs/alter/o3.png
new file mode 100644
index 0000000000000000000000000000000000000000..afde7eb0c452854ab3e1fe4b345ed024a9494cad
--- /dev/null
+++ b/imgs/alter/o3.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:05e41ea9457055913a10fc00f03b29b2e8309d1a0b07bbcc933d959308d5f38f
+size 1205466
diff --git a/imgs/alter/o4.png b/imgs/alter/o4.png
new file mode 100644
index 0000000000000000000000000000000000000000..d33d4ad94e71bad8b88f3586540d332c79e5c940
--- /dev/null
+++ b/imgs/alter/o4.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:711d987da285578021db30d78853f7397d576f27132329a79adf783a3cadbd7a
+size 1263586
diff --git a/imgs/alter/o5.png b/imgs/alter/o5.png
new file mode 100644
index 0000000000000000000000000000000000000000..967e4101da1af86fe2834a7553ce192039380fef
--- /dev/null
+++ b/imgs/alter/o5.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:991a9090baa56c1071f8a8ecadbddfd70dfaa48fdc78508f5e950b4060ee8ba7
+size 1328543
diff --git a/imgs/bgs/1.webp b/imgs/bgs/1.webp
new file mode 100644
index 0000000000000000000000000000000000000000..6691821e63dbc63f8871e3a00039bf2caea135f4
--- /dev/null
+++ b/imgs/bgs/1.webp
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:79723e97642706e949fc2535814ebcad9f3f49c31f35801f0c04789ccb056728
+size 368524
diff --git a/imgs/bgs/10.webp b/imgs/bgs/10.webp
new file mode 100644
index 0000000000000000000000000000000000000000..47d16163daf309cfcf8b648a3ac6b1ae3bcc2c9a
--- /dev/null
+++ b/imgs/bgs/10.webp
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:7728f23767c3bc2d5c5a43743707d832eff47d1e34a45bb8bb680bddcecd8218
+size 219184
diff --git a/imgs/bgs/11.png b/imgs/bgs/11.png
new file mode 100644
index 0000000000000000000000000000000000000000..f5bcfafd1ac1fbc4d802b03e46d5145c14f8dca6
--- /dev/null
+++ b/imgs/bgs/11.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:3d4139ba0c6b88b4775bc8ba09a7cf34e9e7519d68e7cd6f1087e9246d4b8ca6
+size 1369512
diff --git a/imgs/bgs/12.png b/imgs/bgs/12.png
new file mode 100644
index 0000000000000000000000000000000000000000..ce1547caa4c33c71b64fcbf65d88dc2d071805db
--- /dev/null
+++ b/imgs/bgs/12.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:77cb386a40073f0523777ecb14364a2e6dc97cb0bcc548468a2219040088df9d
+size 1476495
diff --git a/imgs/bgs/13.png b/imgs/bgs/13.png
new file mode 100644
index 0000000000000000000000000000000000000000..cf52dfc33f32d00e670315a8dba827b11e3fd0cc
--- /dev/null
+++ b/imgs/bgs/13.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:bdf04609ad05124c5b4e338f84eaf5fdb59dc4a3a69279ca365915ee3727e4d6
+size 1573911
diff --git a/imgs/bgs/14.png b/imgs/bgs/14.png
new file mode 100644
index 0000000000000000000000000000000000000000..4c6ae6196c5c2b5e1870a10dd3e56700a4a0ee73
--- /dev/null
+++ b/imgs/bgs/14.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:b79f72ca34e8f0483aa59373d4e61e753b5a70ac5995e638e1d3e1162c6702b5
+size 1937136
diff --git a/imgs/bgs/15.png b/imgs/bgs/15.png
new file mode 100644
index 0000000000000000000000000000000000000000..887943684ad23a4c69d9a4b565e67642d26c2686
--- /dev/null
+++ b/imgs/bgs/15.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:bb9e6a233d603f35c28ff79a310468196b432fda6d5240115b4d5f051ebca7ec
+size 1416001
diff --git a/imgs/bgs/2.webp b/imgs/bgs/2.webp
new file mode 100644
index 0000000000000000000000000000000000000000..93b88a228f93718140580e97b571cd7d8bdffb35
--- /dev/null
+++ b/imgs/bgs/2.webp
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:ef11950845a2a89a6007f92ff9c1b85c34d47f3c8162577ca27f9e9ea4245d6a
+size 509094
diff --git a/imgs/bgs/3.webp b/imgs/bgs/3.webp
new file mode 100644
index 0000000000000000000000000000000000000000..996bfeecea64e0600a78ed871026e9b53f63fac2
--- /dev/null
+++ b/imgs/bgs/3.webp
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:67193153dcc5ba1484a5b9e720f3721a4fcbc3e85e24422759ad2c6a347ca525
+size 492130
diff --git a/imgs/bgs/4.webp b/imgs/bgs/4.webp
new file mode 100644
index 0000000000000000000000000000000000000000..6eb522e62677a65a07ed5fb78d2ea793ca430fe3
--- /dev/null
+++ b/imgs/bgs/4.webp
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:c4e1892cc08306bdcaa48788cf5164b71eab99e1ea7b91d633a1875d8c7f0f67
+size 1456492
diff --git a/imgs/bgs/5.webp b/imgs/bgs/5.webp
new file mode 100644
index 0000000000000000000000000000000000000000..7d607e2b22b928c990506cc08861db3cd9f25fc5
--- /dev/null
+++ b/imgs/bgs/5.webp
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:68246aafe7fc67e208cf1f5da1c00f4d80902504540eaa390745642713835691
+size 1253980
diff --git a/imgs/bgs/6.webp b/imgs/bgs/6.webp
new file mode 100644
index 0000000000000000000000000000000000000000..e05337365ec72b11a9b4ceafe4e8bacc6c76d084
--- /dev/null
+++ b/imgs/bgs/6.webp
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:fda07617419020c3081fd4d44f835d823ddeb91a4963388ddc6febce8e2b7385
+size 1165386
diff --git a/imgs/bgs/7.webp b/imgs/bgs/7.webp
new file mode 100644
index 0000000000000000000000000000000000000000..7ff1330fb61efdeebb3acd41a207e70a613ccf6b
--- /dev/null
+++ b/imgs/bgs/7.webp
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:e341603d4e4866364b05f7466ce44bec5731c39a5a65cd4dfbe511e9d4d19580
+size 399760
diff --git a/imgs/bgs/8.webp b/imgs/bgs/8.webp
new file mode 100644
index 0000000000000000000000000000000000000000..d754c6c9318988efe7bbe4c14607ab557f6b1821
--- /dev/null
+++ b/imgs/bgs/8.webp
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:cd8bc1b6030eaf93c0bff0512592816aff379a3fc4d5ee08a0459af09920d770
+size 288436
diff --git a/imgs/bgs/9.webp b/imgs/bgs/9.webp
new file mode 100644
index 0000000000000000000000000000000000000000..ffcd62a35e967427535ed13d857d08bfb0cc9898
--- /dev/null
+++ b/imgs/bgs/9.webp
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:06e015f739e8d07322398514897f8ab7eddfe43adb733ea47dd283eed97e7270
+size 215764
diff --git a/imgs/i1.webp b/imgs/i1.webp
new file mode 100644
index 0000000000000000000000000000000000000000..5b36f63ac91f6241678e05e91bf02542d9146a9e
--- /dev/null
+++ b/imgs/i1.webp
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:a951c7aa4e82b7df8574035ac46536eefbd80c977646662fcbab39989e9078cc
+size 400970
diff --git a/imgs/i10.png b/imgs/i10.png
new file mode 100644
index 0000000000000000000000000000000000000000..629bc5c3a457220edfc794986f30f40f3f2ba78e
--- /dev/null
+++ b/imgs/i10.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:ccff0796c08a209cd065179d4b998337eb180f18ae3bb556c413c3711cdd24c6
+size 1963005
diff --git a/imgs/i11.png b/imgs/i11.png
new file mode 100644
index 0000000000000000000000000000000000000000..92facd4007e26ba31063268449261ed97d39489b
--- /dev/null
+++ b/imgs/i11.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:ed8cba962fd16542a222be64f26e0b7ddc91e8f9fb5c96a75c523ae780173de5
+size 2100544
diff --git a/imgs/i13.png b/imgs/i13.png
new file mode 100644
index 0000000000000000000000000000000000000000..3b054d718e266a1f5e659c24f676e0ca67be5946
--- /dev/null
+++ b/imgs/i13.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:56afb68c0131fa2e736cef03eb571da16f785ebb06d4b697e8f13466dd3830ce
+size 2050292
diff --git a/imgs/i14.png b/imgs/i14.png
new file mode 100644
index 0000000000000000000000000000000000000000..16d34c81ae6b40690498bd11360d7c8545ad5f4f
--- /dev/null
+++ b/imgs/i14.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:c97497a295cb7139108d0340998de5655d374ff20ba1c32d2ff7274a5be9ce63
+size 1748947
diff --git a/imgs/i15.png b/imgs/i15.png
new file mode 100644
index 0000000000000000000000000000000000000000..f963f86ab2ad2b09fe45f1a178019f915d0ba05a
--- /dev/null
+++ b/imgs/i15.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:3277617e4869827c30b71f7bd1ec7ae5dc9c9dc3051c37423a909aa905570a91
+size 1808217
diff --git a/imgs/i16.png b/imgs/i16.png
new file mode 100644
index 0000000000000000000000000000000000000000..681e690ad18499efe3525a2e3e1d87585831a7d7
--- /dev/null
+++ b/imgs/i16.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:eef58d97a515ab2695fb05c05b56a76870fe630e7997aa5a5e213fa2b92c69f8
+size 1783204
diff --git a/imgs/i3.png b/imgs/i3.png
new file mode 100644
index 0000000000000000000000000000000000000000..422e9bd321b4df6feec68df38a61968eaf2dfcfb
--- /dev/null
+++ b/imgs/i3.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:30de5080182adef52d66a41259701e230140a42ca3e2fe89124bb686ef539974
+size 2336084
diff --git a/imgs/i5.png b/imgs/i5.png
new file mode 100644
index 0000000000000000000000000000000000000000..e04752dd500fcf559eb772e63faf92d8224bed37
--- /dev/null
+++ b/imgs/i5.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:3504d7e23807e0f1ea2fc2e0c23af3c977e22cb8e3c40ecef9f36e0300ca4794
+size 2885547
diff --git a/imgs/i6.jpg b/imgs/i6.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..7ca478ffbd70a9b1a0a7e9b52719c41bff0522b9
--- /dev/null
+++ b/imgs/i6.jpg
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:5269e4c154d8328902074d869e3e98c170785e7600283590c9ac0d9992e5b0b4
+size 48329
diff --git a/imgs/i7.jpg b/imgs/i7.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..67900278bdad42951dd080244fd09b0e41b359a5
--- /dev/null
+++ b/imgs/i7.jpg
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:487f296512de3692a4ca9196cc1281bf436e3e842190482f369db12b524aba3c
+size 182885
diff --git a/imgs/i8.webp b/imgs/i8.webp
new file mode 100644
index 0000000000000000000000000000000000000000..bb1b91f23b49fdd4078c7b71233cd127812c7788
--- /dev/null
+++ b/imgs/i8.webp
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:7c4f83605a5931be8cf4824f7249c58f1031d39178d2083b63b7d2129582563f
+size 481734
diff --git a/imgs/i9.png b/imgs/i9.png
new file mode 100644
index 0000000000000000000000000000000000000000..c762a6e6c6c7977d16e5a2ca088e2a64a9ba01ac
--- /dev/null
+++ b/imgs/i9.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:00e3a1a67f5de4052bb090a4cadccf50b9ae7a021d46609a366600d664aadec9
+size 1843723
diff --git a/imgs/o1.png b/imgs/o1.png
new file mode 100644
index 0000000000000000000000000000000000000000..7c41526483cfad5d3d83ce138735e11f7aea77ae
--- /dev/null
+++ b/imgs/o1.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:acca1e4e933ed7393813080607c85170b400c1271bca9286d503570c8558c191
+size 1372842
diff --git a/imgs/o10.png b/imgs/o10.png
new file mode 100644
index 0000000000000000000000000000000000000000..b7115f19838fd06455b51c3e153530d25bad8b3f
--- /dev/null
+++ b/imgs/o10.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:42d58e082fc8b752b7daf5d08c8eff4dd5317826900d95c07d26ef0ee6660ea7
+size 1535827
diff --git a/imgs/o11.png b/imgs/o11.png
new file mode 100644
index 0000000000000000000000000000000000000000..b7ebc17dfbee394b18532d73be8601bd32833c26
--- /dev/null
+++ b/imgs/o11.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:b310298cc25493b778936b2c04bdee4e38cc415d900c7a4c1985830ca57d9d80
+size 1281532
diff --git a/imgs/o12.png b/imgs/o12.png
new file mode 100644
index 0000000000000000000000000000000000000000..bb756f9b555ae1a13e0e330a725b8bbdd9bb0d0b
--- /dev/null
+++ b/imgs/o12.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:13aec18ac9d138cee55d6cd7fb68b79198c96ad33b29f171b9ee269743bdaa8d
+size 1275262
diff --git a/imgs/o13.png b/imgs/o13.png
new file mode 100644
index 0000000000000000000000000000000000000000..1e3786aaf92c3bec5b213d2865bc31f122881cd2
--- /dev/null
+++ b/imgs/o13.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:efd87090750d3203158894fe375c25b3892eb6810bed40ed1367eb27b7eeec28
+size 1197524
diff --git a/imgs/o14.png b/imgs/o14.png
new file mode 100644
index 0000000000000000000000000000000000000000..f5fb64747b54221cd50cf6d29404864b79c4586c
--- /dev/null
+++ b/imgs/o14.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:6262149581c7391c2fb8e1fcb42c55e0aca39f765e552872368d734cfea9595b
+size 989806
diff --git a/imgs/o15.png b/imgs/o15.png
new file mode 100644
index 0000000000000000000000000000000000000000..35ea928fa75460853687c469bb3d8893b721caf2
--- /dev/null
+++ b/imgs/o15.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:71f795f743b7550b8cf454576e467e0a0e8d0e4db2ce8846179b0cfc4ca5102a
+size 1166093
diff --git a/imgs/o16.png b/imgs/o16.png
new file mode 100644
index 0000000000000000000000000000000000000000..1895b63a11cf6321e2209f971603c898ada904c9
--- /dev/null
+++ b/imgs/o16.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:63fe02686847b9e457ef9bcbdb0cbc7b4a9deecf7f5cc3c3b0f9aa0db284d1e5
+size 1219527
diff --git a/imgs/o2.png b/imgs/o2.png
new file mode 100644
index 0000000000000000000000000000000000000000..381b7c6e3e382ffa8e3f29eaf6a3c465b86a3792
--- /dev/null
+++ b/imgs/o2.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:9e2ba413e771bd2ab2fb0ffd773c9aefd1ad6e1baf31742c8186cffb9166f83c
+size 1443867
diff --git a/imgs/o3.png b/imgs/o3.png
new file mode 100644
index 0000000000000000000000000000000000000000..bc3b8eea85c75b87148da58a1f212c1a43050983
--- /dev/null
+++ b/imgs/o3.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:139ede0d0513e239d0549c37f3db4d0a9e48fdbb3fefbbbb7ed1de74af092755
+size 927935
diff --git a/imgs/o4.png b/imgs/o4.png
new file mode 100644
index 0000000000000000000000000000000000000000..1dda939aae01c1a63ee52fa8eb7accc121f1e6c6
--- /dev/null
+++ b/imgs/o4.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:f992a2a91ce25f535c726d96491fd85645229f599896e02362c9586fffff2a25
+size 1110298
diff --git a/imgs/o5.png b/imgs/o5.png
new file mode 100644
index 0000000000000000000000000000000000000000..806f0c5599f474b8d4b36135aaa1d18254642e9f
--- /dev/null
+++ b/imgs/o5.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:3ccafb2fa26bc1dfb676b1419e3d404b4201c1ebf4bac3709c9aa8ecc7612802
+size 965678
diff --git a/imgs/o6.png b/imgs/o6.png
new file mode 100644
index 0000000000000000000000000000000000000000..d8d65d567818718b0c8277304784ac21ec7797f9
--- /dev/null
+++ b/imgs/o6.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:d12243aeca9838a8677656809ac0ab65b877a8755a22a1fa26e512c5dcb06c9b
+size 1074591
diff --git a/imgs/o7.png b/imgs/o7.png
new file mode 100644
index 0000000000000000000000000000000000000000..30ef6bb08a35e73caa3ad5297193b2c5f4055c01
--- /dev/null
+++ b/imgs/o7.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:08eb15fbdac46c6be7954ab63a5c51089c330205e6d820b32b2906ff1d0ed8f6
+size 1130739
diff --git a/imgs/o8.png b/imgs/o8.png
new file mode 100644
index 0000000000000000000000000000000000000000..2efdc80163ce787b61cdca1ded7a685a2c3e4ec8
--- /dev/null
+++ b/imgs/o8.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:fad9f813b88e0ad0673b5aa1d19b2a0fb1fa02bf10bd9726746099d3f39a993d
+size 863481
diff --git a/imgs/o9.png b/imgs/o9.png
new file mode 100644
index 0000000000000000000000000000000000000000..14d2822654c99950d56b9904282c633ef11c74e1
--- /dev/null
+++ b/imgs/o9.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:83d6e2e539efb64f8cad73767747b388281c949d5c3f150c636fbcd8afb8aac0
+size 877096