import os from typing import Tuple, Union import gradio as gr import spaces import torch from loadimg import load_img from PIL import Image from torchvision import transforms from transformers import AutoModelForImageSegmentation torch.set_float32_matmul_precision("high") DEVICE = "cuda" if torch.cuda.is_available() else "cpu" birefnet = AutoModelForImageSegmentation.from_pretrained( "ZhengPeng7/BiRefNet", trust_remote_code=True ) birefnet.to(DEVICE) birefnet.eval() # Keep inference inputs aligned with the loaded model precision (fp16/fp32). MODEL_DTYPE = next(birefnet.parameters()).dtype transform_image = transforms.Compose( [ transforms.Resize((1024, 1024)), transforms.ToTensor(), transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]), ] ) EXAMPLE_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "examples") EXAMPLE_IMAGE = os.path.join(EXAMPLE_DIR, "butterfly.jpg") EXAMPLE_URL = ( "https://hips.hearstapps.com/hmg-prod/images/gettyimages-1229892983-square.jpg" ) @spaces.GPU def process(image: Image.Image) -> Image.Image: """ Apply BiRefNet-based image segmentation to remove the background. Args: image (PIL.Image): The input RGB image. Returns: PIL.Image: The image with the background removed, using the segmentation mask as transparency. """ image_size = image.size input_images = ( transform_image(image).unsqueeze(0).to(device=DEVICE, dtype=MODEL_DTYPE) ) with torch.no_grad(): preds = birefnet(input_images)[-1].sigmoid().cpu() pred = preds[0].squeeze() pred_pil = transforms.ToPILImage()(pred) mask = pred_pil.resize(image_size) image.putalpha(mask) return image def remove_bg(image: Union[Image.Image, str]) -> Tuple[Image.Image, Image.Image]: """Remove the background from an uploaded image or an image URL.""" im = load_img(image, output_type="pil").convert("RGB") origin = im.copy() return origin, process(im) def remove_bg_to_file(f: str) -> str: """Load an image file from disk, remove the background, and save as a transparent PNG.""" name_path = os.path.splitext(f)[0] + ".png" im = load_img(f, output_type="pil").convert("RGB") process(im).save(name_path) return name_path AUTHOR_NAME = "Bijaya Kumar Tiadi" AUTHOR_TITLE = "Full-Stack Developer" UPWORK_URL = "https://www.upwork.com/freelancers/~01d86f12209c236752" LINKEDIN_URL = "https://www.linkedin.com/in/bijayakumartiadi/" THEME = gr.themes.Soft( primary_hue="violet", secondary_hue="purple", neutral_hue="slate", font=[gr.themes.GoogleFont("Inter"), "ui-sans-serif", "system-ui", "sans-serif"], ) CSS = """ .gradio-container { max-width: 980px !important; margin: 0 auto !important; } #hero { text-align: center; padding: 34px 24px 30px; margin-bottom: 8px; border-radius: 20px; background: linear-gradient(135deg, #7c3aed 0%, #a855f7 45%, #d946ef 100%); box-shadow: 0 10px 30px -12px rgba(124, 58, 237, 0.55); } #hero h1 { font-size: 2.3rem; margin-bottom: 6px; color: #ffffff; font-weight: 800; letter-spacing: -0.02em; } #hero p { color: rgba(255,255,255,0.92); font-size: 1.05rem; margin: 0 auto; max-width: 560px; } #hero .badges { margin-top: 14px; display: flex; gap: 8px; justify-content: center; flex-wrap: wrap; } #hero .badge { display: inline-block; padding: 4px 12px; border-radius: 999px; background: rgba(255,255,255,0.18); color: #fff; font-size: 0.78rem; font-weight: 600; backdrop-filter: blur(4px); border: 1px solid rgba(255,255,255,0.3); } #run-btn { min-height: 46px; font-weight: 600; } .hire-card { margin-top: 18px; padding: 22px 26px; border-radius: 18px; background: var(--block-background-fill); border: 1px solid var(--border-color-primary); display: flex; align-items: center; justify-content: space-between; gap: 20px; flex-wrap: wrap; } .hire-card .who { display: flex; align-items: center; gap: 14px; } .hire-card .avatar { width: 48px; height: 48px; border-radius: 50%; flex-shrink: 0; background: linear-gradient(135deg, #7c3aed, #d946ef); color: #fff; display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: 1.05rem; } .hire-card .name { font-weight: 700; font-size: 1.05rem; margin: 0; } .hire-card .tagline { margin: 0; opacity: 0.7; font-size: 0.9rem; } .hire-card .cta { margin: 0 0 0 2px; opacity: 0.75; font-size: 0.85rem; } .btn-row { display: flex; gap: 10px; flex-wrap: wrap; } .btn-pill { display: inline-flex; align-items: center; gap: 8px; padding: 10px 18px; border-radius: 999px; font-weight: 600; font-size: 0.9rem; text-decoration: none !important; transition: transform 0.15s ease, box-shadow 0.15s ease; box-shadow: 0 2px 8px rgba(0,0,0,0.12); } .btn-pill:hover { transform: translateY(-2px); box-shadow: 0 6px 16px rgba(0,0,0,0.18); } .btn-pill svg { width: 16px; height: 16px; fill: currentColor; } .btn-upwork { background: #14a800; color: #fff !important; } .btn-linkedin { background: #0a66c2; color: #fff !important; } .footer-note { text-align: center; opacity: 0.6; font-size: 0.82rem; margin-top: 14px; } .footer-note a { color: inherit; } """ with gr.Blocks(title="Background Remover") as demo: gr.Markdown( """

