Python ile toplu arka plan kaldırma: rembg mi, API mi?

Bütün bir klasördeki görsellerin arka planını kaldırmak için iki eksiksiz betik: biri kendi donanımınızda açık kaynak rembg kütüphanesiyle, diğeri yeniden denemeleri, hız sınırlarını ve mükerrer ücretlendirmeyi doğru yöneten bir HTTP API ile.

Güncelleme: 23 Ekim 2026 · 8 dk okuma

Adımları atlayın: arka planı tek tıkla kaldırın. Görsel yükleyin

Elinizde birkaç yüz ürün fotoğrafı, vesikalık ya da ilan görseli olan bir klasör var ve hepsinde arka plan kaldırma gerekiyor. Bunu bir düzenleyicide elle yapmak bütün gününüzü tıklamakla geçirmek demek. Python'da ise bu bir döngüden ibaret; asıl karar döngünün içinde ne çalışacağı: kendi makinenizde açık kaynak bir model mi, yoksa bir HTTP API mi?

Bu rehber ikisini de kuruyor. Bugün bir klasör üzerinde çalıştırabileceğiniz eksiksiz betikler sunuyor ve toplu bir işi güvenilir kılan kısımları ele alıyor: model seçimi, CPU ve GPU, yeniden denemeler, hız sınırları, idempotency ve bir çökmeden sonra kaldığı yerden devam etme.

A seçeneği mi, B seçeneği mi?

Yerel model (rembg)HTTP API
MaliyetYazılım ücretsiz; bedeli donanım ve zamanla ödersinizGörsel başına
KurulumPython 3.11 ile 3.13 arası, model indirmeleri, isteğe bağlı CUDABir API anahtarı ve requests
HızCPU'nuza ya da GPU'nuza ve modele bağlıServise ve paralel isteklere bağlı
KaliteSeçtiğiniz modele bağlıServise bağlı
GizlilikGörseller makinenizden hiç çıkmazGörseller üçüncü bir tarafa yüklenir
BakımModelleri, sürücüleri ve lisansları siz yönetirsinizSağlayıcı yönetir
Uygun olduğu işlerÇevrimdışı çalışma, hassas görseller, denemelerÜretim ortamındaki iş akışları, GPU'suz sunucular

Birçok ekip ikisini birlikte kullanır: denemeler ve iç araçlar için yerel bir model, öngörülebilir kalitenin ve GPU sunucusu yönetmemenin daha önemli olduğu üretim ortamı için bir API.

A seçeneği: rembg, açık kaynak yol

rembg, birkaç arka plan kaldırma modelini bir araya getiren ve bunları ONNX Runtime ile çalıştıran, MIT lisanslı bir Python kütüphanesi ve komut satırı aracıdır. Bu yazı hazırlanırken güncel sürüm 2.0.86 ve Python 3.11 ya da daha yenisini, 3.14'ten eskisini gerektiriyor.

Kurulum

Donanımınıza uyan arka ucu seçin. CPU sürümü her yerde çalışır:

python -m venv .venv && source .venv/bin/activate
pip install "rembg[cpu]"        # library only
pip install "rembg[cpu,cli]"    # library plus the rembg command

NVIDIA GPU'lar için bunun yerine rembg[gpu] kurun. Proje, bunun için onnxruntime-gpu ile uyumlu bir CUDA ve cuDNN gerektiğini belirtiyor ve bunları kuramıyorsanız CPU sürümüne dönmenizi öneriyor. Linux'taki AMD GPU'lar onnxruntime-rocm ile birlikte rembg[rocm] kullanır.

rembg, ONNX Runtime CUDA (ya da ROCm) yürütme sağlayıcısını kullanılabilir gösterdiğinde onu otomatik olarak seçer ve CPU'ya düşerse uyarır. ONNX Runtime'ın neyi gördüğünü kontrol etmek için:

import onnxruntime
print(onnxruntime.get_available_providers())  # look for CUDAExecutionProvider

Model seçimi

