Download src/birefnet.py from vincentkr18/test-all-models: direct link, hf CLI and curl.
- Browser
- Download file 4.53 kB
-
https://huggingface.co/vincentkr18/test-all-models/resolve/main/src/birefnet.py
- Command line
-
hf download hf://vincentkr18/test-all-models/src/birefnet.py
-
curl -L -o birefnet.py https://huggingface.co/vincentkr18/test-all-models/resolve/main/src/birefnet.py
4.53 kB
| import torch | |
| from transformers import AutoModelForImageSegmentation | |
| from torchvision import transforms | |
| from PIL import Image | |
| import numpy as np | |
| # Device setup | |
| _device = torch.device("cuda" if torch.cuda.is_available() else "cpu") | |
| # Global models | |
| _birefnet = None | |
| _birefnet_lite = None | |
| # Preprocessing transform | |
| _transform = transforms.Compose( | |
| [ | |
| transforms.Resize((768, 768)), | |
| transforms.ToTensor(), | |
| transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]), | |
| ] | |
| ) | |
| def load_model(fast_mode=False): | |
| global _birefnet, _birefnet_lite | |
| if fast_mode: | |
| if _birefnet_lite is None: | |
| _birefnet_lite = AutoModelForImageSegmentation.from_pretrained( | |
| "ZhengPeng7/BiRefNet_lite", trust_remote_code=True | |
| ).to(_device) | |
| return _birefnet_lite | |
| else: | |
| if _birefnet is None: | |
| _birefnet = AutoModelForImageSegmentation.from_pretrained( | |
| "ZhengPeng7/BiRefNet", trust_remote_code=True | |
| ).to(_device) | |
| return _birefnet | |
| def unload_model(): | |
| global _birefnet, _birefnet_lite | |
| _birefnet = None | |
| _birefnet_lite = None | |
| if torch.cuda.is_available(): | |
| torch.cuda.empty_cache() | |
| def _apply_mask(image: Image.Image, mask_tensor, bg, bg_type: str): | |
| size = image.size | |
| mask = transforms.ToPILImage()(mask_tensor.squeeze()).resize(size) | |
| if bg_type == "Color" and isinstance(bg, str) and bg.startswith("#"): | |
| color_rgb = tuple(int(bg[i : i + 2], 16) for i in (1, 3, 5)) | |
| bg_image = Image.new("RGBA", size, color_rgb + (255,)) | |
| elif bg_type in ["Image", "Video"]: | |
| bg_image = bg.convert("RGBA").resize(size) | |
| else: | |
| raise ValueError("Invalid background type or format") | |
| return Image.composite(image.convert("RGBA"), bg_image, mask) | |
| def _get_transform(image_size: tuple[int, int] | None = None): | |
| if image_size: | |
| resize = transforms.Resize(image_size) | |
| else: | |
| resize = transforms.Resize((768, 768)) # default fallback | |
| return transforms.Compose( | |
| [ | |
| resize, | |
| transforms.ToTensor(), | |
| transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]), | |
| ] | |
| ) | |
| def predict( | |
| input: Image.Image | list[Image.Image], | |
| bg: str | Image.Image, | |
| bg_type: str = "Color", | |
| fast_mode: bool = True, | |
| bg_frames: list[np.ndarray] | None = None, | |
| image_size_mode: str = "default", # "default", "origin", or "custom" | |
| custom_size: tuple[int, int] | None = None, | |
| ) -> Image.Image | list[Image.Image]: | |
| model = _birefnet_lite if fast_mode else _birefnet | |
| if model is None: | |
| raise RuntimeError("Model not loaded. Please call `load_model()` first.") | |
| def get_transform_for_img(img: Image.Image): | |
| if image_size_mode == "origin": | |
| return _get_transform(img.size) | |
| elif image_size_mode == "custom": | |
| if not custom_size: | |
| raise ValueError("`custom_size` must be provided for 'custom' mode.") | |
| return _get_transform(custom_size) | |
| else: | |
| return _get_transform() # default to (768, 768) | |
| if isinstance(input, Image.Image): | |
| _transform = get_transform_for_img(input) | |
| input_tensor = _transform(input).unsqueeze(0).to(_device) | |
| with torch.no_grad(): | |
| pred = model(input_tensor)[-1].sigmoid().cpu() | |
| bg_image = ( | |
| Image.fromarray(bg_frames[0]) if bg_type == "Video" and bg_frames else bg | |
| ) | |
| return _apply_mask(input, pred[0], bg_image, bg_type) | |
| elif isinstance(input, list): | |
| results = [] | |
| for idx, frame in enumerate(input): | |
| _transform = get_transform_for_img(frame) | |
| input_tensor = _transform(frame).unsqueeze(0).to(_device) | |
| with torch.no_grad(): | |
| pred = model(input_tensor)[-1].sigmoid().cpu() | |
| if bg_type == "Video" and bg_frames: | |
| bg_image = Image.fromarray(bg_frames[idx % len(bg_frames)]) | |
| else: | |
| bg_image = bg | |
| results.append(_apply_mask(frame, pred[0], bg_image, bg_type)) | |
| return results | |
| else: | |
| raise TypeError("`input` must be a PIL.Image or a list of PIL.Image.") | |
| # # Default behavior (768x768) | |
| # predict(img, "#ffffff", "Color") | |
| # # Keep original image size | |
| # predict(img, "#ffffff", "Color", image_size_mode="origin") | |
| # # Resize to 1024x1024 | |
| # predict(img, "#ffffff", "Color", image_size_mode="custom", custom_size=(1024, 1024)) | |