-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathblur.py
More file actions
319 lines (284 loc) · 11.5 KB
/
Copy pathblur.py
File metadata and controls
319 lines (284 loc) · 11.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
from typing import Dict, List, Tuple
from copy import deepcopy
import numpy as np
import cv2
from PIL import Image, ImageFilter
from diffusers.utils import make_image_grid
attributes = {
'background' : 0,
'skin' : 1,
'r_brow' : 2,
'l_brow' : 3,
'r_eye' : 4,
'l_eye' : 5,
'eye_g' : 6,
'l_ear' : 7,
'r_ear' : 8,
'ear_r' : 9,
'nose' : 10,
'mouth' : 11,
'u_lip' : 12,
'l_lip' : 13,
'neck' : 14,
'neck_l' : 15,
'cloth' : 16,
'hair' : 17,
'hat' : 18,
}
color_list = [[0, 0, 0],
[255, 0, 0],
[0, 204, 204],
[0, 0, 204],
[255, 153, 51],
[204, 0, 204],
[255, 0, 255],
[204, 0, 0],
[102, 51, 0],
[0, 0, 0],
[76, 153, 0],
[102, 204, 0],
[255, 255, 0],
[0, 0, 153],
[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
from typing import Dict, List, Tuple
from copy import deepcopy
import numpy as np
import cv2
from PIL import Image, ImageFilter
from diffusers.utils import make_image_grid
def create_condition_images(
image: Image.Image,
seg: Image.Image,
mask: Image.Image,
landmark: Image.Image,
iris: Image.Image,
# attributes: Dict[str, int],
# color_list: List[Tuple[int, int, int]],
condition: str = 'downsample', # 'blur' or 'downsample' or 'None' or 'mask'
downsample_size: int = 8,
blur_radius: int = 64,
remove_targets: List[str] = None, # seg에서 제거할 attribute
glass_target: str = "eye_g", # 안경 영역 이름
skin_targets: List[str] = None # blur를 덮어씌울 영역 (None이면 전체 attributes)
) -> Dict[str, np.ndarray]:
"""
이미지, 세그멘테이션, landmark를 이용해 여러 조건 이미지를 생성한다.
Args:
image: 원본 이미지 (PIL.Image, RGB)
seg: 세그멘테이션 이미지 (PIL.Image, RGB 색으로 class 구분)
mask: 추가 마스크 (현재 로직에서는 사용하지 않지만 인터페이스 유지용)
landmark: 랜드마크 visualization 이미지 (PIL.Image, non-zero 픽셀이 landmark)
attributes: class_name -> index 매핑 딕셔너리
color_list: 각 index에 대응하는 (R, G, B) 튜플 리스트
blur_radius: Gaussian blur radius
remove_targets: seg_landmark에서 제거할 attribute 리스트
glass_target: 안경(eye glasses)에 해당하는 attribute 이름
skin_targets: blur를 덮어씌울 attribute 리스트 (None이면 attributes 전체 사용)
Returns:
Dict[str, np.ndarray]: 아래 키를 갖는 H×W×3 uint8 이미지들
- "image": 원본
- "condition_blur"
- "condition_blur_landmark"
- "condition_blur_landmark_glass"
- "condition_seg_landmark"
- "condition_segSelected_landmark"
- "condition_blur_segSelected_landmark"
- "blended_image"
- "seg_landmark"
- "seg_landmark_selected"
"""
global attributes, color_list
# ---------------------------
# 0. 기본 파라미터 정리
# ---------------------------
if remove_targets is None:
remove_targets = ["skin", "l_ear", "r_ear"]
if skin_targets is None:
skin_targets = list(attributes.keys())
# ---------------------------
# 1. PIL -> numpy 변환
# ---------------------------
image_np = np.array(image) # (H, W, 3)
seg_np = np.array(seg) # (H, W, 3)
landmark_np = np.array(landmark) # (H, W, 3)
iris_landmark_np = np.array(iris) # (H, W, 3)
# ---------------------------
# 2. Downsample->Upsample 이미지 생성
# ---------------------------
if condition == 'blur':
# Gaussian blur 적용 (radius는 원하는 정도로 조절)
blurred_pil = image.filter(ImageFilter.GaussianBlur(radius=blur_radius))
blurred_np = np.array(blurred_pil)
elif condition == 'downsample':
w, h = image.size
blurred_np = image.resize((downsample_size, downsample_size), Image.LANCZOS).resize((w, h), Image.LANCZOS)
blurred_np = np.array(blurred_np)
elif condition == 'None':
blurred_np = image_np
elif condition == 'mask':
# 그냥 검은 이미지
blurred_np = np.zeros_like(image_np)
else:
raise ValueError(f"Unknown condition type: {condition}")
# ---------------------------
# 3. landmark 마스크 생성
# - landmark 이미지에서 non-zero 픽셀 위치를 landmark로 봄
# ---------------------------
landmark_sum = np.sum(landmark_np, axis=-1) # (H, W)
landmark_mask = landmark_sum > 0 # (H, W)
landmark_mask_3c = np.repeat(landmark_mask[..., None], 3, axis=-1) # (H, W, 3)
# seg + landmark (landmark 영역은 흰색으로)
seg_landmark = deepcopy(seg_np)
seg_landmark[landmark_mask_3c] = 255
iris_landmark_idx = iris_landmark_np.sum(axis=-1) > 0 # shape (h, w)
# ---------------------------
# 4. seg_landmark_selected: 특정 attribute 제거한 버전
# ---------------------------
seg_landmark_selected = deepcopy(seg_landmark)
for target in remove_targets:
if target not in attributes:
continue
target_idx = attributes[target]
target_color = color_list[target_idx] # (R, G, B)
target_mask = (
(seg_landmark_selected[..., 0] == target_color[0]) &
(seg_landmark_selected[..., 1] == target_color[1]) &
(seg_landmark_selected[..., 2] == target_color[2])
) # (H, W) bool
seg_landmark_selected[target_mask] = 0
# ---------------------------
# 5. 안경(seg_glass) 영역 추출
# ---------------------------
seg_glass = np.zeros_like(seg_np)
if glass_target in attributes:
g_idx = attributes[glass_target]
g_color = color_list[g_idx]
glass_mask_single = (
(seg_np[..., 0] == g_color[0]) &
(seg_np[..., 1] == g_color[1]) &
(seg_np[..., 2] == g_color[2])
) # (H, W) bool
seg_glass[glass_mask_single] = g_color
glass_mask = np.repeat(glass_mask_single[..., None], 3, axis=-1) # (H, W, 3)
else:
# glass_target이 없으면 전체 False
glass_mask_single = np.zeros(seg_np.shape[:2], dtype=bool)
glass_mask = np.repeat(glass_mask_single[..., None], 3, axis=-1)
# ---------------------------
# 6. skin(mask_skin) 영역 구하기
# - skin_targets에 해당하는 모든 class를 하나의 mask로 합침
# ---------------------------
seg_skin = np.zeros_like(seg_np)
for t in skin_targets:
if t not in attributes:
continue
t_idx = attributes[t]
t_color = color_list[t_idx]
t_mask = (
(seg_np[..., 0] == t_color[0]) &
(seg_np[..., 1] == t_color[1]) &
(seg_np[..., 2] == t_color[2])
)
seg_skin[t_mask] = t_color
# non-zero 픽셀을 skin 영역으로
mask_skin_single = (
(seg_skin[..., 0] != 0) |
(seg_skin[..., 1] != 0) |
(seg_skin[..., 2] != 0)
) # (H, W) bool
mask_skin = np.repeat(mask_skin_single[..., None], 3, axis=-1) # (H, W, 3)
if mask is not None:
mask_np = np.array(mask) # (H, W, 3)
mask_bool = (mask_np.sum(axis=-1) > 0) # (H, W) bool
mask_bool_3c = np.repeat(mask_bool[..., None], 3, axis=-1)
mask_skin = mask_bool_3c
# ---------------------------
# 7. condition_blur: skin 영역만 blur 덮어씌운 이미지
# ---------------------------
condition_blur = deepcopy(image_np)
condition_blur = condition_blur * (~mask_skin) + blurred_np * mask_skin
condition_blur = condition_blur.astype(np.uint8)
# ---------------------------
# 8. condition_blur_landmark: blur + landmark 영역(흰색)
# ---------------------------
condition_blur_landmark = deepcopy(condition_blur)
condition_blur_landmark[landmark_mask_3c] = 255
condition_blur_landmark[iris_landmark_idx] = [255, 0, 0]
condition_blur_landmark = condition_blur_landmark.astype(np.uint8)
# ---------------------------
# 9. condition_blur_landmark_glass:
# blur+landmark 이미지에 안경 영역을 살짝 overlay
# ---------------------------
glass_overlay = cv2.addWeighted(
condition_blur_landmark, 0.9,
seg_glass, 0.1,
0
)
condition_blur_landmark_glass = (
condition_blur_landmark * (~glass_mask) +
glass_overlay * glass_mask
)
condition_blur_landmark_glass = condition_blur_landmark_glass.astype(np.uint8)
# ---------------------------
# 10. condition_seg_landmark:
# 원본 이미지에 seg_landmark를 해당 영역에만 덮어씌운 이미지
# ---------------------------
mask_for_seg = np.any(seg_landmark != 0, axis=-1) # (H, W) bool
mask_for_seg_3c = np.repeat(mask_for_seg[..., None], 3, axis=-1)
condition_seg_landmark = deepcopy(image_np)
condition_seg_landmark = (
condition_seg_landmark * (~mask_for_seg_3c) +
seg_landmark * mask_for_seg_3c
)
condition_seg_landmark = condition_seg_landmark.astype(np.uint8)
# ---------------------------
# 11. condition_segSelected_landmark:
# 제거된 attribute가 빠진 seg_landmark_selected 사용
# ---------------------------
mask_for_seg_selected = np.any(seg_landmark_selected != 0, axis=-1)
mask_for_seg_selected_3c = np.repeat(mask_for_seg_selected[..., None], 3, axis=-1)
condition_segSelected_landmark = deepcopy(image_np)
condition_segSelected_landmark = (
condition_segSelected_landmark * (~mask_for_seg_selected_3c) +
seg_landmark_selected * mask_for_seg_selected_3c
)
condition_segSelected_landmark = condition_segSelected_landmark.astype(np.uint8)
# ---------------------------
# 12. condition_blur_segSelected_landmark:
# blur + 선택된 seg_landmark_selected 합성
# ---------------------------
condition_blur_segSelected_landmark = deepcopy(image_np)
condition_blur_segSelected_landmark = (
condition_blur_segSelected_landmark * (~mask_skin) + blurred_np * mask_skin
)
condition_blur_segSelected_landmark = (
condition_blur_segSelected_landmark * (~mask_for_seg_selected_3c) +
seg_landmark_selected * mask_for_seg_selected_3c
)
condition_blur_segSelected_landmark = condition_blur_segSelected_landmark.astype(np.uint8)
# ---------------------------
# 13. blended_image:
# blur+landmark 이미지와 segSelected 버전을 blend
# ---------------------------
blended_image = cv2.addWeighted(
condition_blur_landmark, 0.8,
condition_blur_segSelected_landmark, 0.2,
0
)
blended_image = blended_image.astype(np.uint8)
# ---------------------------
# 14. 결과 모아서 반환
# ---------------------------
results = {
"image": image_np,
"condition_blur": condition_blur,
"condition_blur_landmark": condition_blur_landmark,
"condition_blur_landmark_glass": condition_blur_landmark_glass,
"condition_seg_landmark": condition_seg_landmark,
"condition_segSelected_landmark": condition_segSelected_landmark,
"condition_blur_segSelected_landmark": condition_blur_segSelected_landmark,
"blended_image": blended_image,
"seg_landmark": seg_landmark,
"seg_landmark_selected": seg_landmark_selected,
}
return results