Spaces:
Running
on
Zero
Running
on
Zero
parokshsaxena
commited on
Commit
β’
5ca0873
1
Parent(s):
d3da15b
intensity transfer instead of color
Browse files- app.py +5 -3
- src/background_processor.py +52 -0
app.py
CHANGED
@@ -153,9 +153,7 @@ def start_tryon(human_img_dict,garm_img,garment_des, background_img, is_checked,
|
|
153 |
|
154 |
#human_img_orig = human_img_dict["background"].convert("RGB") # ImageEditor
|
155 |
human_img_orig = human_img_dict.convert("RGB") # Image
|
156 |
-
|
157 |
-
if background_img:
|
158 |
-
human_img_orig = BackgroundProcessor.color_transfer(human_img_orig, background_img)
|
159 |
|
160 |
"""
|
161 |
# Derive HEIGHT & WIDTH such that width is not more than 1000. This will cater to both Shein images (4160x6240) of 3:4 AR and model standard images ( 768x1024 ) of 2:3 AR
|
@@ -186,6 +184,10 @@ def start_tryon(human_img_dict,garm_img,garment_des, background_img, is_checked,
|
|
186 |
else:
|
187 |
human_img = human_img_orig.resize((WIDTH, HEIGHT))
|
188 |
|
|
|
|
|
|
|
|
|
189 |
|
190 |
if is_checked:
|
191 |
# internally openpose_model is resizing human_img to resolution 384 if not passed as input
|
|
|
153 |
|
154 |
#human_img_orig = human_img_dict["background"].convert("RGB") # ImageEditor
|
155 |
human_img_orig = human_img_dict.convert("RGB") # Image
|
156 |
+
|
|
|
|
|
157 |
|
158 |
"""
|
159 |
# Derive HEIGHT & WIDTH such that width is not more than 1000. This will cater to both Shein images (4160x6240) of 3:4 AR and model standard images ( 768x1024 ) of 2:3 AR
|
|
|
184 |
else:
|
185 |
human_img = human_img_orig.resize((WIDTH, HEIGHT))
|
186 |
|
187 |
+
# Do color transfer from background image for better image harmonization
|
188 |
+
if background_img:
|
189 |
+
human_img = BackgroundProcessor.intensity_transfer(human_img, background_img)
|
190 |
+
|
191 |
|
192 |
if is_checked:
|
193 |
# internally openpose_model is resizing human_img to resolution 384 if not passed as input
|
src/background_processor.py
CHANGED
@@ -235,6 +235,11 @@ class BackgroundProcessor:
|
|
235 |
@classmethod
|
236 |
def color_transfer(cls, source_pil: Image, target_pil: Image) -> Image:
|
237 |
source = ImageFormatConvertor.pil_to_cv2(source_pil)
|
|
|
|
|
|
|
|
|
|
|
238 |
target = ImageFormatConvertor.pil_to_cv2(target_pil)
|
239 |
source = cv2.cvtColor(source, cv2.COLOR_BGR2LAB)
|
240 |
target = cv2.cvtColor(target, cv2.COLOR_BGR2LAB)
|
@@ -254,4 +259,51 @@ class BackgroundProcessor:
|
|
254 |
|
255 |
res = cv2.cvtColor(result, cv2.COLOR_LAB2BGR)
|
256 |
res_pil = ImageFormatConvertor.cv2_to_pil(res)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
257 |
return res_pil
|
|
|
235 |
@classmethod
|
236 |
def color_transfer(cls, source_pil: Image, target_pil: Image) -> Image:
|
237 |
source = ImageFormatConvertor.pil_to_cv2(source_pil)
|
238 |
+
# Resize background image
|
239 |
+
width, height = source_pil.width, source_pil.height
|
240 |
+
target_pil = target_pil.convert("RGB")
|
241 |
+
target_pil = target_pil.resize((width, height))
|
242 |
+
|
243 |
target = ImageFormatConvertor.pil_to_cv2(target_pil)
|
244 |
source = cv2.cvtColor(source, cv2.COLOR_BGR2LAB)
|
245 |
target = cv2.cvtColor(target, cv2.COLOR_BGR2LAB)
|
|
|
259 |
|
260 |
res = cv2.cvtColor(result, cv2.COLOR_LAB2BGR)
|
261 |
res_pil = ImageFormatConvertor.cv2_to_pil(res)
|
262 |
+
return res_pil
|
263 |
+
|
264 |
+
@classmethod
|
265 |
+
def intensity_transfer(cls, source_pil: Image, target_pil: Image) -> Image:
|
266 |
+
"""
|
267 |
+
Transfers the intensity distribution from the target image to the source image.
|
268 |
+
|
269 |
+
Parameters:
|
270 |
+
source (np.ndarray): The source image (foreground) to be harmonized.
|
271 |
+
target (np.ndarray): The target image (background) whose intensity distribution is to be matched.
|
272 |
+
eps (float): A small value to avoid division by zero.
|
273 |
+
|
274 |
+
Returns:
|
275 |
+
np.ndarray: The intensity-transferred source image.
|
276 |
+
"""
|
277 |
+
source = ImageFormatConvertor.pil_to_cv2(source_pil)
|
278 |
+
# Resize background image
|
279 |
+
width, height = source_pil.width, source_pil.height
|
280 |
+
target_pil = target_pil.convert("RGB")
|
281 |
+
target_pil = target_pil.resize((width, height))
|
282 |
+
|
283 |
+
target = ImageFormatConvertor.pil_to_cv2(target_pil)
|
284 |
+
|
285 |
+
source_lab = cv2.cvtColor(source, cv2.COLOR_BGR2LAB)
|
286 |
+
target_lab = cv2.cvtColor(target, cv2.COLOR_BGR2LAB)
|
287 |
+
|
288 |
+
# Compute the mean and standard deviation of the L channel (intensity) of the source and target images
|
289 |
+
source_mean, source_std = cv2.meanStdDev(source_lab[:, :, 0])
|
290 |
+
target_mean, target_std = cv2.meanStdDev(target_lab[:, :, 0])
|
291 |
+
|
292 |
+
# Reshape the mean and std to (1, 1, 1) so they can be broadcast correctly
|
293 |
+
source_mean = source_mean.reshape((1, 1, 1))
|
294 |
+
source_std = source_std.reshape((1, 1, 1))
|
295 |
+
target_mean = target_mean.reshape((1, 1, 1))
|
296 |
+
target_std = target_std.reshape((1, 1, 1))
|
297 |
+
|
298 |
+
# Transfer the intensity (L channel)
|
299 |
+
result_l = (source_lab[:, :, 0] - source_mean) * (target_std / source_std) + target_mean
|
300 |
+
result_l = np.clip(result_l, 0, 255).astype(np.uint8)
|
301 |
+
|
302 |
+
# Combine the transferred L channel with the original A and B channels
|
303 |
+
result_lab = np.copy(source_lab)
|
304 |
+
result_lab[:, :, 0] = result_l
|
305 |
+
|
306 |
+
# return cv2.cvtColor(result_lab, cv2.COLOR_LAB2BGR)
|
307 |
+
res = cv2.cvtColor(result_lab, cv2.COLOR_LAB2BGR)
|
308 |
+
res_pil = ImageFormatConvertor.cv2_to_pil(res)
|
309 |
return res_pil
|