$ cat node-template.py

Image Remove Background

// Removes the background from an image using the RMBG-2.0 model via a native GPU service. Outputs a PNG with alpha channel (transparency).

Process
Image
template.py
1import os2import sys3import json4import subprocess5import time6import traceback78try:9    import requests10except ImportError:11    subprocess.check_call([sys.executable, "-m", "pip", "install", "requests"])12    import requests1314NATIVE_IMAGE_REMOVEBG_SERVICE_URL = os.getenv(15    "NATIVE_IMAGE_REMOVEBG_SERVICE_URL", "http://native-image-removebg-service:8103"16)17_EMBLEMA_VERSION = os.getenv("EMBLEMA_VERSION", "dev")18NATIVE_IMAGE_REMOVEBG_SERVICE_IMAGE = os.getenv(19    "NATIVE_IMAGE_REMOVEBG_SERVICE_IMAGE",20    f"emblema/native-image-removebg-service:{_EMBLEMA_VERSION}",21)22HF_CACHE_HOST_PATH = os.getenv("HF_CACHE_HOST_PATH", "/root/.cache/huggingface")23CONTAINER_NAME = "native-image-removebg-service"24INPUT_DIR = "/data/input"25OUTPUT_DIR = "/data/output"262728def start_container():29    """Create and start native-image-removebg-service, removing any stale container first."""30    subprocess.run(31        ["docker", "rm", "-f", CONTAINER_NAME],32        capture_output=True, text=True33    )3435    hf_token = os.getenv("HUGGINGFACE_TOKEN", "")36    print(f"Creating container {CONTAINER_NAME}...", file=sys.stderr)37    run_cmd = [38        "docker", "run", "-d",39        "--name", CONTAINER_NAME,40        "--network", "emblema",41        "--gpus", "all",42        "-e", "PORT=8103",43        "-e", "DEVICE=cuda",44        "-e", f"HF_TOKEN={hf_token}",45        "-v", f"{HF_CACHE_HOST_PATH}:/root/.cache/huggingface",46        NATIVE_IMAGE_REMOVEBG_SERVICE_IMAGE,47    ]48    result = subprocess.run(run_cmd, capture_output=True, text=True)49    if result.returncode != 0:50        print(f"docker run failed (exit {result.returncode}): {result.stderr}", file=sys.stderr)51        raise RuntimeError(f"Failed to start container: {result.stderr}")5253    # Poll health endpoint54    timeout = 18055    interval = 356    elapsed = 057    health_url = f"{NATIVE_IMAGE_REMOVEBG_SERVICE_URL}/health"58    while elapsed < timeout:59        try:60            r = requests.get(health_url, timeout=5)61            if r.status_code == 200:62                print(f"Container healthy (waited {elapsed}s).", file=sys.stderr)63                return64        except requests.ConnectionError:65            pass66        time.sleep(interval)67        elapsed += interval6869    raise RuntimeError(f"Container did not become healthy within {timeout}s")707172def stop_container():73    """Remove the container."""74    try:75        subprocess.run(76            ["docker", "rm", "-f", CONTAINER_NAME],77            capture_output=True, text=True, timeout=3078        )79        print(f"Container {CONTAINER_NAME} removed.", file=sys.stderr)80    except Exception as e:81        print(f"Warning: failed to remove container: {e}", file=sys.stderr)828384def main():85    try:86        input_json = sys.stdin.read()87        execution_input = json.loads(input_json)88        inputs = execution_input.get("inputs", {})8990        image = inputs.get("image", "")91        if not image:92            raise ValueError("Input image is required")9394        local_path = os.path.join(INPUT_DIR, image)95        if not os.path.exists(local_path):96            raise FileNotFoundError(f"Input image not found: {local_path}")9798        os.makedirs(OUTPUT_DIR, exist_ok=True)99100        # Start the container101        start_container()102103        try:104            # Send image to service105            with open(local_path, "rb") as f:106                resp = requests.post(107                    f"{NATIVE_IMAGE_REMOVEBG_SERVICE_URL}/remove-bg",108                    files={"image": (os.path.basename(local_path), f, "image/png")},109                    timeout=300,110                )111112            if resp.status_code != 200:113                try:114                    error_detail = resp.json()115                except Exception:116                    error_detail = resp.text117                raise RuntimeError(118                    f"Remove BG service returned {resp.status_code}: {error_detail}"119                )120121            # Save result122            out_filename = "removebg_result.png"123            out_path = os.path.join(OUTPUT_DIR, out_filename)124            with open(out_path, "wb") as f:125                f.write(resp.content)126127            inference_time = resp.headers.get("X-Inference-Time-Ms", "unknown")128            print(f"Background removed: time={inference_time}ms", file=sys.stderr)129130            output = {131                "image": out_filename,132            }133            print(json.dumps(output, indent=2))134135        finally:136            stop_container()137138    except Exception as e:139        error_output = {140            "error": str(e),141            "errorType": type(e).__name__,142            "traceback": traceback.format_exc(),143        }144        print(json.dumps(error_output), file=sys.stderr)145        sys.exit(1)146147148if __name__ == "__main__":149    main()