Modeller ilk kullanımda ~/.rembg/models/ klasörüne iner (değiştirmek için REMBG_HOME değişkenini ayarlayın). Projenin listesinden işe yarayan bazıları:

ModelNotlar
bria-rmbgVarsayılan. BRIA'nın RMBG-2.0 modeli, yaklaşık 1,02 GB, 1024 x 1024 çözünürlükte çalışır. Lisansı ticari kullanım için ücretli bir anlaşma gerektirir.
birefnet-generalGenel amaçlı BiRefNet modeli; yumuşak kenarlarda başarılı
birefnet-general-liteGenel kullanım için daha hafif BiRefNet
birefnet-portraitİnsanlar için ayarlanmış
isnet-general-useGenel amaçlı IS-Net modeli
u2netKlasik genel model; daha hızlı, kenarları daha kaba
u2netpHafif u2net; yavaş makinelerde hızlı testler için
siluetau2net ile aynı, 43 MB'a küçültülmüş

İki nokta göründüğünden daha önemli. Birincisi, varsayılan model ticari kullanım için ücretsiz değildir: model ağırlıklarının rembg'nin MIT lisansından ayrı kendi lisansları vardır, bu yüzden ürününüzde kullandığınız modelin kaynağını kontrol edin. İkincisi, yeni modeller (bria-rmbg, birefnet-*, isnet-general-use) yumuşak ve düzgün şekilli kenarlar üretirken eski u2net ailesi daha sert ve kaba kenarlar verme eğilimindedir.

Kenar kalitesi seçenekleri

rembg, saç ve tüy gibi yumuşak kenar piksellerini işlemek için üç yol sunar:

  • Varsayılan: ürünler, arabalar ve logolar gibi keskin kenarlı nesneler için yeterlidir.
  • decontaminate=True (komut satırında -dc): eski arka planın kenar piksellerinde bıraktığı renkli haleyi temizler. Maskenin şeklini asla değiştirmez, yalnızca rengi değiştirir, çok az maliyetlidir ve bütün bir toplu iş boyunca açık bırakmak güvenlidir.
  • alpha_matting=True (-a): maske şekli yanlış olduğunda, örneğin saç telleri kesildiğinde, kenarın kendisini yeniden hesaplar. Çok daha yavaştır ve yakınsamayabilir; bu durumda rembg renk temizliği yapılmış bir kesime geri döner.

Gözetimsiz toplu işler için proje, daha hızlı olduğu ve başarısız olamayacağı için -a yerine -dc öneriyor. Alfa kanalı rehberi halelerin neden oluştuğunu anlatıyor.

Hızlı yol: komut satırı

rembg p -m birefnet-general -dc photos/ cutouts/

rembg p bütün bir klasörü işler; klasörü izleyip yeni dosyaları geldikçe işlemek için -w ekleyin.

Python betiği

Bu sürüm modeli bir kez yükler, durdurup yeniden başlatabilmeniz için tamamlanmış dosyaları atlar ve bir dosya hata verdiğinde çalışmaya devam eder:

import sys
from pathlib import Path

from rembg import new_session, remove

EXTS = {".jpg", ".jpeg", ".png", ".webp"}


def main(in_dir: str, out_dir: str, model: str = "birefnet-general") -> None:
    src_dir, dst_dir = Path(in_dir), Path(out_dir)
    dst_dir.mkdir(parents=True, exist_ok=True)
    session = new_session(model)  # load the model once, reuse it for every image

    files = sorted(p for p in src_dir.iterdir() if p.suffix.lower() in EXTS)
    for i, src in enumerate(files, 1):
        dst = dst_dir / f"{src.stem}.png"
        if dst.exists():
            continue  # resume where a previous run stopped
        try:
            out = remove(src.read_bytes(), session=session, decontaminate=True)
            dst.write_bytes(out)
            print(f"[{i}/{len(files)}] ok      {src.name}")
        except Exception as e:  # one bad file shouldn't stop the batch
            print(f"[{i}/{len(files)}] failed  {src.name}: {e}")


if __name__ == "__main__":
    main(*sys.argv[1:])

