sam-3d-objecting / src /utils.py
hiendang7613vulcanlabs's picture
Add skip SAM-3 checkbox with white background removal option
3f7a009
import re
from pathlib import Path
from PIL import Image
def natural_key(s: str):
"""Natural sort key: '10.png' sorts after '2.png' correctly."""
return [int(t) if t.isdigit() else t.lower() for t in re.split(r"(\d+)", s)]
def load_rgb_image(path: str | Path) -> Image.Image:
img = Image.open(path)
if img.mode != "RGB":
img = img.convert("RGB")
return img
def save_rgb_png(img: Image.Image, path: str | Path):
path = Path(path)
path.parent.mkdir(parents=True, exist_ok=True)
img.save(path, format="PNG")
def make_rgba_with_alpha(rgb_img: Image.Image, alpha_mask: Image.Image) -> Image.Image:
"""
rgb_img: RGB PIL
alpha_mask: L PIL, same size or will be resized
Returns RGBA PIL where alpha channel is the mask.
"""
if rgb_img.mode != "RGB":
rgb_img = rgb_img.convert("RGB")
if alpha_mask.mode != "L":
alpha_mask = alpha_mask.convert("L")
if alpha_mask.size != rgb_img.size:
alpha_mask = alpha_mask.resize(rgb_img.size, Image.NEAREST)
rgba = rgb_img.copy()
rgba.putalpha(alpha_mask)
return rgba
def save_rgba_png(img: Image.Image, path: str | Path):
path = Path(path)
path.parent.mkdir(parents=True, exist_ok=True)
img.save(path, format="PNG")
def remove_white_background_alpha(img: Image.Image, threshold: int = 240) -> Image.Image:
"""
Create an alpha mask by treating near-white pixels as background.
Pixels where R, G, B are all >= threshold are considered background (alpha=0).
All other pixels get alpha=255.
Returns L mode image (0=background, 255=foreground).
"""
import numpy as np
if img.mode != "RGB":
img = img.convert("RGB")
arr = np.array(img) # (H, W, 3)
# Background = all channels >= threshold
is_white = (arr[:, :, 0] >= threshold) & (arr[:, :, 1] >= threshold) & (arr[:, :, 2] >= threshold)
alpha = np.where(is_white, 0, 255).astype(np.uint8)
return Image.fromarray(alpha, mode="L")