TastyRice commited on
Commit
f38d68c
1 Parent(s): 78a695f

Upload 5 files

Browse files
Files changed (4) hide show
  1. config.py +111 -0
  2. demo.ipynb +114 -0
  3. style.css +63 -0
  4. utils.py +182 -0
config.py ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ examples = [
2
+ "1girl, souryuu asuka langley, neon genesis evangelion, plugsuit, pilot suit, red bodysuit, sitting, crossing legs, black eye patch, cat hat, throne, symmetrical, looking down, from bottom, looking at viewer, outdoors",
3
+ "1boy, male focus, yuuki makoto \(persona 3\), persona 3, black jacket, white shirt, long sleeves, closed mouth, glowing eyes, gun, hair over one eye, holding gun, handgun, looking at viewer, solo, upper body",
4
+ "1girl, makima \(chainsaw man\), chainsaw man, black jacket, black necktie, black pants, braid, business suit, fingernails, formal, hand on own chin, jacket on shoulders, light smile, long sleeves, looking at viewer, looking up, medium breasts, office lady, smile, solo, suit, upper body, white shirt, outdoors",
5
+ "1boy, male focus, gojou satoru, jujutsu kaisen, black jacket, blindfold lift, blue eyes, glowing, glowing eyes, high collar, jacket, jujutsu tech uniform, solo, grin, white hair",
6
+ "1girl, cagliostro, granblue fantasy, violet eyes, standing, hand on own chin, looking at object, smile, closed mouth, table, beaker, glass tube, experiment apparatus, dark room, laboratory",
7
+ "kimi no na wa., building, cityscape, cloud, cloudy sky, gradient sky, lens flare, no humans, outdoors, power lines, scenery, shooting star, sky, sparkle, star \(sky\), starry sky, sunset, tree, utility pole",
8
+ ]
9
+
10
+ quality_prompt_list = [
11
+ {
12
+ "name": "(None)",
13
+ "prompt": "{prompt}",
14
+ "negative_prompt": "nsfw, lowres",
15
+ },
16
+ {
17
+ "name": "Standard v3.0",
18
+ "prompt": "{prompt}, masterpiece, best quality",
19
+ "negative_prompt": "nsfw, lowres, bad anatomy, bad hands, text, error, missing fingers, extra digit, fewer digits, cropped, worst quality, low quality, normal quality, jpeg artifacts, signature, watermark, username, blurry, artist name",
20
+ },
21
+ {
22
+ "name": "Standard v3.1",
23
+ "prompt": "{prompt}, masterpiece, best quality, very aesthetic, absurdres",
24
+ "negative_prompt": "nsfw, lowres, (bad), text, error, fewer, extra, missing, worst quality, jpeg artifacts, low quality, watermark, unfinished, displeasing, oldest, early, chromatic aberration, signature, extra digits, artistic error, username, scan, [abstract]",
25
+ },
26
+ {
27
+ "name": "Light v3.1",
28
+ "prompt": "{prompt}, (masterpiece), best quality, very aesthetic, perfect face",
29
+ "negative_prompt": "nsfw, (low quality, worst quality:1.2), very displeasing, 3d, watermark, signature, ugly, poorly drawn",
30
+ },
31
+ {
32
+ "name": "Heavy v3.1",
33
+ "prompt": "{prompt}, (masterpiece), (best quality), (ultra-detailed), very aesthetic, illustration, disheveled hair, perfect composition, moist skin, intricate details",
34
+ "negative_prompt": "nsfw, longbody, lowres, bad anatomy, bad hands, missing fingers, pubic hair, extra digit, fewer digits, cropped, worst quality, low quality, very displeasing",
35
+ },
36
+ ]
37
+
38
+ sampler_list = [
39
+ "DPM++ 2M Karras",
40
+ "DPM++ SDE Karras",
41
+ "DPM++ 2M SDE Karras",
42
+ "Euler",
43
+ "Euler a",
44
+ "DDIM",
45
+ ]
46
+
47
+ aspect_ratios = [
48
+ "1024 x 1024",
49
+ "1152 x 896",
50
+ "896 x 1152",
51
+ "1216 x 832",
52
+ "832 x 1216",
53
+ "1344 x 768",
54
+ "768 x 1344",
55
+ "1536 x 640",
56
+ "640 x 1536",
57
+ "Custom",
58
+ ]
59
+
60
+ style_list = [
61
+ {
62
+ "name": "(None)",
63
+ "prompt": "{prompt}",
64
+ "negative_prompt": "",
65
+ },
66
+ {
67
+ "name": "Cinematic",
68
+ "prompt": "{prompt}, cinematic still, emotional, harmonious, vignette, highly detailed, high budget, bokeh, cinemascope, moody, epic, gorgeous, film grain, grainy",
69
+ "negative_prompt": "nsfw, cartoon, graphic, text, painting, crayon, graphite, abstract, glitch, deformed, mutated, ugly, disfigured",
70
+ },
71
+ {
72
+ "name": "Photographic",
73
+ "prompt": "{prompt}, cinematic photo, 35mm photograph, film, bokeh, professional, 4k, highly detailed",
74
+ "negative_prompt": "nsfw, drawing, painting, crayon, sketch, graphite, impressionist, noisy, blurry, soft, deformed, ugly",
75
+ },
76
+ {
77
+ "name": "Anime",
78
+ "prompt": "{prompt}, anime artwork, anime style, key visual, vibrant, studio anime, highly detailed",
79
+ "negative_prompt": "nsfw, photo, deformed, black and white, realism, disfigured, low contrast",
80
+ },
81
+ {
82
+ "name": "Manga",
83
+ "prompt": "{prompt}, manga style, vibrant, high-energy, detailed, iconic, Japanese comic style",
84
+ "negative_prompt": "nsfw, ugly, deformed, noisy, blurry, low contrast, realism, photorealistic, Western comic style",
85
+ },
86
+ {
87
+ "name": "Digital Art",
88
+ "prompt": "{prompt}, concept art, digital artwork, illustrative, painterly, matte painting, highly detailed",
89
+ "negative_prompt": "nsfw, photo, photorealistic, realism, ugly",
90
+ },
91
+ {
92
+ "name": "Pixel art",
93
+ "prompt": "{prompt}, pixel-art, low-res, blocky, pixel art style, 8-bit graphics",
94
+ "negative_prompt": "nsfw, sloppy, messy, blurry, noisy, highly detailed, ultra textured, photo, realistic",
95
+ },
96
+ {
97
+ "name": "Fantasy art",
98
+ "prompt": "{prompt}, ethereal fantasy concept art, magnificent, celestial, ethereal, painterly, epic, majestic, magical, fantasy art, cover art, dreamy",
99
+ "negative_prompt": "nsfw, photographic, realistic, realism, 35mm film, dslr, cropped, frame, text, deformed, glitch, noise, noisy, off-center, deformed, cross-eyed, closed eyes, bad anatomy, ugly, disfigured, sloppy, duplicate, mutated, black and white",
100
+ },
101
+ {
102
+ "name": "Neonpunk",
103
+ "prompt": "{prompt}, neonpunk style, cyberpunk, vaporwave, neon, vibes, vibrant, stunningly beautiful, crisp, detailed, sleek, ultramodern, magenta highlights, dark purple shadows, high contrast, cinematic, ultra detailed, intricate, professional",
104
+ "negative_prompt": "nsfw, painting, drawing, illustration, glitch, deformed, mutated, cross-eyed, ugly, disfigured",
105
+ },
106
+ {
107
+ "name": "3D Model",
108
+ "prompt": "{prompt}, professional 3d model, octane render, highly detailed, volumetric, dramatic lighting",
109
+ "negative_prompt": "nsfw, ugly, deformed, noisy, low poly, blurry, painting",
110
+ },
111
+ ]
demo.ipynb ADDED
@@ -0,0 +1,114 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": null,
6
+ "id": "538a3f0c-50c1-4952-9fcc-070d365c9a0f",
7
+ "metadata": {
8
+ "id": "538a3f0c-50c1-4952-9fcc-070d365c9a0f",
9
+ "scrolled": true
10
+ },
11
+ "outputs": [],
12
+ "source": [
13
+ "import os\n",
14
+ "import subprocess\n",
15
+ "from threading import Timer\n",
16
+ "from queue import Queue\n",
17
+ "\n",
18
+ "def is_colab():\n",
19
+ " try:\n",
20
+ " import google.colab\n",
21
+ " return True\n",
22
+ " except ImportError:\n",
23
+ " return False\n",
24
+ "\n",
25
+ "ROOT_DIR = \"/workspace/\" if not is_colab() else \"/content/\"\n",
26
+ "REPO_URL = \"https://huggingface.co/spaces/Tasty-Rice/Magic_on_paper\"\n",
27
+ "REPO_DIR = os.path.join(ROOT_DIR, \"animagine-xl\")\n",
28
+ "\n",
29
+ "NGROK_TOKEN = \"\"\n",
30
+ "NGROK_SUBDOMAIN = \"\"\n",
31
+ "PORT = 7860\n",
32
+ "\n",
33
+ "# os.environ[\"HF_TOKEN\"] = \"\"\n",
34
+ "os.environ[\"IS_COLAB\"] = \"1\"\n",
35
+ "os.environ[\"MODEL\"] = \"https://huggingface.co/Tasty-Rice/Magic_on_paper/blob/main/Magic_on_paper-SDXL-v3.safetensors\"\n",
36
+ "os.environ[\"CACHE_EXAMPLES\"] = \"1\"\n",
37
+ "\n",
38
+ "def clone_repository(url, directory, branch=None):\n",
39
+ " subprocess.run([\"git\", \"clone\", url, directory], check=True)\n",
40
+ " if branch:\n",
41
+ " subprocess.run([\"git\", \"checkout\", branch], cwd=directory, check=True)\n",
42
+ "\n",
43
+ "def install_dependencies(directory):\n",
44
+ " dependencies = [\"accelerate==0.27.2\", \"diffusers==0.26.3\", \"gradio==4.20.0\",\n",
45
+ " \"invisible-watermark==0.2.0\", \"spaces==0.24.0\", \"omegaconf==2.3.0\", \"timm==0.9.10\"]\n",
46
+ " if is_colab():\n",
47
+ " subprocess.run([\"pip\", \"install\"] + dependencies, check=True)\n",
48
+ " else:\n",
49
+ " requirements_path = os.path.join(directory, \"requirements.txt\")\n",
50
+ " subprocess.run([\"pip\", \"install\", \"-r\", requirements_path], check=True)\n",
51
+ "\n",
52
+ "def setup_ngrok_tunnel(port, queue, auth_token, subdomain):\n",
53
+ " ngrok.set_auth_token(auth_token)\n",
54
+ " url = ngrok.connect(port, bind_tls=True, subdomain=subdomain)\n",
55
+ " queue.put(url)\n",
56
+ "\n",
57
+ "def main():\n",
58
+ " if not os.path.exists(REPO_DIR):\n",
59
+ " print(f\"Cloning repository to {REPO_DIR}\")\n",
60
+ " clone_repository(REPO_URL, REPO_DIR)\n",
61
+ "\n",
62
+ " print(\"Installing required Python libraries\")\n",
63
+ " install_dependencies(REPO_DIR)\n",
64
+ " print(\"Done!\")\n",
65
+ "\n",
66
+ " os.chdir(REPO_DIR)\n",
67
+ "\n",
68
+ " if NGROK_TOKEN:\n",
69
+ " try:\n",
70
+ " from pyngrok import conf, ngrok\n",
71
+ " except ImportError:\n",
72
+ " subprocess.run([\"pip\", \"install\", \"-qqqq\", \"--upgrade\", \"setuptools\"], check=True)\n",
73
+ " subprocess.run([\"pip\", \"install\", \"-qqqq\", \"-U\", \"pyngrok\"], check=True)\n",
74
+ " from pyngrok import conf, ngrok\n",
75
+ "\n",
76
+ " ngrok.kill()\n",
77
+ " ngrok_output_queue = Queue()\n",
78
+ " ngrok_thread = Timer(2, setup_ngrok_tunnel, args=(PORT, ngrok_output_queue, NGROK_TOKEN, NGROK_SUBDOMAIN))\n",
79
+ " ngrok_thread.start()\n",
80
+ " ngrok_thread.join()\n",
81
+ " print(ngrok_output_queue.get())\n",
82
+ "\n",
83
+ " !python app.py\n",
84
+ "\n",
85
+ "if __name__ == \"__main__\":\n",
86
+ " main()"
87
+ ]
88
+ }
89
+ ],
90
+ "metadata": {
91
+ "colab": {
92
+ "provenance": []
93
+ },
94
+ "kernelspec": {
95
+ "display_name": "Python 3 (ipykernel)",
96
+ "language": "python",
97
+ "name": "python3"
98
+ },
99
+ "language_info": {
100
+ "codemirror_mode": {
101
+ "name": "ipython",
102
+ "version": 3
103
+ },
104
+ "file_extension": ".py",
105
+ "mimetype": "text/x-python",
106
+ "name": "python",
107
+ "nbconvert_exporter": "python",
108
+ "pygments_lexer": "ipython3",
109
+ "version": "3.10.12"
110
+ }
111
+ },
112
+ "nbformat": 4,
113
+ "nbformat_minor": 5
114
+ }
style.css ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ :root {
2
+ --title-font-size: clamp(1.5rem, 6vw, 3rem);
3
+ --subtitle-font-size: clamp(1rem, 2vw, 1.2rem);
4
+ }
5
+
6
+ h1 {
7
+ text-align: center;
8
+ font-size: var(--title-font-size);
9
+ display: block;
10
+ }
11
+
12
+ h2 {
13
+ text-align: center;
14
+ font-size: 2rem;
15
+ display: block;
16
+ }
17
+
18
+ #duplicate-button {
19
+ display: block;
20
+ margin: 1rem auto;
21
+ color: #fff;
22
+ background: #1565c0;
23
+ border-radius: 100vh;
24
+ padding: 0.5rem 1rem;
25
+ }
26
+
27
+ #component-0 {
28
+ max-width: 85%;
29
+ margin: 2rem auto;
30
+ padding: 2rem;
31
+ }
32
+
33
+ @media (max-width: 600px) {
34
+ #component-0 {
35
+ max-width: 100%;
36
+ padding: 0.5rem;
37
+ }
38
+ }
39
+
40
+ #title-container {
41
+ text-align: center;
42
+ padding: 2rem 0;
43
+ }
44
+
45
+ #title {
46
+ font-size: var(--title-font-size);
47
+ color: #333;
48
+ font-family: 'Helvetica Neue', sans-serif;
49
+ text-transform: uppercase;
50
+ background: transparent;
51
+ }
52
+
53
+ #title span {
54
+ background: linear-gradient(45deg, #4EACEF, #28b485);
55
+ background-clip: text;
56
+ color: transparent;
57
+ }
58
+
59
+ #subtitle {
60
+ text-align: center;
61
+ font-size: var(--subtitle-font-size);
62
+ margin-top: 1rem;
63
+ }
utils.py ADDED
@@ -0,0 +1,182 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gc
2
+ import os
3
+ import random
4
+ import numpy as np
5
+ import json
6
+ import torch
7
+ import uuid
8
+ from PIL import Image, PngImagePlugin
9
+ from datetime import datetime
10
+ from dataclasses import dataclass
11
+ from typing import Callable, Dict, Optional, Tuple
12
+ from diffusers import (
13
+ DDIMScheduler,
14
+ DPMSolverMultistepScheduler,
15
+ DPMSolverSinglestepScheduler,
16
+ EulerAncestralDiscreteScheduler,
17
+ EulerDiscreteScheduler,
18
+ )
19
+
20
+ MAX_SEED = np.iinfo(np.int32).max
21
+
22
+
23
+ @dataclass
24
+ class StyleConfig:
25
+ prompt: str
26
+ negative_prompt: str
27
+
28
+
29
+ def randomize_seed_fn(seed: int, randomize_seed: bool) -> int:
30
+ if randomize_seed:
31
+ seed = random.randint(0, MAX_SEED)
32
+ return seed
33
+
34
+
35
+ def seed_everything(seed: int) -> torch.Generator:
36
+ torch.manual_seed(seed)
37
+ torch.cuda.manual_seed_all(seed)
38
+ np.random.seed(seed)
39
+ generator = torch.Generator()
40
+ generator.manual_seed(seed)
41
+ return generator
42
+
43
+
44
+ def parse_aspect_ratio(aspect_ratio: str) -> Optional[Tuple[int, int]]:
45
+ if aspect_ratio == "Custom":
46
+ return None
47
+ width, height = aspect_ratio.split(" x ")
48
+ return int(width), int(height)
49
+
50
+
51
+ def aspect_ratio_handler(
52
+ aspect_ratio: str, custom_width: int, custom_height: int
53
+ ) -> Tuple[int, int]:
54
+ if aspect_ratio == "Custom":
55
+ return custom_width, custom_height
56
+ else:
57
+ width, height = parse_aspect_ratio(aspect_ratio)
58
+ return width, height
59
+
60
+
61
+ def get_scheduler(scheduler_config: Dict, name: str) -> Optional[Callable]:
62
+ scheduler_factory_map = {
63
+ "DPM++ 2M Karras": lambda: DPMSolverMultistepScheduler.from_config(
64
+ scheduler_config, use_karras_sigmas=True
65
+ ),
66
+ "DPM++ SDE Karras": lambda: DPMSolverSinglestepScheduler.from_config(
67
+ scheduler_config, use_karras_sigmas=True
68
+ ),
69
+ "DPM++ 2M SDE Karras": lambda: DPMSolverMultistepScheduler.from_config(
70
+ scheduler_config, use_karras_sigmas=True, algorithm_type="sde-dpmsolver++"
71
+ ),
72
+ "Euler": lambda: EulerDiscreteScheduler.from_config(scheduler_config),
73
+ "Euler a": lambda: EulerAncestralDiscreteScheduler.from_config(
74
+ scheduler_config
75
+ ),
76
+ "DDIM": lambda: DDIMScheduler.from_config(scheduler_config),
77
+ }
78
+ return scheduler_factory_map.get(name, lambda: None)()
79
+
80
+
81
+ def free_memory() -> None:
82
+ torch.cuda.empty_cache()
83
+ gc.collect()
84
+
85
+
86
+ def preprocess_prompt(
87
+ style_dict,
88
+ style_name: str,
89
+ positive: str,
90
+ negative: str = "",
91
+ add_style: bool = True,
92
+ ) -> Tuple[str, str]:
93
+ p, n = style_dict.get(style_name, style_dict["(None)"])
94
+
95
+ if add_style and positive.strip():
96
+ formatted_positive = p.format(prompt=positive)
97
+ else:
98
+ formatted_positive = positive
99
+
100
+ combined_negative = n
101
+ if negative.strip():
102
+ if combined_negative:
103
+ combined_negative += ", " + negative
104
+ else:
105
+ combined_negative = negative
106
+
107
+ return formatted_positive, combined_negative
108
+
109
+
110
+ def common_upscale(
111
+ samples: torch.Tensor,
112
+ width: int,
113
+ height: int,
114
+ upscale_method: str,
115
+ ) -> torch.Tensor:
116
+ return torch.nn.functional.interpolate(
117
+ samples, size=(height, width), mode=upscale_method
118
+ )
119
+
120
+
121
+ def upscale(
122
+ samples: torch.Tensor, upscale_method: str, scale_by: float
123
+ ) -> torch.Tensor:
124
+ width = round(samples.shape[3] * scale_by)
125
+ height = round(samples.shape[2] * scale_by)
126
+ return common_upscale(samples, width, height, upscale_method)
127
+
128
+
129
+ def load_wildcard_files(wildcard_dir: str) -> Dict[str, str]:
130
+ wildcard_files = {}
131
+ for file in os.listdir(wildcard_dir):
132
+ if file.endswith(".txt"):
133
+ key = f"__{file.split('.')[0]}__" # Create a key like __character__
134
+ wildcard_files[key] = os.path.join(wildcard_dir, file)
135
+ return wildcard_files
136
+
137
+
138
+ def get_random_line_from_file(file_path: str) -> str:
139
+ with open(file_path, "r") as file:
140
+ lines = file.readlines()
141
+ if not lines:
142
+ return ""
143
+ return random.choice(lines).strip()
144
+
145
+
146
+ def add_wildcard(prompt: str, wildcard_files: Dict[str, str]) -> str:
147
+ for key, file_path in wildcard_files.items():
148
+ if key in prompt:
149
+ wildcard_line = get_random_line_from_file(file_path)
150
+ prompt = prompt.replace(key, wildcard_line)
151
+ return prompt
152
+
153
+
154
+ def preprocess_image_dimensions(width, height):
155
+ if width % 8 != 0:
156
+ width = width - (width % 8)
157
+ if height % 8 != 0:
158
+ height = height - (height % 8)
159
+ return width, height
160
+
161
+
162
+ def save_image(image, metadata, output_dir, is_colab):
163
+ if is_colab:
164
+ current_time = datetime.now().strftime("%Y%m%d_%H%M%S")
165
+ filename = f"image_{current_time}.png"
166
+ else:
167
+ filename = str(uuid.uuid4()) + ".png"
168
+ os.makedirs(output_dir, exist_ok=True)
169
+ filepath = os.path.join(output_dir, filename)
170
+ metadata_str = json.dumps(metadata)
171
+ info = PngImagePlugin.PngInfo()
172
+ info.add_text("metadata", metadata_str)
173
+ image.save(filepath, "PNG", pnginfo=info)
174
+ return filepath
175
+
176
+
177
+ def is_google_colab():
178
+ try:
179
+ import google.colab
180
+ return True
181
+ except:
182
+ return False