Files
2024-02-19 08:34:53 +09:00

151 lines
5.2 KiB
Python

import math, cv2, random, torch, torchvision, json, os
import numpy as np
import nodes, folder_paths # 기본노드, 파일로드
# class name:
# def __init__(self):
# pass
# @classmethod
# def INPUT_TYPES(s):
# return {
# "required": {},
# "optional": {},
# }
# RETURN_TYPES = ()
# RETURN_NAMES = ()
# FUNCTION = "run"
# CATEGORY = "abyz22"
# def run(self,*args,**kwargs):
# return None
def find_white_bbox(mask):
mask = (mask > 0).astype(np.uint8)
# 행과 열의 합을 계산하여 흰색 영역을 찾습니다.
row_sum = np.sum(mask, axis=1) # 768
col_sum = np.sum(mask, axis=0) # 512
# 흰색 영역의 시작과 끝 인덱스를 찾습니다.
for i, x in enumerate(row_sum):
if x > 0:
break
for ii, x in enumerate(col_sum):
if x > 0:
break
y1, x1 = i, ii
for i, x in enumerate(row_sum[::-1]):
if x > 0:
break
for ii, x in enumerate(col_sum[::-1]):
if x > 0:
break
y2, x2 = row_sum.shape[0] - i, col_sum.shape[0] - ii
return y1, x1, y2, x2
class abyz22_smallhead:
def __init__(self):
pass
@classmethod
def INPUT_TYPES(s):
return {
"required": {
"image": ("IMAGE",), # image= 1,768,512,3
"segs": ("IMAGE",), # mask= 1,768,512,3
"ratio": ("FLOAT", {"default": 0.8, "min": 0.01, "max": 1.5, "step": 0.01, "round": 0.001, "dispaly": "slider"}),
"empty_space": (["noise", "black"],),
"model_detector": ("BOOLEAN", {"default": True, "label_on": "face", "label_off": "head"}),
"kernel_size": ("INT", {"default": 10, "min": 0, "max": 100, "step": 1, "dispaly": "slider"}),
"sigma": ("FLOAT", {"default": 10.0, "min": 0.1, "max": 100.0, "step": 0.1, "round": 0.01, "dispaly": "slider"}),
"mask_dilation": ("INT", {"default": 10, "min": 0, "max": 128, "step": 1, "dispaly": "slider"}),
}
}
RETURN_TYPES = (
"IMAGE",
"MASK",
)
RETURN_NAMES = (
"images",
"masks",
)
FUNCTION = "run"
CATEGORY = "abyz22"
def run(sefl, *args, **kwargs): # image= 1,768,512,3 mask= n,1,h,w
images, mask = None, None
if len(kwargs["segs"]) == 1:
kwargs["segs"] = kwargs["segs"][0]
for i in range(kwargs["image"].shape[0]):
# y1, x1, y2, x2 = find_white_bbox(kwargs["segs"].permute(0, 3, 1, 2)[i][0].numpy())
y1, x1, y2, x2 = find_white_bbox(kwargs["segs"][i].permute(2, 0, 1)[0].numpy())
w = x2 - x1
h = y2 - y1
image = kwargs["image"][i]
face = kwargs["image"][i].clone()
face_cropped = face * kwargs["segs"][i]
if kwargs["empty_space"] == "noise":
image[y1:y2, x1:x2, :] = torch.rand_like(image[y1:y2, x1:x2, :])
face_noised = torch.rand_like(face) * -1 * (kwargs["segs"] - 1)[i]
elif kwargs["empty_space"] == "black":
image[y1:y2, x1:x2, :] = torch.zeros_like(image[y1:y2, x1:x2, :])
face_noised = torch.zeros_like(face) * -1 * (kwargs["segs"] - 1)[i]
face_cropped = face_cropped + face_noised
face_cropped = face_cropped[y1:y2, x1:x2, :].permute(2, 0, 1) # 768,512,3 -> 3,768,512
face_resized = torchvision.transforms.Resize((int(h * kwargs["ratio"]), int(w * kwargs["ratio"])))(face_cropped).permute(
1, 2, 0
) # 3,768,512 -> 768,512,3
h, w, c = face_resized.shape
image[y2 - h : y2, int((x1 + x2) // 2 - w // 2) : int((x1 + x2) // 2 - w // 2) + w, :] = face_resized
# mask 출력
mask = torch.zeros_like(kwargs["segs"][i, :, :, 0])
mask_face = kwargs["segs"][i][y1:y2, x1:x2, :].permute(2, 0, 1)
mask_face = torchvision.transforms.Resize((int(h * kwargs["ratio"]), int(w * kwargs["ratio"])))(mask_face).permute(1, 2, 0)
h, w, c = mask_face.shape
mask[y2 - h : y2, int((x1 + x2) // 2 - w // 2) : int((x1 + x2) // 2 - w // 2) + w] = mask_face[:, :, 0]
mask = -1 * mask + 1
mask[:y1] = 0
mask[y2:] = 0
mask[:, :x1] = 0
mask[:, x2:] = 0
kernel = np.ones((kwargs["mask_dilation"], kwargs["mask_dilation"]), np.uint8)
mask = cv2.dilate(mask.numpy(), kernel, iterations=1)
mask = torch.tensor(mask)
mask = mask.unsqueeze(0)
if kwargs["model_detector"]:
mask[:, :y1, x1:x2] = 1
if i == 0:
images = image.unsqueeze(0)
masks = mask
else:
images = torch.cat([images, image.unsqueeze(0)])
masks = torch.cat([masks, mask])
# mask= n,1,h,w
masks = torchvision.transforms.GaussianBlur(kernel_size=kwargs["kernel_size"] * 2 + 1, sigma=kwargs["sigma"])(masks)
if masks.shape[0] ==1:
masks=masks.unsqueeze(0)
return (
images,
masks,
) # image shoulde be n,768,512,3