fixed a bug with simple_square and convex_hull masks size
This commit is contained in:
@@ -57,45 +57,45 @@ class OrderedFaceFilter:
|
||||
rest = sorted_faces[:take_start] + sorted_faces[take_start+take_count:]
|
||||
return (filtered, rest)
|
||||
|
||||
class FaceDetailsDEPRECATED:
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
'required': {
|
||||
'faces': ('FACE',),
|
||||
'crop_size': ('INT', {'default': 512, 'min': 512, 'max': 1024, 'step': 128}),
|
||||
'crop_factor': ('FLOAT', {'default': 1.5, 'min': 1.0, 'max': 3, 'step': 0.1}),
|
||||
'mask_type': (mask_types,)
|
||||
}
|
||||
}
|
||||
# class FaceDetailsDEPRECATED:
|
||||
# @classmethod
|
||||
# def INPUT_TYPES(cls):
|
||||
# return {
|
||||
# 'required': {
|
||||
# 'faces': ('FACE',),
|
||||
# 'crop_size': ('INT', {'default': 512, 'min': 512, 'max': 1024, 'step': 128}),
|
||||
# 'crop_factor': ('FLOAT', {'default': 1.5, 'min': 1.0, 'max': 3, 'step': 0.1}),
|
||||
# 'mask_type': (mask_types,)
|
||||
# }
|
||||
# }
|
||||
|
||||
RETURN_TYPES = ('IMAGE', 'MASK', 'WARP')
|
||||
RETURN_NAMES = ('crops', 'masks', 'warps')
|
||||
FUNCTION = 'run'
|
||||
CATEGORY = 'facetools'
|
||||
# RETURN_TYPES = ('IMAGE', 'MASK', 'WARP')
|
||||
# RETURN_NAMES = ('crops', 'masks', 'warps')
|
||||
# FUNCTION = 'run'
|
||||
# CATEGORY = 'facetools'
|
||||
|
||||
def run(self, faces, crop_size, crop_factor, mask_type):
|
||||
if len(faces) == 0:
|
||||
empty_crop = torch.zeros((1,512,512,3))
|
||||
empty_mask = torch.zeros((1,512,512))
|
||||
empty_warp = np.array([
|
||||
[1,0,-512],
|
||||
[0,1,-512],
|
||||
], dtype=np.float32)
|
||||
return (empty_crop, empty_mask, [empty_warp])
|
||||
# def run(self, faces, crop_size, crop_factor, mask_type):
|
||||
# if len(faces) == 0:
|
||||
# empty_crop = torch.zeros((1,512,512,3))
|
||||
# empty_mask = torch.zeros((1,512,512))
|
||||
# empty_warp = np.array([
|
||||
# [1,0,-512],
|
||||
# [0,1,-512],
|
||||
# ], dtype=np.float32)
|
||||
# return (empty_crop, empty_mask, [empty_warp])
|
||||
|
||||
crops = []
|
||||
masks = []
|
||||
warps = []
|
||||
for face in faces:
|
||||
M, crop = crop_faces(face.image, face, crop_size, crop_factor)
|
||||
mask = mask_crop(face, M, crop, mask_type)
|
||||
crops.append(np.array(crop) / 255)
|
||||
masks.append(np.array(mask))
|
||||
warps.append(M)
|
||||
crops = torch.from_numpy(np.array(crops)).type(torch.float32)
|
||||
masks = torch.from_numpy(np.array(masks)).type(torch.float32)
|
||||
return (crops, masks, warps)
|
||||
# crops = []
|
||||
# masks = []
|
||||
# warps = []
|
||||
# for face in faces:
|
||||
# M, crop = crop_faces(face.image, face, crop_size, crop_factor)
|
||||
# mask = mask_crop(face, M, crop, mask_type)
|
||||
# crops.append(np.array(crop) / 255)
|
||||
# masks.append(np.array(mask))
|
||||
# warps.append(M)
|
||||
# crops = torch.from_numpy(np.array(crops)).type(torch.float32)
|
||||
# masks = torch.from_numpy(np.array(masks)).type(torch.float32)
|
||||
# return (crops, masks, warps)
|
||||
|
||||
class DetectFaces:
|
||||
@classmethod
|
||||
@@ -175,38 +175,38 @@ class CropFaces:
|
||||
masks = torch.from_numpy(np.array(masks)).type(torch.float32)
|
||||
return (crops, masks, warps)
|
||||
|
||||
class AlignFacesDEPRECATED:
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
'required': {
|
||||
'insightface': ('INSIGHTFACE',),
|
||||
'image': ('IMAGE',),
|
||||
'threshold': ('FLOAT', {'default': 0.5, 'min': 0.5, 'max': 1.0, 'step': 0.01}),
|
||||
'min_size': ('INT', {'default': 64, 'max': 512, 'step': 8}),
|
||||
'max_size': ('INT', {'default': 512, 'min': 512, 'step': 8}),
|
||||
}
|
||||
}
|
||||
# class AlignFacesDEPRECATED:
|
||||
# @classmethod
|
||||
# def INPUT_TYPES(cls):
|
||||
# return {
|
||||
# 'required': {
|
||||
# 'insightface': ('INSIGHTFACE',),
|
||||
# 'image': ('IMAGE',),
|
||||
# 'threshold': ('FLOAT', {'default': 0.5, 'min': 0.5, 'max': 1.0, 'step': 0.01}),
|
||||
# 'min_size': ('INT', {'default': 64, 'max': 512, 'step': 8}),
|
||||
# 'max_size': ('INT', {'default': 512, 'min': 512, 'step': 8}),
|
||||
# }
|
||||
# }
|
||||
|
||||
RETURN_TYPES = ('FACE',)
|
||||
RETURN_NAMES = ('faces',)
|
||||
FUNCTION = 'run'
|
||||
CATEGORY = 'facetools'
|
||||
# RETURN_TYPES = ('FACE',)
|
||||
# RETURN_NAMES = ('faces',)
|
||||
# FUNCTION = 'run'
|
||||
# CATEGORY = 'facetools'
|
||||
|
||||
def run(self, insightface, image, threshold, min_size, max_size):
|
||||
faces = []
|
||||
images = (image * 255).type(torch.uint8).numpy()
|
||||
for i, img in enumerate(images):
|
||||
unfiltered_faces = get_faces(img, insightface)
|
||||
for face in unfiltered_faces:
|
||||
a, b, c, d = face.bbox
|
||||
h = abs(d-b)
|
||||
w = abs(c-a)
|
||||
if face.det_score >= threshold and (h <= max_size or w <= max_size) and (min_size <= h or min_size <= w):
|
||||
face.image_idx = i
|
||||
face.image = img
|
||||
faces.append(face)
|
||||
return (faces,)
|
||||
# def run(self, insightface, image, threshold, min_size, max_size):
|
||||
# faces = []
|
||||
# images = (image * 255).type(torch.uint8).numpy()
|
||||
# for i, img in enumerate(images):
|
||||
# unfiltered_faces = get_faces(img, insightface)
|
||||
# for face in unfiltered_faces:
|
||||
# a, b, c, d = face.bbox
|
||||
# h = abs(d-b)
|
||||
# w = abs(c-a)
|
||||
# if face.det_score >= threshold and (h <= max_size or w <= max_size) and (min_size <= h or min_size <= w):
|
||||
# face.image_idx = i
|
||||
# face.image = img
|
||||
# faces.append(face)
|
||||
# return (faces,)
|
||||
|
||||
class WarpFaceBack:
|
||||
RETURN_TYPES = ('IMAGE',)
|
||||
@@ -291,9 +291,9 @@ class MergeWarps:
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
'DetectFaces': DetectFaces,
|
||||
'CropFaces': CropFaces,
|
||||
'AlignFaces': AlignFacesDEPRECATED,
|
||||
# 'AlignFaces': AlignFacesDEPRECATED,
|
||||
'WarpFacesBack': WarpFaceBack,
|
||||
'FaceDetails': FaceDetailsDEPRECATED,
|
||||
# 'FaceDetails': FaceDetailsDEPRECATED,
|
||||
'MergeWarps': MergeWarps,
|
||||
'GenderFaceFilter': GenderFaceFilter,
|
||||
'OrderedFaceFilter': OrderedFaceFilter,
|
||||
@@ -302,9 +302,9 @@ NODE_CLASS_MAPPINGS = {
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
'DetectFaces': 'DetectFaces',
|
||||
'CropFaces': 'CropFaces',
|
||||
'AlignFaces': 'Align Faces (DEPRECATED)',
|
||||
# 'AlignFaces': 'Align Faces (DEPRECATED)',
|
||||
'WarpFacesBack': 'Warp Faces Back',
|
||||
'FaceDetails': 'Face Details (DEPRECATED)',
|
||||
# 'FaceDetails': 'Face Details (DEPRECATED)',
|
||||
'MergeWarps': 'Merge Warps',
|
||||
'GenderFaceFilter': 'Gender Face Filter',
|
||||
'OrderedFaceFilter': 'Ordered Face Filter',
|
||||
|
||||
@@ -202,6 +202,7 @@ def get_face_mesh(crop):
|
||||
|
||||
def mask_simple_square(face, M, crop):
|
||||
# rotated bbox and size
|
||||
h,w = crop.shape[:2]
|
||||
a,b,c,d = face.bbox
|
||||
rect = np.array([
|
||||
[a,b,1],
|
||||
@@ -211,15 +212,16 @@ def mask_simple_square(face, M, crop):
|
||||
]) @ M.T
|
||||
lx, ly = [int(x) for x in np.min(rect, axis=0)]
|
||||
hx, hy = [int(x) for x in np.max(rect, axis=0)]
|
||||
mask = np.zeros((512,512), dtype=np.float32)
|
||||
mask = np.zeros((h,w), dtype=np.float32)
|
||||
mask = cv2.rectangle(mask, (lx,ly), (hx,hy), 1, -1)
|
||||
return mask
|
||||
|
||||
def mask_convex_hull(face, M, crop):
|
||||
h,w = crop.shape[:2]
|
||||
points = get_face_mesh(crop)
|
||||
if points is None: return mask_simple_square(face, M, crop)
|
||||
hull = ConvexHull(points)
|
||||
mask = np.zeros((512,512), dtype=np.int32)
|
||||
mask = np.zeros((h,w), dtype=np.int32)
|
||||
cv2.fillPoly(mask, [points[hull.vertices,:]], color=1)
|
||||
mask = mask.astype(np.float32)
|
||||
return mask
|
||||
|
||||
Reference in New Issue
Block a user