Spaces:
Sleeping
Sleeping
Update rembg/bg.py
Browse files- rembg/bg.py +67 -17
rembg/bg.py
CHANGED
@@ -24,24 +24,19 @@ from .sessions.base import BaseSession
|
|
24 |
|
25 |
kernel = getStructuringElement(MORPH_ELLIPSE, (3, 3))
|
26 |
|
|
|
27 |
class ReturnType(Enum):
|
28 |
BYTES = 0
|
29 |
PILLOW = 1
|
30 |
NDARRAY = 2
|
31 |
|
32 |
-
# Argumentos configurables desde la interfaz Gradio
|
33 |
-
# Estos valores predeterminados pueden modificarse en la interfaz.
|
34 |
-
foreground_threshold = 240
|
35 |
-
background_threshold = 10
|
36 |
-
erode_structure_size = 10
|
37 |
-
alpha_matting = False
|
38 |
-
only_mask = False
|
39 |
-
post_process_mask = False
|
40 |
-
bgcolor = None
|
41 |
|
42 |
def alpha_matting_cutout(
|
43 |
img: PILImage,
|
44 |
mask: PILImage,
|
|
|
|
|
|
|
45 |
) -> PILImage:
|
46 |
if img.mode == "RGBA" or img.mode == "CMYK":
|
47 |
img = img.convert("RGB")
|
@@ -77,15 +72,67 @@ def alpha_matting_cutout(
|
|
77 |
|
78 |
return cutout
|
79 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
80 |
def remove(
|
81 |
data: Union[bytes, PILImage, np.ndarray],
|
82 |
-
alpha_matting: bool =
|
83 |
-
alpha_matting_foreground_threshold: int =
|
84 |
-
alpha_matting_background_threshold: int =
|
85 |
-
alpha_matting_erode_size: int =
|
86 |
-
|
87 |
-
|
88 |
-
|
|
|
89 |
*args: Optional[Any],
|
90 |
**kwargs: Optional[Any]
|
91 |
) -> Union[bytes, PILImage, np.ndarray]:
|
@@ -99,7 +146,7 @@ def remove(
|
|
99 |
return_type = ReturnType.NDARRAY
|
100 |
img = Image.fromarray(data)
|
101 |
else:
|
102 |
-
raise ValueError("Input type {} is not supported.".format(type(data))
|
103 |
|
104 |
# Fix image orientation
|
105 |
img = fix_image_orientation(img)
|
@@ -122,6 +169,9 @@ def remove(
|
|
122 |
cutout = alpha_matting_cutout(
|
123 |
img,
|
124 |
mask,
|
|
|
|
|
|
|
125 |
)
|
126 |
except ValueError:
|
127 |
cutout = naive_cutout(img, mask)
|
|
|
24 |
|
25 |
kernel = getStructuringElement(MORPH_ELLIPSE, (3, 3))
|
26 |
|
27 |
+
|
28 |
class ReturnType(Enum):
|
29 |
BYTES = 0
|
30 |
PILLOW = 1
|
31 |
NDARRAY = 2
|
32 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
33 |
|
34 |
def alpha_matting_cutout(
|
35 |
img: PILImage,
|
36 |
mask: PILImage,
|
37 |
+
foreground_threshold: int,
|
38 |
+
background_threshold: int,
|
39 |
+
erode_structure_size: int,
|
40 |
) -> PILImage:
|
41 |
if img.mode == "RGBA" or img.mode == "CMYK":
|
42 |
img = img.convert("RGB")
|
|
|
72 |
|
73 |
return cutout
|
74 |
|
75 |
+
|
76 |
+
def naive_cutout(img: PILImage, mask: PILImage) -> PILImage:
|
77 |
+
empty = Image.new("RGBA", (img.size), 0)
|
78 |
+
cutout = Image.composite(img, empty, mask)
|
79 |
+
return cutout
|
80 |
+
|
81 |
+
|
82 |
+
def get_concat_v_multi(imgs: List[PILImage]) -> PILImage:
|
83 |
+
pivot = imgs.pop(0)
|
84 |
+
for im in imgs:
|
85 |
+
pivot = get_concat_v(pivot, im)
|
86 |
+
return pivot
|
87 |
+
|
88 |
+
|
89 |
+
def get_concat_v(img1: PILImage, img2: PILImage) -> PILImage:
|
90 |
+
dst = Image.new("RGBA", (img1.width, img1.height + img2.height))
|
91 |
+
dst.paste(img1, (0, 0))
|
92 |
+
dst.paste(img2, (0, img1.height))
|
93 |
+
return dst
|
94 |
+
|
95 |
+
|
96 |
+
def post_process(mask: np.ndarray) -> np.ndarray:
|
97 |
+
"""
|
98 |
+
Post Process the mask for a smooth boundary by applying Morphological Operations
|
99 |
+
Research based on paper: https://www.sciencedirect.com/science/article/pii/S2352914821000757
|
100 |
+
args:
|
101 |
+
mask: Binary Numpy Mask
|
102 |
+
"""
|
103 |
+
mask = morphologyEx(mask, MORPH_OPEN, kernel)
|
104 |
+
mask = GaussianBlur(mask, (5, 5), sigmaX=2, sigmaY=2, borderType=BORDER_DEFAULT)
|
105 |
+
mask = np.where(mask < 127, 0, 255).astype(np.uint8) # convert again to binary
|
106 |
+
return mask
|
107 |
+
|
108 |
+
|
109 |
+
def apply_background_color(img: PILImage, color: Tuple[int, int, int, int]) -> PILImage:
|
110 |
+
r, g, b, a = color
|
111 |
+
colored_image = Image.new("RGBA", img.size, (r, g, b, a))
|
112 |
+
colored_image.paste(img, mask=img)
|
113 |
+
|
114 |
+
return colored_image
|
115 |
+
|
116 |
+
|
117 |
+
def fix_image_orientation(img: PILImage) -> PILImage:
|
118 |
+
return ImageOps.exif_transpose(img)
|
119 |
+
|
120 |
+
|
121 |
+
def download_models() -> None:
|
122 |
+
for session in sessions_class:
|
123 |
+
session.download_models()
|
124 |
+
|
125 |
+
|
126 |
def remove(
|
127 |
data: Union[bytes, PILImage, np.ndarray],
|
128 |
+
alpha_matting: bool = False,
|
129 |
+
alpha_matting_foreground_threshold: int = 240,
|
130 |
+
alpha_matting_background_threshold: int = 10,
|
131 |
+
alpha_matting_erode_size: int = 10,
|
132 |
+
session: Optional[BaseSession] = None,
|
133 |
+
only_mask: bool = False,
|
134 |
+
post_process_mask: bool = False,
|
135 |
+
bgcolor: Optional[Tuple[int, int, int, int]] = None,
|
136 |
*args: Optional[Any],
|
137 |
**kwargs: Optional[Any]
|
138 |
) -> Union[bytes, PILImage, np.ndarray]:
|
|
|
146 |
return_type = ReturnType.NDARRAY
|
147 |
img = Image.fromarray(data)
|
148 |
else:
|
149 |
+
raise ValueError("Input type {} is not supported.".format(type(data)))
|
150 |
|
151 |
# Fix image orientation
|
152 |
img = fix_image_orientation(img)
|
|
|
169 |
cutout = alpha_matting_cutout(
|
170 |
img,
|
171 |
mask,
|
172 |
+
alpha_matting_foreground_threshold,
|
173 |
+
alpha_matting_background_threshold,
|
174 |
+
alpha_matting_erode_size,
|
175 |
)
|
176 |
except ValueError:
|
177 |
cutout = naive_cutout(img, mask)
|