๐Ÿช„ Background Remover

Drop an image, get a clean transparent cutout. Powered by the open-source BiRefNet model โ€” free, no sign-up, no watermark.

โšก Free to use ๐Ÿ–ผ๏ธ No watermark ๐Ÿ”Œ API / MCP ready
""" ) with gr.Tabs(): with gr.Tab("๐Ÿ“ค Upload"): with gr.Row(): with gr.Column(): upload_in = gr.Image( label="Source image", type="pil", sources=["upload", "clipboard"] ) upload_btn = gr.Button( "Remove background", variant="primary", elem_id="run-btn" ) with gr.Column(): upload_out = gr.ImageSlider( label="Result โ€” drag to compare", type="pil", format="png" ) gr.Examples(examples=[EXAMPLE_IMAGE], inputs=upload_in, label="Try an example") upload_btn.click(remove_bg, inputs=upload_in, outputs=upload_out, api_name="image") with gr.Tab("๐Ÿ”— Image URL"): with gr.Row(): with gr.Column(): url_in = gr.Textbox( label="Image URL", placeholder="https://example.com/photo.jpg" ) url_btn = gr.Button( "Remove background", variant="primary", elem_id="run-btn" ) with gr.Column(): url_out = gr.ImageSlider( label="Result โ€” drag to compare", type="pil", format="png" ) gr.Examples(examples=[EXAMPLE_URL], inputs=url_in, label="Try an example") url_btn.click(remove_bg, inputs=url_in, outputs=url_out, api_name="text") with gr.Tab("๐Ÿ“ File โ†’ PNG"): gr.Markdown("Upload a file and get back a downloadable transparent PNG โ€” handy for automation, the API, or MCP.") with gr.Row(): file_in = gr.Image(label="Source image", type="filepath") file_out = gr.File(label="Transparent PNG") file_btn = gr.Button("Generate PNG", variant="primary", elem_id="run-btn") gr.Examples(examples=[EXAMPLE_IMAGE], inputs=file_in, label="Try an example") file_btn.click(remove_bg_to_file, inputs=file_in, outputs=file_out, api_name="png") gr.HTML( f"""
BT

{AUTHOR_NAME}

{AUTHOR_TITLE}

Need something like this built for your product? Let's talk ๐Ÿ‘‡

Hire me on Upwork Connect on LinkedIn
""" ) gr.Markdown( """ """ ) if __name__ == "__main__": demo.launch(show_error=True, mcp_server=True, theme=THEME, css=CSS)