Background Removal: Foreground Cutout
Atelico removes the background from an image entirely on-device, producing an RGBA PNG with a transparent background — useful for turning photos or generated art into game-ready sprites and cutouts. No external API is involved.
model value | Model | Params | License | Best for |
|---|---|---|---|---|
isnet | IS-Net (general) | 44M | Apache 2.0 | Photographic / general content (default) |
isnet-anime | IS-Net (anime) | 44M | Apache 2.0 | Stylized / anime artwork |
birefnet | BiRefNet (Swin-L) | 221M | MIT | Highest quality, slower |
Prefix with the backend as usual: in-memory::isnet. Unknown ids return a clear
error listing the supported models.
The flow: a base64-encoded source image goes in, a base64-encoded RGBA PNG (with
the background made transparent) comes out. Like image generation, every binding
exposes a non-blocking async variant (*_async) since segmentation takes a
moment on larger models.
Request fields
The request deserializes into a BackgroundRemovalRequest:
| Field | Type | Default | Description |
|---|---|---|---|
model | string | required | Model id, e.g. in-memory::isnet |
image | string | required | Source image as base64-encoded PNG or JPEG |
output | object | see below | What to return (RGBA image and/or mask) |
refinement | object | see below | Post-processing options for the alpha mask |
output controls which artifacts come back:
output field | Type | Default | Description |
|---|---|---|---|
rgba_image | bool | true | Return the RGBA cutout with transparent background |
mask | bool | false | Also return the alpha mask separately (grayscale PNG) |
refinement tunes the mask edges:
refinement field | Type | Default | Description |
|---|---|---|---|
smooth_radius | u32 | 0 | Gaussian blur radius for mask smoothing (0 = off) |
feather_width | u32 | 0 | Alpha feathering width in pixels (0 = sharp edges) |
threshold | f32 | 0.0 | Binarize soft edges, 0.0–1.0 (0 = keep soft) |
fill_holes | bool | true | Fill small holes inside the foreground mask |
min_region_size | u32 | 0 | Drop disconnected foreground blobs below this pixel count (0 = off) |
Response
The response is a BackgroundRemovalResponse. The image field holds the RGBA
cutout; mask is present only when output.mask was requested. Both are
b64_json PNG payloads carrying their own pixel dimensions:
{
"id": "...",
"created": 1234567890,
"model": "isnet",
"image": {"b64_json": "iVBORw0KGgo...", "width": 1024, "height": 1024},
"mask": null,
"stats": {
"preprocess_ms": 4.1,
"inference_ms": 38.0,
"postprocess_ms": 6.2,
"total_ms": 48.3
}
}
image.b64_json is a PNG with an alpha channel — the background pixels are
fully transparent.
The mask in a mask response is a grayscale PNG where white is foreground and
black is background. Request it (set output.mask to true) when you want to
composite the subject onto a new background yourself rather than using the
pre-cut RGBA image.
SDK usage (in-process)
Rust SDK
use atelico_sdk::{Engine, BackgroundRemovalRequest};
use base64::Engine as _;
let engine = Engine::new()?;
let src_b64 = base64::engine::general_purpose::STANDARD
.encode(std::fs::read("subject.png")?);
let request = BackgroundRemovalRequest {
model: "in-memory::isnet".into(),
image: src_b64,
..Default::default()
};
// Blocking
let response = engine.images().remove_background_sync(request)?;
let cutout = response.image.expect("rgba_image requested by default");
let png = base64::engine::general_purpose::STANDARD.decode(&cutout.b64_json)?;
std::fs::write("subject_cutout.png", &png)?;
For a game loop, engine.images().remove_background_async(request) returns a
[StreamHandle] you drive with poll() / next() / next_blocking().
Python
import base64, json
from atelico import Engine
engine = Engine()
src_b64 = base64.b64encode(open("subject.png", "rb").read()).decode()
resp = json.loads(engine.image_remove_background(json.dumps({
"model": "in-memory::isnet",
"image": src_b64,
})))
cutout = base64.b64decode(resp["image"]["b64_json"])
open("subject_cutout.png", "wb").write(cutout)
engine.image_remove_background_async(...) takes the same request JSON and
returns a JsonResultStream you poll for the final response.
C / FFI
// Blocking background removal
const char* request =
"{\"model\":\"in-memory::isnet\",\"image\":\"iVBORw0KGgo...\"}";
const char* response_json = NULL;
int rc = atelico_image_remove_background(engine, request, &response_json);
// response_json: {"id":..,"created":..,"model":"isnet",
// "image":{"b64_json":"iVBORw0KGgo...","width":1024,"height":1024},
// "mask":null,"stats":{...}}
// base64-decode image.b64_json to recover the RGBA PNG bytes.
atelico_image_remove_background_async takes the same request JSON and returns a
stream handle; drive it with the shared atelico_stream_poll /
atelico_stream_destroy loop (see the
C FFI getting started guide). The output pointer
is owned by the FFI layer's thread-local return buffer — copy it before the next
API call on the same thread.
Demo
demos/background-removal is a desktop app (also iOS-buildable) that lets you
load an image, pick a model (IS-Net general, IS-Net anime, or BiRefNet) and input
resolution, and preview the transparent cutout. It is the recommended starting
point before wiring foreground extraction into an asset pipeline.
See also
- Image Generation — text-to-image diffusion models
- Models — full supported-model catalogue