python batch_rembg.py photos cutouts birefnet-general komutuyla çalıştırın. Oturumu bir kez oluşturmak önemlidir: bir modeli yüklemek onu çalıştırmaktan çok daha uzun sürer ve rembg README dosyası toplu iş performansı için oturumun yeniden kullanılmasını öneriyor. Sonuçta bir alfa kanalı olduğu için çıktılar her zaman PNG'dir.

rembg'nin yetersiz kaldığı yerler

  • İlk çalıştırma yavaştır, çünkü model indirilir; büyük modeller de çok fazla RAM ya da VRAM ister.
  • Yüksek kaliteli modellerle CPU hızı mütevazıdır. Bin görsele girişmeden önce temsil edici 20 görselle test edin.
  • Lisanslar ve sürücüler sizin sorumluluğunuzdadır. Sonraki bir güncelleme sonuçları sessizce değiştirmesin diye rembg ve model sürümlerinizi sabitleyin.

B seçeneği: bir HTTP API

API ile ağır iş başkasının GPU'larında yapılır ve betiğiniz büyük ölçüde ağı iyi yönetmekle ilgilenir. Örnek, sözleşmesi /openapi.json adresinde OpenAPI 3.1 olarak yayımlandığı için removebackground.dev API'sini kullanıyor; aynı kalıplar benzer her servis için geçerlidir.

Sözleşme

  • Anahtarınız x-api-key başlığında olacak şekilde POST https://removebackground.dev/v1/remove.
  • Görseli image_file adlı multipart alanında (JPG, PNG ya da WebP, en fazla 25 MB) ya da image_url içeren JSON olarak gönderin.
  • İsteğe bağlı alanlar arasında format (png, jpg ya da webp), bg_color, size (preview, medium, hd, full) ve crop bulunur.
  • 200, gövdenin bitmiş görsel olduğu anlamına gelir. 202, yaklaşık 55 saniye sonra hâlâ işlendiği anlamına gelir: gövde bir iş id değeri içeren JSON'dur ve GET /v1/jobs/{id}/result adresini yoklarsınız; bu adres görsel hazır olana kadar Retry-After ile 409 not_ready yanıtı verir. 202 gövdesini asla görsel olarak kaydetmeyin.
  • Hesap başına dakikada en fazla 60 işleme isteği; bunun üzerinde Retry-After ile 429 rate_limited yanıtı alırsınız.
  • Idempotency-Key başlığı yeniden denemeleri güvenli kılar: aynı anahtar ve aynı istek, yeniden ücret almak yerine ilk işi döndürür. Aynı anahtar farklı bir istekle gelirse 409 idempotency_key_reused yanıtı verilir.
  • Sonuçlar 48 saat sonra silinir, bu yüzden aldığınızda kaydedin.

İki kez ödemenizi önleyen yeniden deneme kuralları

YanıtNe yapmalı
200Görseli kaydedin
202İş sonucunu yoklayın; yeniden yüklemeyin
400, 401, 402, 413, 422İsteği, anahtarı, krediyi ya da görseli düzeltin; döngüye sokmayın
429Retry-After kadar saniye bekleyin, aynı anahtarla yeniden gönderin
500, 503, zaman aşımı, kopan bağlantıBekleme süresini artırarak aynı anahtarla yeniden gönderin
502O görsel başarısız oldu ve ücretlendirilmedi; kaydını tutun

İşin püf noktası idempotency anahtarını deterministik yapmaktır: görsel baytlarının ve seçeneklerin bir hash değeri. Betik çöker ve yeniden çalıştırırsanız her yeniden gönderim aynı anahtarı taşır, böylece hiçbir şey iki kez işlenmez ya da ücretlendirilmez.

Python betiği

import hashlib
import mimetypes
import os
import sys
import time
from concurrent.futures import ThreadPoolExecutor, as_completed
from pathlib import Path

import requests

