WiNE-iNEFF commited on
Commit
87a76f1
·
verified ·
1 Parent(s): 1c2602b

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +127 -108
app.py CHANGED
@@ -1,108 +1,127 @@
1
- import gradio as gr
2
- import torch, torchvision
3
- from torchvision import transforms
4
- import torch.nn.functional as F
5
- import numpy as np
6
- from time import time, ctime
7
- from PIL import Image, ImageColor
8
- from diffusers import DDPMPipeline
9
- from diffusers import DDIMScheduler
10
-
11
- device = (
12
- "mps"
13
- if torch.backends.mps.is_available()
14
- else "cuda"
15
- if torch.cuda.is_available()
16
- else "cpu"
17
- )
18
-
19
- pipeline_name = 'WiNE-iNEFF/Minecraft-Skin-Diffusion-V2'
20
- image_pipe = DDPMPipeline.from_pretrained(pipeline_name, use_safetensors=True).to(device)
21
- try:
22
- scheduler = DDIMScheduler.from_pretrained(pipeline_name)
23
- except:
24
- scheduler = DDIMScheduler.from_pretrained(pipeline_name, subfolder="scheduler")
25
- scheduler.set_timesteps(num_inference_steps=25)
26
-
27
- def show_images_save(x):
28
- grid = torchvision.utils.make_grid(x, nrow=4, padding=0)
29
- grid_im = grid.detach().cpu().permute(1, 2, 0).clip(0, 1) * 255
30
- grid_im = Image.fromarray(np.array(grid_im).astype(np.uint8))
31
- #CROP
32
- width, height = grid_im.size
33
- sav = []
34
- for w in range(width//64):
35
- for h in range(height//64):
36
- box = (w*64, h*64, (w+1)*64, (h+1)*64)
37
- sav.append(grid_im.crop(box))
38
- return sav
39
-
40
- def color_loss(images, target_color=(0, 0, 0, 1)):
41
- target = (torch.tensor(target_color).to(images.device) * 2 - 1)
42
- target = target[None, :, None, None]
43
- error = torch.abs(images - target).mean()
44
- return error
45
-
46
- def generate():
47
- print(ctime(time()))
48
- x = torch.randn(8, 4, 64, 64).to(device)
49
- for i, t in enumerate(scheduler.timesteps):
50
- model_input = scheduler.scale_model_input(x, t)
51
- with torch.no_grad():
52
- noise_pred = image_pipe.unet(model_input, t)["sample"]
53
- x = scheduler.step(noise_pred, t, x).prev_sample
54
- return show_images_save(x)
55
-
56
- def generate_g(color, guidance_loss_scale):
57
- print(f'--V2-- {ctime(time())}')
58
- target_color = ImageColor.getcolor(color, "RGBA") # Target color as RGB
59
- target_color = [a / 255 for a in target_color] # Rescale from (0, 255) to (0, 1)
60
- x = torch.randn(8, 4, 64, 64).to(device)
61
- for i, t in enumerate(scheduler.timesteps):
62
- model_input = scheduler.scale_model_input(x, t)
63
- with torch.no_grad():
64
- noise_pred = image_pipe.unet(model_input, t)["sample"]
65
- x = x.detach().requires_grad_()
66
- x0 = scheduler.step(noise_pred, t, x).pred_original_sample
67
- loss = color_loss(x0, target_color) * guidance_loss_scale
68
- cond_grad = -torch.autograd.grad(loss, x)[0]
69
- x = x.detach() + cond_grad
70
- x = scheduler.step(noise_pred, t, x).prev_sample
71
- return show_images_save(x)
72
-
73
- demo = gr.Blocks(css=".tabs {max-width: 60%; margin-left: 20%; margin-right: 20%;} #column {max-width: 50%} .fixed-height {min-height: 0px !important} @media(min-width: 1280px){.fixed-height {min-height: 0px !important}}")
74
- with demo:
75
- gr.HTML(
76
- """
77
- <div style="text-align: center; margin: 0 auto;">
78
- <div style="display: inline-flex; align-items: center; justify-content: center;">
79
- <img src='https://huggingface.co/spaces/WiNE-iNEFF/MinecraftSkin-Diffusion/resolve/main/MSD_7.png' width='45%'>
80
- </div>
81
- <p style="margin-bottom: 10px; font-size: 94%; line-height: 23px;">
82
- Gradio demo for Minecraft Skin Diffusion. This is simple Unconditional Diffusion Model<br>that can generate skins for game Minecraft.
83
- </p>
84
- </div>
85
- """)
86
- with gr.Tabs():
87
- with gr.TabItem("V1"):
88
- with gr.Column():
89
- gall = gr.Gallery().style(grid=[4])
90
- greet_btn = gr.Button("Generate")
91
- greet_btn.click(fn=generate, outputs=gall)
92
- with gr.TabItem("V2"):
93
- with gr.Row():
94
- with gr.Column(min_width = 0, elem_id='column'):
95
- picker = gr.ColorPicker(label="color", value="#55FFAA", min_width='0')
96
- slide = gr.Slider(label="guidance_scale", minimum=0, maximum=100, value=50)
97
- greet_btn = gr.Button("Generate", min_width = '0')
98
- with gr.Column(min_width = 0):
99
- gall = gr.Gallery(min_width = '250').style(grid=[3])
100
- greet_btn.click(fn=generate_g, inputs=[picker, slide], outputs=gall)
101
- gr.HTML(
102
- """
103
- <div class="footer">
104
- <div style='text-align: center;'>Minecraft Skin Diffusion by <a href='https://twitter.com/wine_ineff' target='_blank'>Artsem Holub (WiNE-iNEFF)</a></div>
105
- </div>
106
- """)
107
-
108
- demo.launch()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import torch, torchvision
3
+ from torchvision import transforms
4
+ import torch.nn.functional as F
5
+ import numpy as np
6
+ import PIL
7
+ from PIL import Image, ImageColor
8
+ from diffusers import DiffusionPipeline
9
+ from diffusers import DDIMScheduler, DDPMScheduler, DEISMultistepScheduler, LCMScheduler, PNDMScheduler, UniPCMultistepScheduler
10
+ import base64
11
+ from urllib.parse import quote_plus
12
+ from io import BytesIO
13
+
14
+ device = ("mps" if torch.backends.mps.is_available() else "cuda" if torch.cuda.is_available() else "cpu")
15
+
16
+
17
+ class MSPipeline(DiffusionPipeline):
18
+ def __init__(self, unet, scheduler):
19
+ super().__init__()
20
+ self.register_modules(unet=unet, scheduler=scheduler)
21
+
22
+ @torch.no_grad()
23
+ def __call__(self, batch_size = 1, num_inference_steps = 1000):
24
+ x = torch.randn(batch_size, self.unet.config.in_channels, self.unet.config.sample_size, self.unet.config.sample_size).to(device)
25
+
26
+ self.scheduler.set_timesteps(num_inference_steps)
27
+
28
+ for t in self.progress_bar(self.scheduler.timesteps):
29
+ #x = self.scheduler.scale_model_input(x, t)
30
+ model_output = self.unet(x, t).sample
31
+ x = self.scheduler.step(model_output, t, x).prev_sample
32
+
33
+ x = x.cpu().permute(0, 2, 3, 1).clip(0, 1).numpy() #* 255
34
+ x = self.numpy_to_pil(x)
35
+
36
+ return x
37
+
38
+
39
+ def clear_pix(x):
40
+ datas = []
41
+ for pixel in list(x.getdata()):
42
+ r,g,b,a = pixel
43
+ if a == 0 or a < 150:
44
+ datas.append((0,0,0,0))
45
+ else:
46
+ datas.append((r,g,b,255))
47
+ x.putdata(datas)
48
+ return x
49
+
50
+
51
+ def show_3D(image, print_link = False):
52
+ if isinstance(image, PIL.Image.Image):
53
+ buffer = BytesIO()
54
+ image.save(buffer, format="PNG")
55
+ skin_base64 = base64.b64encode(buffer.getvalue()).decode("utf-8")
56
+ else:
57
+ with open(image, "rb") as f:
58
+ skin_base64 = base64.b64encode(f.read()).decode("utf-8")
59
+
60
+ data = f"data:image/png;base64,{skin_base64}"
61
+ quoted = quote_plus(data)
62
+ url = f"https://wine-ineff.github.io/SkinViewFrame/skin.html?color=c2b4ff&data={quoted}"
63
+
64
+ if print_link == True:
65
+ print(url)
66
+ return url
67
+
68
+
69
+ def generate(schedulers, inference_steps, images_num):
70
+ pipe = MSPipeline.from_pretrained("WiNE-iNEFF/Mineskin-Diffusion-v1.0", use_safetensors=True).to(device)
71
+
72
+ if schedulers == "DDIMScheduler":
73
+ pipe.scheduler = DDIMScheduler.from_pretrained("WiNE-iNEFF/Mineskin-Diffusion-v1.0", subfolder="scheduler")
74
+ elif schedulers == "DDPMScheduler":
75
+ pipe.scheduler = DDPMScheduler.from_pretrained("WiNE-iNEFF/Mineskin-Diffusion-v1.0", subfolder="scheduler")
76
+ elif schedulers == "DEISMultistepScheduler":
77
+ pipe.scheduler = DEISMultistepScheduler.from_pretrained("WiNE-iNEFF/Mineskin-Diffusion-v1.0", subfolder="scheduler")
78
+ elif schedulers == "LCMScheduler":
79
+ pipe.scheduler = LCMScheduler.from_pretrained("WiNE-iNEFF/Mineskin-Diffusion-v1.0", subfolder="scheduler")
80
+ elif schedulers == "PNDMScheduler":
81
+ pipe.scheduler = PNDMScheduler.from_pretrained("WiNE-iNEFF/Mineskin-Diffusion-v1.0", subfolder="scheduler")
82
+ elif schedulers == "UniPCMultistepScheduler":
83
+ pipe.scheduler = UniPCMultistepScheduler.from_pretrained("WiNE-iNEFF/Mineskin-Diffusion-v1.0", subfolder="scheduler")
84
+
85
+ images = pipe(batch_size = images_num, num_inference_steps = inference_steps)
86
+ return images, update_iframe(images)
87
+
88
+
89
+ def update_iframe(images):
90
+ iframe_html = "<div style='display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px'>"
91
+ for img in images:
92
+ iframe_url = show_3D(clear_pix(img), print_link=True)
93
+ iframe_html += f"<iframe style='min-width: 100%;' src='{iframe_url}'></iframe>"
94
+ iframe_html += "</div>"
95
+ return iframe_html
96
+
97
+
98
+ interface = gr.Blocks()
99
+ with interface:
100
+ gr.HTML(f"""
101
+ <h1 style="min-width: 100%; text-align: center;">Mineskin Diffusion</h1>
102
+ <p>This space run with {f"<b>{device.upper()}</b>." if device != "cpu" else f"<b>{device.upper()}</b>. This space will be work very slow. Pleasy use a <a href="https://colab.research.google.com/#fileId=https%3A//huggingface.co/WiNE-iNEFF/Mineskin-Diffusion-v1.0/MineskinDiffusion.ipynb" style="text-decoration: none; color: orange;">Google Colab notebook</a> for get fully experience of model or dublicate this space with your devices"}</p>
103
+ """)
104
+ with gr.Tabs():
105
+ with gr.TabItem("v1.0"):
106
+ with gr.Column():
107
+ scheduler_type = gr.Dropdown(
108
+ ["DDIMScheduler", "DDPMScheduler", "DEISMultistepScheduler", "LCMScheduler", "PNDMScheduler", "UniPCMultistepScheduler"],
109
+ label = "Type of scheduler"
110
+ )
111
+
112
+ with gr.Row():
113
+ inference_steps = gr.Number(
114
+ label = "Amount of denoising steps",
115
+ value = 30, minimum = 5, maximum = 1000
116
+ )
117
+ images_num = gr.Number(
118
+ label = "Amount of skins",
119
+ value = 4, minimum = 1, maximum = 4
120
+ )
121
+
122
+ gallery = gr.Gallery(columns=4, object_fit="scale-down", min_width=76)
123
+ iframe_output = gr.HTML()
124
+ gen_btn = gr.Button("Generate")
125
+ gen_btn.click(fn=generate, outputs=[gallery, iframe_output], inputs=[scheduler_type, inference_steps, images_num])
126
+
127
+ interface.launch()