diff --git a/py/crop_by_mask.py b/py/crop_by_mask.py index d1778ca..4fa89fa 100644 --- a/py/crop_by_mask.py +++ b/py/crop_by_mask.py @@ -9,7 +9,7 @@ class CropByMask: @classmethod def INPUT_TYPES(self): - detect_mode = ['min_bounding_rect', 'max_inscribed_rect'] + detect_mode = ['min_bounding_rect', 'max_inscribed_rect', 'mask_area'] return { "required": { "image": ("IMAGE", ), # @@ -61,8 +61,11 @@ class CropByMask: height = 0 if detect == "min_bounding_rect": (x, y, width, height) = min_bounding_rect(bluredmask) - if detect == "max_inscribed_rect": + elif detect == "max_inscribed_rect": (x, y, width, height) = max_inscribed_rect(bluredmask) + else: + (x, y, width, height) = mask_area(_mask) + log(f"{NODE_NAME}: Box detected. x={x},y={y},width={width},height={height}") canvas_width, canvas_height = tensor2pil(torch.unsqueeze(image[0], 0)).convert('RGB').size x1 = x - left_reserve if x - left_reserve > 0 else 0 y1 = y - top_reserve if y - top_reserve > 0 else 0 diff --git a/py/image_auto_crop.py b/py/image_auto_crop.py index 5020c50..e789570 100644 --- a/py/image_auto_crop.py +++ b/py/image_auto_crop.py @@ -11,7 +11,7 @@ class ImageAutoCrop: @classmethod def INPUT_TYPES(self): matting_method_list = ['RMBG 1.4', 'SegmentAnything'] - detect_mode = ['min_bounding_rect', 'max_inscribed_rect'] + detect_mode = ['min_bounding_rect', 'max_inscribed_rect', 'mask_area'] ratio_list = ['1:1', '3:2', '4:3', '16:9', '2:3', '3:4', '9:16', 'custom', 'detect_mask'] return { "required": { @@ -97,8 +97,10 @@ class ImageAutoCrop: y_offset = 0 if detect == "min_bounding_rect": (x, y, width, height) = min_bounding_rect(bluredmask) - if detect == "max_inscribed_rect": + elif detect == "max_inscribed_rect": (x, y, width, height) = max_inscribed_rect(bluredmask) + else: + (x, y, width, height) = mask_area(bluredmask) canvas_width, canvas_height = _image.size x1 = x - border_reserve y1 = y - border_reserve diff --git a/py/imagefunc.py b/py/imagefunc.py index a2903c5..5d31a3c 100644 --- a/py/imagefunc.py +++ b/py/imagefunc.py @@ -974,6 +974,18 @@ def RGB2RGBA(image:Image, mask:Image) -> Image: (R, G, B) = image.convert('RGB').split() return Image.merge('RGBA', (R, G, B, mask.convert('L'))) +def mask_area(image:Image) -> tuple: + cv2_image = pil2cv2(image.convert('RGBA')) + gray = cv2.cvtColor(cv2_image, cv2.COLOR_BGR2GRAY) + _, thresh = cv2.threshold(gray, 127, 255, 0) + locs = np.where(thresh == 255) + x1 = np.min(locs[1]) + x2 = np.max(locs[1]) + y1 = np.min(locs[0]) + y2 = np.max(locs[0]) + x1, y1, x2, y2 = min(x1, x2), min(y1, y2), max(x1, x2), max(y1, y2) + return (x1, y1, x2 - x1, y2 - y1) + def min_bounding_rect(image:Image) -> tuple: cv2_image = pil2cv2(image) gray = cv2.cvtColor(cv2_image, cv2.COLOR_BGR2GRAY) diff --git a/py/mask_box_detect.py b/py/mask_box_detect.py index b8593cc..c242916 100644 --- a/py/mask_box_detect.py +++ b/py/mask_box_detect.py @@ -9,7 +9,7 @@ class MaskBoxDetect: @classmethod def INPUT_TYPES(self): - detect_mode = ['min_bounding_rect', 'max_inscribed_rect'] + detect_mode = ['min_bounding_rect', 'max_inscribed_rect', 'mask_area'] return { "required": { "mask": ("MASK", ), @@ -46,8 +46,11 @@ class MaskBoxDetect: if detect == "min_bounding_rect": (x, y, width, height) = min_bounding_rect(_mask) - if detect == "max_inscribed_rect": + elif detect == "max_inscribed_rect": (x, y, width, height) = max_inscribed_rect(_mask) + else: + (x, y, width, height) = mask_area(_mask) + log(f"{NODE_NAME}: Box detected. x={x},y={y},width={width},height={height}") _width = width _height = height if scale_adjust != 1.0: diff --git a/py/mask_edge_ultrl_detail.py b/py/mask_edge_ultrl_detail.py index 041dad2..5d7ec63 100644 --- a/py/mask_edge_ultrl_detail.py +++ b/py/mask_edge_ultrl_detail.py @@ -52,13 +52,12 @@ class MaskEdgeUltraDetail: _mask = l_masks[i] if mask_grow != 0: _mask = expand_mask(_mask, mask_grow, mask_grow//2) + if fix_gap: + _mask = mask_fix(_mask, 1, fix_gap, fix_threshold, fix_threshold) if method == 'OpenCV-GuidedFilter': - if fix_gap: - _mask = mask_fix(_mask, 1, fix_gap, fix_threshold, fix_threshold) _mask = guided_filter_alpha(_image, _mask, detail_range) _mask = tensor2pil(histogram_remap(_mask, black_point, white_point)) else: - _mask = mask_fix(_mask, 1, fix_gap, fix_threshold, fix_threshold) _mask = tensor2pil(mask_edge_detail(_image, _mask, detail_range, black_point, white_point)) ret_image = RGB2RGBA(orig_image, _mask.convert('L')) diff --git a/py/mask_gradient.py b/py/mask_gradient.py index 00698a6..6cbfdf7 100644 --- a/py/mask_gradient.py +++ b/py/mask_gradient.py @@ -33,6 +33,7 @@ class MaskGradient: def mask_gradient(self, mask, invert_mask, gradient_side, gradient_scale, gradient_offset, opacity, ): + if mask.dim() == 2: mask = torch.unsqueeze(mask, 0) @@ -50,8 +51,10 @@ class MaskGradient: width = _mask.width height = _mask.height _gradient = gradient('#000000', '#FFFFFF', - _mask.width, _mask.height, 0) - (box_x, box_y, box_width, box_height) = min_bounding_rect(_mask) + 1024, 1024, 0) + # (box_x, box_y, box_width, box_height) = min_bounding_rect(_mask) + (box_x, box_y, box_width, box_height) = mask_area(_mask) + log(f"{NODE_NAME}: Box detected. x={box_x},y={box_y},width={box_width},height={box_height}") if box_width < 1 or box_height < 1: log(f"Error: {NODE_NAME} skipped, because the mask is does'nt have valid area", message_type='error') return (mask,)