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