Spaces:
No application file
No application file
| import argparse | |
| import os | |
| os.environ['CUDA_HOME'] = '/usr/local/cuda' | |
| os.environ['PATH'] = os.environ['PATH'] + ':/usr/local/cuda/bin' | |
| from datetime import datetime | |
| import numpy as np | |
| import torch | |
| from diffusers.image_processor import VaeImageProcessor | |
| from huggingface_hub import snapshot_download | |
| from PIL import Image | |
| torch.jit.script = lambda f: f | |
| from model.cloth_masker import AutoMasker, vis_mask | |
| from model.pipeline import CatVTONPipeline | |
| from utils import init_weight_dtype, resize_and_crop, resize_and_padding | |
| # ํจํค์ง ์ถ๊ฐ | |
| import cv2 | |
| ''' | |
| def parse_args(): | |
| parser = argparse.ArgumentParser(description="Simple example of a training script.") | |
| parser.add_argument( | |
| "--base_model_path", | |
| type=str, | |
| default="booksforcharlie/stable-diffusion-inpainting", | |
| # default="runwayml/stable-diffusion-inpainting", | |
| help=( | |
| "The path to the base model to use for evaluation. This can be a local path or a model identifier from the Model Hub." | |
| ), | |
| ) | |
| parser.add_argument( | |
| "--resume_path", | |
| type=str, | |
| default="zhengchong/CatVTON", | |
| help=( | |
| "The Path to the checkpoint of trained tryon model." | |
| ), | |
| ) | |
| parser.add_argument( | |
| "--output_dir", | |
| type=str, | |
| default="resource/demo/output", | |
| help="The output directory where the model predictions will be written.", | |
| ) | |
| parser.add_argument( | |
| "--width", | |
| type=int, | |
| default=768, | |
| help=( | |
| "The resolution for input images, all the images in the train/validation dataset will be resized to this" | |
| " resolution" | |
| ), | |
| ) | |
| parser.add_argument( | |
| "--height", | |
| type=int, | |
| default=1024, | |
| help=( | |
| "The resolution for input images, all the images in the train/validation dataset will be resized to this" | |
| " resolution" | |
| ), | |
| ) | |
| parser.add_argument( | |
| "--repaint", | |
| action="store_true", | |
| help="Whether to repaint the result image with the original background." | |
| ) | |
| parser.add_argument( | |
| "--allow_tf32", | |
| action="store_true", | |
| default=True, | |
| help=( | |
| "Whether or not to allow TF32 on Ampere GPUs. Can be used to speed up training. For more information, see" | |
| " https://pytorch.org/docs/stable/notes/cuda.html#tensorfloat-32-tf32-on-ampere-devices" | |
| ), | |
| ) | |
| parser.add_argument( | |
| "--mixed_precision", | |
| type=str, | |
| default="no", | |
| choices=["no", "fp16", "bf16"], | |
| help=( | |
| "Whether to use mixed precision. Choose between fp16 and bf16 (bfloat16). Bf16 requires PyTorch >=" | |
| " 1.10.and an Nvidia Ampere GPU. Default to the value of accelerate config of the current system or the" | |
| " flag passed with the `accelerate.launch` command. Use this argument to override the accelerate config." | |
| ), | |
| ) | |
| args = parser.parse_args() | |
| env_local_rank = int(os.environ.get("LOCAL_RANK", -1)) | |
| if env_local_rank != -1 and env_local_rank != args.local_rank: | |
| args.local_rank = env_local_rank | |
| return args | |
| args = parse_args() | |
| ''' | |
| RESUME_PATH = os.getenv("RESUME_PATH", "zhengchong/CatVTON") | |
| repo_path = snapshot_download(repo_id=RESUME_PATH) | |
| # AutoMasker | |
| mask_processor = VaeImageProcessor(vae_scale_factor=8, do_normalize=False, do_binarize=True, do_convert_grayscale=True) | |
| automasker = AutoMasker( | |
| densepose_ckpt=os.path.join(repo_path, "DensePose"), | |
| schp_ckpt=os.path.join(repo_path, "SCHP"), | |
| device='cuda', | |
| ) | |
| person_image = Image.open("./resource/demo/example/person/men/model_7.png").convert("RGB") | |
| mask = automasker( | |
| person_image, | |
| 'upper' | |
| )['mask'] # ์ฌ๊ธฐ์ ๋ฆฌํด๋๋ mask๋ PIL ์ด๋ฏธ์ง์.(cloth_masker.py ์ฐธ์กฐ) # ์ฐธ๊ณ ๋ก ['densepose']๋ก densepose๋ ํ์ธ๊ฐ๋ฅ. | |
| ### ์ฌ๊ธฐ์ mask modify์ ์ฌ์ฉ๋ ์ฝ๋๋ฅผ app.py์ ์ฒดํฌํด๋์ ๋ถ๋ถ์ ์ถ๊ฐํ๋ฉด ๋๋ค! | |
| def remove_bottom_part(mask: np.ndarray, y_threshold: int): | |
| """ | |
| ์ด๋ฏธ์ง์ y_threshold ์๋์ ์๋ ๋ถ๋ถ์ ์ญ์ . | |
| :param mask: ์ ๋ ฅ ๋ง์คํฌ (numpy ๋ฐฐ์ด) | |
| :param y_threshold: ์ ๊ฑฐํ Y ์ขํ ๊ฐ | |
| :return: ์์ ๋ ๋ง์คํฌ (numpy ๋ฐฐ์ด) | |
| """ | |
| # y_threshold ์๋์ ๋ชจ๋ ํฝ์ ์ 0์ผ๋ก ์ค์ | |
| mask[y_threshold:, :] = 0 | |
| return Image.fromarray(mask) | |
| # closing ์ฐ์ฐ / fitting_mode๊ฐ standard ๋ loose ์ผ๋๋ง ์ฌ์ฉํ๊ธฐ | |
| def morph_close(mask): | |
| mask_np = np.array(mask) | |
| kernel = np.ones((30, 30), np.uint8) # ์ปค์ง์๋ก ์ ์ฐ๊ฒฐ๋จ | |
| closed_mask = cv2.morphologyEx(mask_np, cv2.MORPH_CLOSE, kernel) | |
| return Image.fromarray(closed_mask) | |
| # opening ์ฐ์ฐ / fitting_mode๊ฐ standard ๋ loose ์ผ๋๋ง ์ฌ์ฉํ๊ธฐ | |
| def morph_open(mask): | |
| mask_np = np.array(mask) | |
| kernel = np.ones((30, 30), np.uint8) # ์ปค์ง์๋ก ์ ์ฌ๋ผ์ง | |
| #closed_mask = cv2.morphologyEx(mask_np, cv2.MORPH_CLOSE, kernel) | |
| opened_mask = cv2.morphologyEx(mask_np, cv2.MORPH_OPEN, kernel) #opened_mask๋ numpy ์ฐ์ฐ ๊ฒฐ๊ณผ ์ด๋ฏ๋ก PIL ์ด๋ฏธ์ง๋ก ๋ณํ ํ์ | |
| return Image.fromarray(opened_mask) | |
| def morph_open2(mask): | |
| mask_np = np.array(mask) | |
| kernel = np.ones((10, 10), np.uint8) # ์ปค์ง์๋ก ์ ์ฌ๋ผ์ง | |
| #closed_mask = cv2.morphologyEx(mask_np, cv2.MORPH_CLOSE, kernel) | |
| opened_mask = cv2.morphologyEx(mask_np, cv2.MORPH_OPEN, kernel) #opened_mask๋ numpy ์ฐ์ฐ ๊ฒฐ๊ณผ ์ด๋ฏ๋ก PIL ์ด๋ฏธ์ง๋ก ๋ณํ ํ์ | |
| return Image.fromarray(opened_mask) | |
| ## opened_mask = morph_open(mask) | |
| ## opened_mask.save('./opened_mask.png') #opened_mask๋ PIL ์ด๋ฏธ์ง ํํ๋ก ๋ฐํ๋์์ผ๋ฏ๋ก (Image.fromarray()์ฌ์ฉํด์) .save๋ฅผ ๋ฐ๋ก ์ฌ์ฉํ ์ ์๋ค. | |
| #opened_mask2 = morph_open2(mask) | |
| #kernel = np.ones((50, 50), np.uint8) | |
| #opened_mask2 = cv2.dilate(np.array(opened_mask2), kernel, iterations=1) | |
| #opened_mask2 = Image.fromarray(opened_mask2) | |
| #opened_mask2 = mask_processor.blur(opened_mask2, blur_factor=9) | |
| #opened_mask2.save('./opened_mask2.png') | |
| # mask = mask_processor.blur(mask, blur_factor=9) | |
| ## mask.save("./test_mask.png") # ๋ง์คํฌ๋ฅผ PNG ํ์ผ๋ก ์ ์ฅ | |
| ## masked_person = vis_mask(person_image, mask) # app.py์์๋ blur ์ฒ๋ฆฌ ํ ๋ค์์ vis_mask ๋ฉ์๋ ํธ์ถํจ. | |
| ## masked_person.save("./test_masked_person.png") # ๋ง์คํฌ์ target img๊ฐ ํฉ์ณ์ง ์ฌ์ง์ PNG ํ์ผ๋ก ์ ์ฅ | |
| # mask์ y์ถ ์์ ๋ฐฉํฅ ์ด๋ | |
| def extend_mask_downward(mask_image: np.ndarray, pixels: int) -> np.ndarray: | |
| """ | |
| y์ถ ์์ ๋ฐฉํฅ์ผ๋ก (์๋๋ก) ๋ง์คํฌ ์ด๋ฏธ์ง๋ฅผ ํ์ฅํ๋ ํจ์. | |
| :param mask_image: ๋ง์คํฌ ์ด๋ฏธ์ง (numpy ๋ฐฐ์ด) | |
| :param pixels: ํ์ฅํ ํฝ์ ์ | |
| :return: ํ์ฅ๋ ๋ง์คํฌ ์ด๋ฏธ์ง (numpy ๋ฐฐ์ด) | |
| """ | |
| # ์ด์งํ๋ ๋ง์คํฌ๋ฅผ ๋ง๋ฆ | |
| mask = cv2.threshold(mask_image, 127, 255, cv2.THRESH_BINARY)[1] | |
| # ํ์ฅ์ ์ํ ์ปค๋. y์ถ์ผ๋ก๋ง ํ์ฅํ๊ธฐ ์ํด ์ธ๋ก ๊ธธ์ด๋ฅผ ํฌ๊ฒ ์ค์ ํจ | |
| kernel = np.zeros((pixels, 1), np.uint8) # y์ถ์ผ๋ก๋ง ๊ธธ์ด์ง ์ปค๋ | |
| # y์ถ ์์ ๋ฐฉํฅ์ผ๋ก๋ง ํ์ฅ (cv2.dilate ์ฌ์ฉ) | |
| extended_mask = cv2.dilate(mask, kernel, iterations=1) | |
| return Image.fromarray(extended_mask) | |
| def image_equal(img1, img2): | |
| return np.array_equal(np.array(img1), np.array(img2)) | |
| # automasker์ ๋ํ fitting ์ ๋๋ฅผ default ์ฒ๋ฆฌํ๊ธฐ ์ํ ์ฝ๋ ์ถ๊ฐ. | |
| def extend_mask_downward2(mask_image: np.ndarray, pixels: int) -> Image.Image: | |
| # ์ด์งํ๋ ๋ง์คํฌ๋ฅผ ๋ง๋ฆ | |
| mask = cv2.threshold(mask_image, 127, 255, cv2.THRESH_BINARY)[1] | |
| height, width = mask.shape[:2] | |
| # ๋ง์คํฌ๊ฐ ์์ํ๋ y ์ขํ์ ๋๋๋ y ์ขํ ์ฐพ๊ธฐ | |
| non_zero_rows = np.where(mask.any(axis=1))[0] | |
| if len(non_zero_rows) == 0: | |
| # ๋ง์คํฌ๊ฐ ๋น์ด์๋ ๊ฒฝ์ฐ, ์๋ณธ ์ด๋ฏธ์ง๋ฅผ ๋ฐํ | |
| return Image.fromarray(mask.copy()) | |
| mask_start_row = non_zero_rows[0] | |
| mask_end_row = non_zero_rows[-1] | |
| # ๋์ด๋ ๋ง์คํฌ์ ๋ y ์ขํ ๊ณ์ฐ (์ด๋ฏธ์ง ๋์ด๋ฅผ ์ด๊ณผํ์ง ์๋๋ก) | |
| new_mask_end_row = min(mask_end_row + pixels, height - 1) | |
| # ์๋ณธ ๋ง์คํฌ ์์ญ๊ณผ ๋์ด๋ ๋ง์คํฌ ์์ญ์ ๊ธธ์ด ๊ณ์ฐ | |
| original_mask_length = mask_end_row - mask_start_row + 1 | |
| stretched_mask_length = new_mask_end_row - mask_start_row + 1 | |
| # y ์ขํ ๋งคํ ๋ฐฐ์ด ์์ฑ | |
| map_y = np.arange(height, dtype=np.float32) | |
| # ๋ง์คํฌ ์์ญ์ ๋ํ y ์ขํ ์ฌ๋งคํ (์ ํ์ ์ผ๋ก ๋๋ฆฌ๊ธฐ) | |
| if stretched_mask_length > 1: | |
| map_y[mask_start_row:new_mask_end_row + 1] = np.linspace( | |
| mask_start_row, | |
| mask_end_row, | |
| stretched_mask_length | |
| ) | |
| else: | |
| map_y[mask_start_row:new_mask_end_row + 1] = mask_start_row | |
| # ๋ง์คํฌ ์๋ ์์ญ์ ๋ง์ง๋ง ๋ง์คํฌ ํ์ผ๋ก ๋งคํ | |
| if new_mask_end_row + 1 < height: | |
| map_y[new_mask_end_row + 1:] = mask_end_row | |
| # map_y์ ํฌ๊ธฐ๋ฅผ (height, width)๋ก ํ์ฅ | |
| map_y = np.repeat(map_y[:, np.newaxis], width, axis=1) | |
| # x ์ขํ๋ ๊ทธ๋๋ก ์ ์ง | |
| map_x = np.tile(np.arange(width, dtype=np.float32), (height, 1)) | |
| # ์ด๋ฏธ์ง ๋ฆฌ๋งคํ | |
| extended_mask = cv2.remap( | |
| mask, | |
| map_x, | |
| map_y, | |
| interpolation=cv2.INTER_LINEAR, | |
| borderMode=cv2.BORDER_CONSTANT, | |
| borderValue=0 | |
| ) | |
| return Image.fromarray(extended_mask) | |
| # ๋ง์คํฌ๋ฅผ y์ถ ์์ ๋ฐฉํฅ์ผ๋ก 50ํฝ์ ํ์ฅ | |
| ## extended_mask = extend_mask_downward(np.array(mask), pixels=100) | |
| # ํ์ฅ๋ ๋ง์คํฌ ์ ์ฅ | |
| ## extended_mask.save('extended_mask_image.png') | |
| # ์ต์ข ๋ง์คํฌ ์ ์ฅ | |
| # fitting ์ ๋์ ๋ฐ๋ผ, extended_mask ํจ์ ํธ์ถ ๋ณ์์ธ pixels๋ฅผ ์กฐ์ ํ๋ฉด ๋๋ค. | |
| # ์ ํ๋๋ฅผ ์ํด ๊ทธ๋ฅ dilation ํ์ง ์๊ณ , y์ขํ๊ฐ ์ฝ๊ฐ ๋ค๋ฅธ ๋ ๋ง์คํฌ๋ฅผ ํฉ์ณค๋ค. | |
| ## final_mask = Image.fromarray(np.array(opened_mask) | np.array(extended_mask)) | |
| ## final_mask = morph_close(morph_open(final_mask)) #๋ถํ์ํ ๋๋จ์ด์ง ๋ถ๋ถ ์ญ์ -> ์ฐ๊ฒฐ๋์ง ์์ ๋ถ๋ถ ์ฐ๊ฒฐ | |
| ## final_mask.save('final_mask_image.png') | |
| ## masked_person2 = vis_mask(person_image, final_mask) # app.py์์๋ blur ์ฒ๋ฆฌ ํ ๋ค์์ vis_mask ๋ฉ์๋ ํธ์ถํจ. | |
| ## masked_person2.save("./test_masked_person2.png") # ๋ง์คํฌ์ target img๊ฐ ํฉ์ณ์ง ์ฌ์ง์ PNG ํ์ผ๋ก ์ ์ฅ | |
| #person_image = Image.open("path_to_image").convert("RGB") | |
| #standard_image = Image.open("./resource/demo/example/person/men/m_lvl3.png").convert("RGB") | |
| """ | |
| compare_image_mlvl3 = Image.open("./resource/demo/example/person/men/m_lvl3.png").convert("RGB") | |
| compare_image_mlvl3 = resize_and_crop(compare_image_mlvl3, (args.width, args.height)) | |
| person_image2 = Image.open("./resource/demo/example/person/men/m_lvl0.png").convert("RGB") # ์ด๊ฑธ ์ด๋ bmi ๋ ๋ฒจ์ ๊ธฐ์ค์ผ๋ก ์ธ์ง๋ ๋ญ.. ์คํํด๋ณด๋ฉด์ ์ ์ผ ์ข์ ๊ฑฐ ์ ํ๋ฉด ๋จ. | |
| person_image2 = resize_and_crop(person_image2, (args.width, args.height)) | |
| mask = automasker( | |
| person_image2, | |
| "upper" | |
| )['mask'] | |
| mask.save("./first_mask.png") | |
| # ์ดํ ์ฒ๋ฆฌ | |
| sam_mask_lower = Image.open("./resource/demo/example/person/sam/m_lvl3_lower_sam.png").convert("L") | |
| sam_mask_lower = resize_and_crop(sam_mask_lower, (args.width, args.height)) | |
| sam_mask_upper = Image.open("./resource/demo/example/person/sam/m_lvl3_upper_sam.png").convert("L") | |
| sam_mask_upper = resize_and_crop(sam_mask_upper, (args.width, args.height)) | |
| mask_np = np.array(mask) | |
| sam_mask_upper_np = np.array(sam_mask_upper) | |
| sam_mask_lower_np = np.array(sam_mask_lower) | |
| kernel = np.ones((10, 10), np.uint8) | |
| sam_mask_upper_np = cv2.dilate(sam_mask_upper_np, kernel, iterations=1) | |
| sam_mask_lower_np = cv2.dilate(sam_mask_lower_np, kernel, iterations=1) | |
| result_np = np.where(sam_mask_lower_np== 255, 0, mask_np) | |
| result_np = np.where(sam_mask_upper_np== 255, 255, result_np) | |
| mask = Image.fromarray(result_np) | |
| mask.save("./last_mask2.png") | |
| """ |