mattyamonaca commited on
Commit
c3b62d3
1 Parent(s): f483907

first commit

Browse files
Files changed (5) hide show
  1. app.py +80 -0
  2. bg_alpha.py +60 -0
  3. lineart.py +21 -0
  4. models/lora/_put_your_lora.txt +0 -0
  5. utils.py +33 -0
app.py ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import sys
3
+ from utils import load_lora_model
4
+ from bg_alpha import adjust_transparency
5
+ from lineart import get_pipe
6
+ import os
7
+ from PIL import Image
8
+ import spaces
9
+
10
+ path = os.getcwd()
11
+ output_dir = f"{path}/output"
12
+ lora_dir = f"{path}/models/lora"
13
+
14
+ load_lora_model(lora_dir)
15
+
16
+ pipe = get_pipe(lora_dir)
17
+
18
+ @spaces.GPU()
19
+ def generate(prompt, negative_prompt):
20
+ default_pos = "((white background)), lineart, <lora:sdxl_BWLine:1.0>, monochrome, "
21
+ default_neg = ""
22
+ prompt = default_pos + prompt
23
+ negative_prompt = default_neg + negative_prompt
24
+
25
+ width, height = 1024, 1024
26
+ color = (255, 255, 255)
27
+ white_bg = Image.new("RGB", (width, height), color)
28
+
29
+ image = pipe(
30
+ prompt=prompt,
31
+ negative_prompt = negative_prompt,
32
+ image=[white_bg],
33
+ num_inference_steps=50,
34
+ controlnet_conditioning_scale=[0.1]
35
+ ).images[0]
36
+
37
+ return image
38
+
39
+
40
+ class webui:
41
+ def __init__(self):
42
+ self.demo = gr.Blocks()
43
+
44
+ def process(self, pos_prompt, neg_prompt):
45
+ image = generate(pos_prompt, neg_prompt)
46
+ image = adjust_transparency(image)
47
+ return [image]
48
+
49
+ def launch(self, share):
50
+ with self.demo:
51
+ with gr.Column():
52
+ with gr.Tab("output"):
53
+ output_0 = gr.Gallery(format="png")
54
+ #output_file = gr.File()
55
+ with gr.Column():
56
+ pos_prompt = gr.Textbox(value="1girl, cute, kawaii, medium breasts, medium hair, smile, mini skirt, best quality, very aesthetic," ,max_lines=1000, label="positive prompt")
57
+ neg_prompt = gr.Textbox(value="bold line, multiple people," ,max_lines=1000, label="negative prompt")
58
+
59
+ submit = gr.Button(value="Start")
60
+
61
+
62
+ submit.click(
63
+ self.process,
64
+ inputs=[pos_prompt, neg_prompt], #[input_image, pos_prompt, neg_prompt, alpha_th, thickness, reference_image],
65
+ outputs=[output_0]
66
+ )
67
+
68
+ self.demo.queue()
69
+ self.demo.launch(share=share)
70
+
71
+
72
+ if __name__ == "__main__":
73
+ ui = webui()
74
+ if len(sys.argv) > 1:
75
+ if sys.argv[1] == "share":
76
+ ui.launch(share=True)
77
+ else:
78
+ ui.launch(share=False)
79
+ else:
80
+ ui.launch(share=False)
bg_alpha.py ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from PIL import Image, ImageFilter
2
+ import numpy as np
3
+
4
+ def erode(image, iterations=1):
5
+ # モルフォロジー操作のためのカーネルを定義
6
+ kernel = np.array([[0, 1, 0],
7
+ [1, 1, 1],
8
+ [0, 1, 0]], dtype=np.uint8)
9
+
10
+ image_np = np.array(image)
11
+ for _ in range(iterations):
12
+ eroded_image = np.zeros_like(image_np)
13
+ for i in range(1, image_np.shape[0] - 1):
14
+ for j in range(1, image_np.shape[1] - 1):
15
+ region = image_np[i-1:i+2, j-1:j+2]
16
+ eroded_image[i, j] = np.min(region + (1 - kernel) * 255)
17
+ image_np = eroded_image
18
+
19
+ return Image.fromarray(image_np.astype(np.uint8))
20
+
21
+ def convert_non_white_to_black(image):
22
+ # 画像をNumPy配列に変換
23
+ image_np = np.array(image)
24
+
25
+ # 完全に白でないピクセルをすべて黒にする
26
+ #image_np[image_np < 250] = 0
27
+ image_np[image_np > 200] = 255
28
+
29
+ # NumPy配列を画像に変換
30
+ return Image.fromarray(image_np)
31
+
32
+
33
+
34
+ def adjust_transparency(image):
35
+ # 画像を読み込み、グレースケールに変換
36
+ image.save("tmp.png")
37
+ image = image.convert('L')
38
+ image = convert_non_white_to_black(image)
39
+ image = image.filter(ImageFilter.SMOOTH)
40
+
41
+ result = Image.new('RGBA', image.size)
42
+ for x in range(image.width):
43
+ for y in range(image.height):
44
+ # グレースケール値を取得
45
+ gray = image.getpixel((x, y))
46
+
47
+ alpha = 255
48
+ # 透明度の設定
49
+ if gray == 0:
50
+ alpha = 0 # 完全に透明
51
+ else:
52
+ alpha = 255-gray # 完全に不透明
53
+
54
+ # 新しい画像にピクセルを設定
55
+ result.putpixel((x, y), (0, 0, 0, alpha))
56
+
57
+ return result
58
+
59
+ def remove_bg(image):
60
+ image = adjust_transparency(image)
lineart.py ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from diffusers import AutoPipelineForText2Image
2
+ import torch
3
+
4
+ from diffusers import StableDiffusionControlNetPipeline, ControlNetModel, UniPCMultistepScheduler
5
+ from diffusers import StableDiffusionXLControlNetPipeline, ControlNetModel, AutoencoderKL
6
+ import torch
7
+
8
+ from PIL import Image
9
+
10
+
11
+ def get_pipe(lora_dir):
12
+ controlnets = [ControlNetModel.from_pretrained("mattyamonaca/white2line", torch_dtype=torch.float16)]
13
+
14
+ vae = AutoencoderKL.from_pretrained("madebyollin/sdxl-vae-fp16-fix", torch_dtype=torch.float16)
15
+ pipe = StableDiffusionXLControlNetPipeline.from_pretrained(
16
+ "cagliostrolab/animagine-xl-3.1", controlnet=controlnets, vae=vae, torch_dtype=torch.float16
17
+ )
18
+
19
+ pipe.enable_model_cpu_offload()
20
+ pipe.load_lora_weights(lora_dir, weight_name="sdxl_BWLine.safetensors")
21
+ return pipe
models/lora/_put_your_lora.txt ADDED
File without changes
utils.py ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import random
2
+ import string
3
+ import os
4
+
5
+ import requests
6
+ from tqdm import tqdm
7
+
8
+
9
+ def randomname(n):
10
+ randlst = [random.choice(string.ascii_letters + string.digits) for i in range(n)]
11
+ return ''.join(randlst)
12
+
13
+ def load_lora_model(model_dir):
14
+ folder = model_dir
15
+ file_name = 'sdxl_BWLine.safetensors'
16
+ url = "https://huggingface.co/tori29umai/lineart/resolve/main/sdxl_BWLine.safetensors"
17
+
18
+
19
+ file_path = os.path.join(folder, file_name)
20
+ if not os.path.exists(file_path):
21
+ response = requests.get(url, stream=True)
22
+
23
+ total_size = int(response.headers.get('content-length', 0))
24
+ with open(file_path, 'wb') as f, tqdm(
25
+ desc=file_name,
26
+ total=total_size,
27
+ unit='iB',
28
+ unit_scale=True,
29
+ unit_divisor=1024,
30
+ ) as bar:
31
+ for data in response.iter_content(chunk_size=1024):
32
+ size = f.write(data)
33
+ bar.update(size)