Skip to content

Commit 53fb4ce

Browse files
committed
Add --mask-threshold, cap workers at 4, print device info, bump to 0.4.0
- Add -mt/--mask-threshold for hard/sharp edges on cartoonish images (fixes #122) - Cap worker count at 4 to prevent hangs and GPU memory exhaustion (fixes #181) - Print detected device (CUDA/MPS/CPU) at startup for debugging (helps #145) - Expose mask_threshold via HTTP API server (?mt= parameter)
1 parent 4208677 commit 53fb4ce

5 files changed

Lines changed: 26 additions & 6 deletions

File tree

backgroundremover/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@
44
A library to remove background from videos and images
55
"""
66

7-
__version__ = "0.3.9"
7+
__version__ = "0.4.0"
88
__author__ = 'Johnathan Nader'
99
__credits__ = 'BackgroundRemoverAI.com'

backgroundremover/bg.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,15 @@
2727
try:
2828
if torch.cuda.is_available():
2929
DEVICE = torch.device('cuda:0')
30+
print(f"Device: CUDA ({torch.cuda.get_device_name(0)})")
3031
elif torch.backends.mps.is_available():
3132
DEVICE = torch.device('mps')
33+
print("Device: MPS (Apple Silicon GPU)")
3234
else:
3335
DEVICE = torch.device('cpu')
36+
print("Device: CPU (no GPU detected - install CUDA toolkit for GPU acceleration)")
3437
except Exception as e:
35-
print(f"Using CPU. Setting Cuda or MPS failed: {e}")
38+
print(f"Device: CPU (Setting CUDA or MPS failed: {e})")
3639
DEVICE = torch.device('cpu')
3740

3841
class Net(torch.nn.Module):
@@ -216,6 +219,7 @@ def remove(
216219
only_mask=False,
217220
background_color=None,
218221
background_image=None,
222+
mask_threshold=None,
219223
):
220224
model = get_model(model_name)
221225

@@ -232,6 +236,10 @@ def remove(
232236

233237
mask = detect.predict(model, np.array(img)).convert("L")
234238

239+
# Apply threshold for hard/sharp edges (fixes #122)
240+
if mask_threshold is not None:
241+
mask = mask.point(lambda p: 255 if p > mask_threshold else 0)
242+
235243
# If only_mask is True, return just the mask
236244
if only_mask:
237245
bio = io.BytesIO()

backgroundremover/cmd/cli.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,14 @@ def main():
7171
help="Output only the binary mask (grayscale image).",
7272
)
7373

74+
ap.add_argument(
75+
"-mt",
76+
"--mask-threshold",
77+
default=None,
78+
type=int,
79+
help="Threshold (0-255) to binarize the mask for hard/sharp edges. Useful for cartoonish images. Values around 128 work well.",
80+
)
81+
7482
ap.add_argument(
7583
"-bc",
7684
"--background-color",
@@ -240,10 +248,11 @@ def main():
240248
print("Example: backgroundremover -i video.mp4 -tgwb -bi background.png -o output.gif")
241249
exit(1)
242250

243-
# Warn about high worker counts that may cause issues
251+
# Cap worker count to prevent hangs and resource exhaustion (see issue #181)
244252
if args.workernodes > 4:
245-
print(f"Warning: Using {args.workernodes} workers. High worker counts (>4) may cause ConnectionResetError or crashes on some systems.")
246-
print("If you experience errors, try reducing workers with -wn 1 or -wn 2")
253+
print(f"Warning: Requested {args.workernodes} workers, capping at 4. Higher values cause hangs and GPU memory exhaustion.")
254+
print("Use -wn 1 through -wn 4 for best results.")
255+
args.workernodes = 4
247256

248257
# Parse background color if provided
249258
background_color = None
@@ -348,6 +357,7 @@ def is_image_file(filename):
348357
only_mask=args.only_mask,
349358
background_color=background_color,
350359
background_image=background_image,
360+
mask_threshold=args.mask_threshold,
351361
),
352362
)
353363
return

backgroundremover/cmd/server.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ def index():
3838
ab = request.values.get("ab", type=int, default=10)
3939
ae = request.values.get("ae", type=int, default=10)
4040
az = request.values.get("az", type=int, default=1000)
41+
mt = request.values.get("mt", type=int, default=None)
4142

4243
model = request.args.get("model", type=str, default="u2net")
4344
model_path = os.environ.get(
@@ -62,6 +63,7 @@ def index():
6263
alpha_matting_background_threshold=ab,
6364
alpha_matting_erode_structure_size=ae,
6465
alpha_matting_base_size=az,
66+
mask_threshold=mt,
6567
)
6668
),
6769
mimetype="image/png",

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
setup(
1313
name="backgroundremover",
14-
version="0.3.9",
14+
version="0.4.0",
1515
description="Background remover from image and video using AI",
1616
long_description=long_description,
1717
long_description_content_type="text/markdown",

0 commit comments

Comments
 (0)