API = os.environ.get("REMOVEBG_API", "https://removebackground.dev")
KEY = os.environ["REMOVEBG_API_KEY"]  # keep the key out of your code
OPTIONS = {"format": "png", "size": "full"}  # or {"format": "jpg", "bg_color": "ffffff"}
WORKERS = 4  # the API allows 60 processing requests a minute
EXTS = {".jpg", ".jpeg", ".png", ".webp"}
RETRYABLE = {429, 500, 503}


def idempotency_key(data: bytes) -> str:
    # Same image + same options = same key, so a rerun never pays twice.
    h = hashlib.sha256(data)
    h.update(repr(sorted(OPTIONS.items())).encode())
    return h.hexdigest()


def wait(res, default=2.0):
    try:
        return float(res.headers.get("Retry-After", default))
    except ValueError:
        return default


def save(res, dst: Path) -> Path:
    if res.status_code != 200 or not res.headers.get("Content-Type", "").startswith("image/"):
        raise RuntimeError(f"HTTP {res.status_code}: {res.text[:300]}")
    dst.write_bytes(res.content)
    return dst


def process(src: Path, dst: Path) -> Path:
    data = src.read_bytes()
    mime = mimetypes.guess_type(src.name)[0] or "application/octet-stream"
    headers = {"x-api-key": KEY, "Idempotency-Key": idempotency_key(data)}

    for attempt in range(6):
        try:
            res = requests.post(
                f"{API}/v1/remove",
                files={"image_file": (src.name, data, mime)},
                data=OPTIONS,
                headers=headers,
                timeout=(10, 120),
            )
        except (requests.ConnectionError, requests.Timeout):
            time.sleep(2 ** attempt)  # same key: safe to resend
            continue
        if res.status_code in RETRYABLE:
            time.sleep(wait(res, 2 ** attempt))
            continue
        break
    else:
        raise RuntimeError("gave up after retries")

    if res.status_code != 202:
        return save(res, dst)  # 200 is the image; 4xx and 502 raise

    # 202: still processing. Poll the same job; never upload the image again.
    job_id = res.json()["id"]
    deadline = time.monotonic() + 600
    while time.monotonic() < deadline:
        time.sleep(wait(res))
        try:
            res = requests.get(f"{API}/v1/jobs/{job_id}/result", headers=headers, timeout=30)
        except (requests.ConnectionError, requests.Timeout):
            continue  # reading a job is free and safe to repeat
        if res.status_code == 409 and res.json()["error"]["code"] == "not_ready":
            continue
        if res.status_code >= 500:
            continue
        return save(res, dst)
    raise TimeoutError(f"job {job_id} still running; fetch it later")


def main(in_dir: str, out_dir: str) -> None:
    src_dir, dst_dir = Path(in_dir), Path(out_dir)
    dst_dir.mkdir(parents=True, exist_ok=True)
    ext = ".jpg" if OPTIONS.get("format") == "jpg" else "." + OPTIONS.get("format", "png")
    todo = [
        (p, dst_dir / (p.stem + ext))
        for p in sorted(src_dir.iterdir())
        if p.suffix.lower() in EXTS and not (dst_dir / (p.stem + ext)).exists()
    ]
    print(f"{len(todo)} images to process")

    failed = []
    with ThreadPoolExecutor(max_workers=WORKERS) as pool:
        jobs = {pool.submit(process, s, d): s for s, d in todo}
        for fut in as_completed(jobs):
            src = jobs[fut]
            try:
                print("ok    ", src.name, "->", fut.result().name)
            except Exception as e:
                failed.append(src.name)
                print("failed", src.name, e)
    print(f"done: {len(todo) - len(failed)} ok, {len(failed)} failed")


if __name__ == "__main__":
    main(sys.argv[1], sys.argv[2])

REMOVEBG_API_KEY=... python batch_api.py photos cutouts komutuyla çalıştırın. Dört işçi temkinli bir başlangıçtır; hızlı yanıtlar sizi dakikalık sınırın üzerine çıkarırsa 429 yönetimi bekler ve aynı anahtarla yeniden gönderir. Dosya yerine URL göndermek için JSON gönderin:

res = requests.post(
    f"{API}/v1/remove",
    json={"image_url": "https://example.com/shoe.jpg", "format": "png"},
    headers={"x-api-key": KEY, "Idempotency-Key": "shoe-front-v1"},
    timeout=(10, 120),
)

Uzun URL listeleri için aynı API'de, en fazla 100 görsel URL'sini yokladığınız tek bir iş olarak sıraya alan POST /v1/batch uç noktası var.

Her toplu işi sağlamlaştırmak

  • Tamamlanmış çıktıları atlayın, böylece yeniden çalıştırma baştan başlamak yerine kaldığı yerden devam eder. İki betik de bunu yapıyor.
  • İsim çakışmalarına dikkat edin. Aynı klasördeki shoe.jpg ve shoe.png dosyalarının ikisi de shoe.png olur; girdileri yeniden adlandırın ya da özgün uzantıyı çıktı adına ekleyin.
  • Hataları bir dosyaya kaydedin ve yalnızca onları yeniden çalıştırın.
  • Her şeyi işlemeden önce bir örneği koyu ve açık arka planlarda %100 yakınlaştırmayla kontrol edin.
  • Orijinallere dokunmayın. Ayrı bir çıktı klasörüne yazın.
  • Çıktı biçimini hedefe göre seçin. Şeffaflık için PNG ya da WebP, pazaryerleri için beyaz üzerine JPG. Bkz. PNG, JPEG ve WebP karşılaştırması.

Sorular

rembg ticari kullanım için ücretsiz mi?

rembg'nin kendisi MIT lisanslıdır, ancak her modelin kendi lisansı vardır. Varsayılan model olan BRIA'nın RMBG-2.0'ı (bria-rmbg) ticari kullanım için ücretli bir anlaşma gerektirir; bu yüzden kullandığınız modelin lisansını kontrol edin ya da başka bir model seçin.

rembg GPU'mu otomatik olarak kullanır mı?

Evet, rembg[gpu] kurarsanız ve ONNX Runtime CUDA sağlayıcısını yükleyebilirse (bunun için uyumlu CUDA ve cuDNN gerekir). rembg, varsa CUDA ya da ROCm kullanır ve CPU'ya düştüğünde uyarır. onnxruntime.get_available_providers() ile kontrol edin.

En iyi kaliteyi hangi rembg modeli verir?

Yeni modeller, yani bria-rmbg (varsayılan), birefnet ailesi ve isnet-general-use, eski u2net ailesine göre daha yumuşak ve daha düzgün şekilli kenarlar üretir. İnsanlar için birefnet-portrait iyi bir başlangıçtır. Sonuçlar nesneye göre değiştiği için kendi görsellerinizden bir örnekle test edin.

API çağrılarını yeniden denerken iki kez ücretlendirilmekten nasıl kaçınırım?

Bir Idempotency-Key başlığı gönderin ve aynı görselin her yeniden denemesinde onu tekrar kullanın. Anahtarı görsel baytlarının ve seçeneklerin hash değerinden türetirseniz, betiğin tamamını yeniden çalıştırdığınızda bile aynı anahtarlar kullanılır.

Betiğim 202 yanıtıyla ne yapmalı?

Bunu bir görsel olarak değil, hâlâ işleniyor olarak değerlendirin. JSON gövdesinden iş id değerini okuyun ve GET /v1/jobs/{id}/result adresini yoklayın; 409 not_ready yanıtı geldiğinde her seferinde Retry-After kadar bekleyin. Görseli yeniden yüklemeyin.

removebackground.dev API'sine ne kadar hızlı istek gönderebilirim?

Hesap başına dakikada en fazla 60 işleme isteği. Bunun üzerinde API, Retry-After başlığıyla 429 rate_limited yanıtı verir. Çok sayıda URL için POST /v1/batch istek başına en fazla 100 URL kabul eder.

Kendi görselinizde deneyin

Yeni hesaplara 50 ücretsiz kredi verilir. Görsel başına bir kredi, abonelik yok ve kredilerin süresi hiç dolmaz.

Arka plan kaldırın

Kaynaklar