浏览代码

Merge pull request #15583 from AUTOMATIC1111/get_crop_region_v2

get_crop_region_v2
AUTOMATIC1111 1 年之前
父节点
当前提交
e6a8d0b4e6
共有 2 个文件被更改,包括 44 次插入18 次删除
  1. 32 10
      modules/masking.py
  2. 12 8
      modules/processing.py

+ 32 - 10
modules/masking.py

@@ -1,17 +1,39 @@
 from PIL import Image, ImageFilter, ImageOps
 
 
-def get_crop_region(mask, pad=0):
-    """finds a rectangular region that contains all masked ares in an image. Returns (x1, y1, x2, y2) coordinates of the rectangle.
-    For example, if a user has painted the top-right part of a 512x512 image, the result may be (256, 0, 512, 256)"""
-    mask_img = mask if isinstance(mask, Image.Image) else Image.fromarray(mask)
-    box = mask_img.getbbox()
-    if box:
+def get_crop_region_v2(mask, pad=0):
+    """
+    Finds a rectangular region that contains all masked ares in a mask.
+    Returns None if mask is completely black mask (all 0)
+
+    Parameters:
+    mask: PIL.Image.Image L mode or numpy 1d array
+    pad: int number of pixels that the region will be extended on all sides
+    Returns: (x1, y1, x2, y2) | None
+
+    Introduced post 1.9.0
+    """
+    mask = mask if isinstance(mask, Image.Image) else Image.fromarray(mask)
+    if box := mask.getbbox():
         x1, y1, x2, y2 = box
-    else:  # when no box is found
-        x1, y1 = mask_img.size
-        x2 = y2 = 0
-    return max(x1 - pad, 0), max(y1 - pad, 0), min(x2 + pad, mask_img.size[0]), min(y2 + pad, mask_img.size[1])
+        return max(x1 - pad, 0), max(y1 - pad, 0), min(x2 + pad, mask.size[0]), min(y2 + pad, mask.size[1]) if pad else box
+
+
+def get_crop_region(mask, pad=0):
+    """
+    Same function as get_crop_region_v2 but handles completely black mask (all 0) differently
+    when mask all black still return coordinates but the coordinates may be invalid ie x2>x1 or y2>y1
+    Notes: it is possible for the coordinates to be "valid" again if pad size is sufficiently large
+    (mask_size.x-pad, mask_size.y-pad, pad, pad)
+
+    Extension developer should use get_crop_region_v2 instead unless for compatibility considerations.
+    """
+    mask = mask if isinstance(mask, Image.Image) else Image.fromarray(mask)
+    if box := get_crop_region_v2(mask, pad):
+        return box
+    x1, y1 = mask.size
+    x2 = y2 = 0
+    return max(x1 - pad, 0), max(y1 - pad, 0), min(x2 + pad, mask.size[0]), min(y2 + pad, mask.size[1])
 
 
 def expand_crop_region(crop_region, processing_width, processing_height, image_width, image_height):

+ 12 - 8
modules/processing.py

@@ -1611,19 +1611,23 @@ class StableDiffusionProcessingImg2Img(StableDiffusionProcessing):
             if self.inpaint_full_res:
                 self.mask_for_overlay = image_mask
                 mask = image_mask.convert('L')
-                crop_region = masking.get_crop_region(mask, self.inpaint_full_res_padding)
-                if crop_region[0] >= crop_region[2] and crop_region[1] >= crop_region[3]:
-                    crop_region = None
-                    image_mask = None
-                    self.mask_for_overlay = None
-                else:
+                crop_region = masking.get_crop_region_v2(mask, self.inpaint_full_res_padding)
+                if crop_region:
                     crop_region = masking.expand_crop_region(crop_region, self.width, self.height, mask.width, mask.height)
                     x1, y1, x2, y2 = crop_region
                     mask = mask.crop(crop_region)
                     image_mask = images.resize_image(2, mask, self.width, self.height)
+                    self.inpaint_full_res = False
                     self.paste_to = (x1, y1, x2-x1, y2-y1)
-                self.extra_generation_params["Inpaint area"] = "Only masked"
-                self.extra_generation_params["Masked area padding"] = self.inpaint_full_res_padding
+                    self.extra_generation_params["Inpaint area"] = "Only masked"
+                    self.extra_generation_params["Masked area padding"] = self.inpaint_full_res_padding
+                else:
+                    crop_region = None
+                    image_mask = None
+                    self.mask_for_overlay = None
+                    massage = 'Unable to perform "Inpaint Only mask" because mask is blank, switch to img2img mode.'
+                    model_hijack.comments.append(massage)
+                    logging.info(massage)
             else:
                 image_mask = images.resize_image(self.resize_mode, image_mask, self.width, self.height)
                 np_mask = np.array(image_mask)