tori29umai commited on
Commit
6907b56
·
verified ·
1 Parent(s): 4a24f58

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +74 -170
app.py CHANGED
@@ -1,156 +1,61 @@
1
  import gradio as gr
2
- from PIL import Image, ImageFilter, ImageOps
3
- import cv2
4
- import numpy as np
5
  import os
6
- from collections import defaultdict
7
- from skimage.color import deltaE_ciede2000, rgb2lab
8
  import zipfile
9
 
10
- def DoG_filter(image, kernel_size=0, sigma=1.0, k_sigma=2.0, gamma=1.5):
11
- g1 = cv2.GaussianBlur(image, (kernel_size, kernel_size), sigma)
12
- g2 = cv2.GaussianBlur(image, (kernel_size, kernel_size), sigma * k_sigma)
13
- return g1 - gamma * g2
14
 
15
- def XDoG_filter(image, kernel_size=0, sigma=1.4, k_sigma=1.6, epsilon=0, phi=10, gamma=0.98):
16
- epsilon /= 255
17
- dog = DoG_filter(image, kernel_size, sigma, k_sigma, gamma)
18
- dog /= dog.max()
19
- e = 1 + np.tanh(phi * (dog - epsilon))
20
- e[e >= 1] = 1
21
- return (e * 255).astype('uint8')
22
-
23
- def binarize_image(image):
24
- _, binarized = cv2.threshold(image, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
25
- return binarized
26
-
27
-
28
- def process_XDoG(image_path):
29
- kernel_size=0
30
- sigma=1.4
31
- k_sigma=1.6
32
- epsilon=0
33
- phi=10
34
- gamma=0.98
35
-
36
- image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
37
- xdog_image = XDoG_filter(image, kernel_size, sigma, k_sigma, epsilon, phi, gamma)
38
- binarized_image = binarize_image(xdog_image)
39
- final_image = Image.fromarray(binarized_image)
40
- return final_image
41
-
42
-
43
-
44
- def replace_color(image, color_1, blur_radius=2):
45
- data = np.array(image)
46
- original_shape = data.shape
47
- channels = original_shape[2] if len(original_shape) > 2 else 1 # チャンネル数を確認
48
- data = data.reshape(-1, channels)
49
- color_1 = np.array(color_1)
50
- matches = np.all(data[:, :3] == color_1, axis=1)
51
- nochange_count = 0
52
- mask = np.zeros(data.shape[0], dtype=bool)
53
-
54
- while np.any(matches):
55
- new_matches = np.zeros_like(matches)
56
- match_num = np.sum(matches)
57
- for i in range(len(data)):
58
- if matches[i]:
59
- x, y = divmod(i, original_shape[1])
60
- neighbors = [
61
- (x, y-1), (x, y+1), (x-1, y), (x+1, y)
62
- ]
63
- valid_neighbors = []
64
- for nx, ny in neighbors:
65
- if 0 <= nx < original_shape[0] and 0 <= ny < original_shape[1]:
66
- ni = nx * original_shape[1] + ny
67
- if not np.all(data[ni, :3] == color_1, axis=0):
68
- valid_neighbors.append(data[ni, :3])
69
- if valid_neighbors:
70
- new_color = np.mean(valid_neighbors, axis=0).astype(np.uint8)
71
- data[i, :3] = new_color
72
- data[i, 3] = 255
73
- mask[i] = True
74
- else:
75
- new_matches[i] = True
76
- matches = new_matches
77
- if match_num == np.sum(matches):
78
- nochange_count += 1
79
- if nochange_count > 5:
80
- break
81
-
82
- data = data.reshape(original_shape)
83
- mask = mask.reshape(original_shape[:2])
84
-
85
- result_image = Image.fromarray(data, 'RGBA')
86
- blurred_image = result_image.filter(ImageFilter.GaussianBlur(radius=blur_radius))
87
- blurred_data = np.array(blurred_image)
88
-
89
- np.copyto(data, blurred_data, where=mask[..., None])
90
-
91
- return Image.fromarray(data, 'RGBA')
92
-
93
- def generate_distant_colors(consolidated_colors, distance_threshold):
94
- consolidated_lab = [rgb2lab(np.array([color], dtype=np.float32) / 255.0).reshape(3) for color, _ in consolidated_colors]
95
- max_attempts = 10000
96
- for _ in range(max_attempts):
97
- random_rgb = np.random.randint(0, 256, size=3)
98
- random_lab = rgb2lab(np.array([random_rgb], dtype=np.float32) / 255.0).reshape(3)
99
- if all(deltaE_ciede2000(base_color_lab, random_lab) > distance_threshold for base_color_lab in consolidated_lab):
100
- return tuple(random_rgb)
101
- return (128, 128, 128)
102
-
103
- def consolidate_colors(major_colors, threshold):
104
- colors_lab = [rgb2lab(np.array([[color]], dtype=np.float32)/255.0).reshape(3) for color, _ in major_colors]
105
- i = 0
106
- while i < len(colors_lab):
107
- j = i + 1
108
- while j < len(colors_lab):
109
- if deltaE_ciede2000(colors_lab[i], colors_lab[j]) < threshold:
110
- if major_colors[i][1] >= major_colors[j][1]:
111
- major_colors[i] = (major_colors[i][0], major_colors[i][1] + major_colors[j][1])
112
- major_colors.pop(j)
113
- colors_lab.pop(j)
114
- else:
115
- major_colors[j] = (major_colors[j][0], major_colors[j][1] + major_colors[i][1])
116
- major_colors.pop(i)
117
- colors_lab.pop(i)
118
- continue
119
- j += 1
120
- i += 1
121
- return major_colors
122
-
123
- def get_major_colors(image, threshold_percentage=0.01):
124
- if image.mode != 'RGB':
125
- image = image.convert('RGB')
126
- color_count = defaultdict(int)
127
- for pixel in image.getdata():
128
- color_count[pixel] += 1
129
- total_pixels = image.width * image.height
130
- major_colors = [(color, count) for color, count in color_count.items() if (count / total_pixels) >= threshold_percentage]
131
- return major_colors
132
-
133
- def line_color(image, mask, new_color):
134
- data = np.array(image)
135
- data[mask, :3] = new_color
136
- return Image.fromarray(data)
137
-
138
- def process_image(image, lineart):
139
- if image.mode != 'RGBA':
140
- image = image.convert('RGBA')
141
-
142
- lineart = lineart.point(lambda x: 0 if x < 200 else 255)
143
- lineart = ImageOps.invert(lineart)
144
- kernel = np.ones((3, 3), np.uint8)
145
- lineart = cv2.dilate(np.array(lineart), kernel, iterations=1)
146
- lineart = Image.fromarray(lineart)
147
- mask = np.array(lineart) == 255
148
- major_colors = get_major_colors(image, threshold_percentage=0.05)
149
- major_colors = consolidate_colors(major_colors, 10)
150
- new_color_1 = generate_distant_colors(major_colors, 100)
151
- filled_image = line_color(image, mask, new_color_1)
152
- replace_color_image = replace_color(filled_image, new_color_1, 2).convert('RGB')
153
- return replace_color_image
154
 
155
  def zip_files(zip_files, zip_path):
156
  with zipfile.ZipFile(zip_path, 'w') as zipf:
@@ -163,32 +68,31 @@ class webui:
163
 
164
  def main(self, image_path):
165
  image = Image.open(image_path)
166
- #拡張子を取り除いたファイル名を取得
167
  image_name = os.path.splitext(image_path)[0]
168
- alpha = image.getchannel('A') if image.mode == 'RGBA' else None
169
- image = Image.open(image_path).convert('RGBA')
170
- rgb_image = image.convert('RGB')
171
- lineart = process_XDoG(image_path).convert('L')
172
- replace_color_image = process_image(rgb_image, lineart).convert('RGBA')
173
-
174
- if alpha:
175
- replace_color_image.putalpha(alpha)
176
-
177
- replace_color_image_path = f"{image_name}_noline.png"
178
- replace_color_image.save(replace_color_image_path)
179
-
180
- lineart_image = lineart.convert('RGBA')
181
- lineart_alpha = 255 - np.array(lineart)
182
- lineart_image.putalpha(Image.fromarray(lineart_alpha))
183
-
184
- lineart_image_path = f"{image_name}_lineart.png"
185
- lineart_image.save(lineart_image_path)
186
 
187
- zip_files_list = [replace_color_image_path, lineart_image_path]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
188
  zip_path = f"{image_name}.zip"
189
  zip_files(zip_files_list, zip_path)
190
 
191
- outputs = [replace_color_image, lineart_image]
 
192
  return outputs, zip_path
193
 
194
  def launch(self, share):
@@ -213,4 +117,4 @@ class webui:
213
 
214
  if __name__ == "__main__":
215
  ui = webui()
216
- ui.launch(share=True)
 
1
  import gradio as gr
2
+ from PIL import Image, ImageOps
 
 
3
  import os
 
 
4
  import zipfile
5
 
 
 
 
 
6
 
7
+ def process_image(image):
8
+ # 元の画像のサイズ
9
+ original_width, original_height = image.size
10
+
11
+ # 新しいサイズ
12
+ target_width, target_height = 252, 144
13
+
14
+ # 分割後の画像を格納するリスト
15
+ outputs = []
16
+
17
+ # 画像を4つのセクションに分割するための新しいサイズ
18
+ new_width = original_width // 2
19
+ new_height = original_height // 2
20
+
21
+ # 画像を4つのセクションに分割
22
+ for i in range(2):
23
+ for j in range(2):
24
+ left = new_width * j
25
+ upper = new_height * i
26
+ right = new_width * (j + 1)
27
+ lower = new_height * (i + 1)
28
+
29
+ # 画像を切り取る
30
+ cropped_image = image.crop((left, upper, right, lower))
31
+
32
+ # アスペクト比を保ちながら、指定のサイズにリサイズ
33
+ cropped_image = cropped_image.resize((target_width, target_height), Image.ANTIALIAS)
34
+
35
+ # 新しい黒背景を作成
36
+ black_background = Image.new('RGBA', (target_width, target_height), (0, 0, 0, 255))
37
+
38
+ # 余白の追加を左上、左下、右上、右下に対応
39
+ if i == 0 and j == 0: # 左上
40
+ left_offset = 0
41
+ top_offset = 0
42
+ elif i == 1 and j == 0: # 左下
43
+ left_offset = 0
44
+ top_offset = target_height - cropped_image.height
45
+ elif i == 0 and j == 1: # 右上
46
+ left_offset = target_width - cropped_image.width
47
+ top_offset = 0
48
+ elif i == 1 and j == 1: # 右下
49
+ left_offset = target_width - cropped_image.width
50
+ top_offset = target_height - cropped_image.height
51
+
52
+ # 中心に元画像を貼り付け
53
+ black_background.paste(cropped_image, (left_offset, top_offset))
54
+
55
+ outputs.append(black_background)
56
+
57
+ # 出力される4つの画像を返す
58
+ return outputs[0], outputs[1], outputs[2], outputs[3]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
 
60
  def zip_files(zip_files, zip_path):
61
  with zipfile.ZipFile(zip_path, 'w') as zipf:
 
68
 
69
  def main(self, image_path):
70
  image = Image.open(image_path)
71
+ # 拡張子を取り除いたファイル名を取得
72
  image_name = os.path.splitext(image_path)[0]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
 
74
+ # 画像を処理
75
+ output1, output2, output3, output4 = process_image(image)
76
+
77
+ # 保存先のパスを作成
78
+ output1_path = f"{image_name}_1.png"
79
+ output2_path = f"{image_name}_2.png"
80
+ output3_path = f"{image_name}_3.png"
81
+ output4_path = f"{image_name}_4.png"
82
+
83
+ # 画像を保存
84
+ output1.save(output1_path)
85
+ output2.save(output2_path)
86
+ output3.save(output3_path)
87
+ output4.save(output4_path)
88
+
89
+ # 保存したファイルをリストに追加
90
+ zip_files_list = [output1_path, output2_path, output3_path, output4_path]
91
  zip_path = f"{image_name}.zip"
92
  zip_files(zip_files_list, zip_path)
93
 
94
+ # 出力として画像とzipファイルを返す
95
+ outputs = [output1, output2, output3, output4]
96
  return outputs, zip_path
97
 
98
  def launch(self, share):
 
117
 
118
  if __name__ == "__main__":
119
  ui = webui()
120
+ ui.launch(share=True)