Du har en mapp med några hundra produktbilder, porträtt eller annonsbilder, och alla behöver få bakgrunden borttagen. Att göra det för hand i en bildredigerare är en dag av klickande. I Python är det en loop, och det verkliga valet är vad som körs i loopen: en open source-modell på din egen dator, eller ett HTTP-API.
Den här guiden bygger båda, med kompletta skript som du kan köra på en mapp redan i dag, och tar upp det som gör ett massjobb pålitligt: modellval, CPU eller GPU, omförsök, hastighetsgränser, idempotens och att fortsätta efter en krasch.
Alternativ A eller alternativ B?
| Lokal modell (rembg) | HTTP-API | |
|---|---|---|
| Kostnad | Gratis programvara; du betalar med hårdvara och tid | Per bild |
| Installation | Python 3.11 till 3.13, nedladdning av modeller, valfritt CUDA | En API-nyckel och requests |
| Hastighet | Beror på din CPU eller GPU och modellen | Beror på tjänsten, parallella anrop |
| Kvalitet | Beror på modellen du väljer | Beror på tjänsten |
| Integritet | Bilderna lämnar aldrig din dator | Bilderna laddas upp till en tredje part |
| Underhåll | Du sköter modeller, drivrutiner och licenser | Leverantören gör det |
| Bra för | Arbete offline, känsliga bilder, experiment | Produktionsflöden, servrar utan GPU |
Många team använder båda: en lokal modell för experiment och interna verktyg, ett API för produktion där förutsägbar kvalitet och inga GPU-servrar väger tyngre.
Alternativ A: rembg, open source-vägen
rembg är ett MIT-licensierat Python-bibliotek och CLI som paketerar flera modeller för bakgrundsborttagning och kör dem med ONNX Runtime. När detta skrivs är den aktuella versionen 2.0.86, och den kräver Python 3.11 eller senare och tidigare än 3.14.
Installera
Välj den backend som passar din hårdvara. CPU-versionen fungerar överallt:
python -m venv .venv && source .venv/bin/activate
pip install "rembg[cpu]" # library only
pip install "rembg[cpu,cli]" # library plus the rembg commandFör NVIDIA-GPU:er, installera rembg[gpu] i stället. Projektet påpekar att det kräver onnxruntime-gpu plus matchande CUDA och cuDNN, och föreslår att du faller tillbaka på CPU-versionen om du inte kan installera dem. AMD-GPU:er på Linux använder rembg[rocm] med onnxruntime-rocm.
rembg väljer automatiskt CUDA- (eller ROCm-) providern när ONNX Runtime rapporterar att den finns, och varnar om den faller tillbaka på CPU. Så kontrollerar du vad ONNX Runtime ser:
import onnxruntime
print(onnxruntime.get_available_providers()) # look for CUDAExecutionProviderVälj en modell
Modellerna laddas ner vid första användningen till ~/.rembg/models/ (ändra med REMBG_HOME). Några användbara från projektets lista:
| Modell | Kommentar |
|---|---|
bria-rmbg | Standard. BRIA:s RMBG-2.0, cirka 1,02 GB, körs i 1024 x 1024. Licensen kräver ett betalt avtal för kommersiell användning. |
birefnet-general | BiRefNet-modell för allmänt bruk; bra mjuka kanter |
birefnet-general-lite | Lättare BiRefNet för allmänt bruk |
birefnet-portrait | Anpassad för personer |
isnet-general-use | IS-Net-modell för allmänt bruk |
u2net | Den klassiska allmänna modellen; snabbare, grövre kanter |
u2netp | Lätt u2net; snabba tester på långsamma datorer |
silueta | Samma som u2net, krympt till 43 MB |
Två saker är viktigare än de ser ut. För det första: standardmodellen är inte gratis för kommersiell användning. Modellvikter har egna licenser, skilda från rembgs MIT-licens, så kontrollera källan för den modell du levererar med. För det andra ger de nyare modellerna (bria-rmbg, birefnet-*, isnet-general-use) mjuka, välformade kanter, medan den äldre u2net-familjen tenderar att ge fastare, grövre kanter.
Alternativ för kantkvalitet
rembg har tre sätt att hantera mjuka kantpixlar som hår och päls:
- Standard: bra för motiv med skarpa kanter som produkter, bilar och logotyper.
decontaminate=True(-dci CLI): tar bort den färgade gloria som den gamla bakgrunden lämnar i kantpixlarna. Det ändrar bara färgen, aldrig maskens form, kostar väldigt lite och kan vara på för en hel omgång.alpha_matting=True(-a): uppskattar själva kanten på nytt när maskens form är fel, till exempel avklippta hårstrån. Det är mycket långsammare och kan misslyckas, och då faller rembg tillbaka på en dekontaminerad friläggning.
För obevakade omgångar rekommenderar projektet -dc framför -a eftersom det är snabbare och inte kan misslyckas. Guiden om alfakanaler förklarar varför glorior uppstår.
Det snabba sättet: CLI
rembg p -m birefnet-general -dc photos/ cutouts/rembg p bearbetar en hel mapp; lägg till -w för att bevaka mappen och bearbeta nya filer när de dyker upp.
Python-skriptet
Den här versionen laddar modellen en gång, hoppar över filer som redan är klara så att du kan stoppa och starta om, och fortsätter när en fil misslyckas:
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:])Kör det med python batch_rembg.py photos cutouts birefnet-general. Att skapa sessionen en gång spelar roll: att ladda en modell tar mycket längre tid än att köra den, och rembgs README rekommenderar att sessionen återanvänds för bättre prestanda vid massbearbetning. Resultaten blir alltid PNG eftersom de har en alfakanal.
Där rembg inte räcker till
- Första körningen är långsam medan modellen laddas ner, och stora modeller kräver mycket RAM eller VRAM.
- Genomströmningen på CPU är blygsam med de högkvalitativa modellerna. Testa med 20 representativa bilder innan du satsar på tusen.
- Licenser och drivrutiner är ditt ansvar. Lås versionerna av rembg och modellerna så att en senare uppgradering inte ändrar resultaten i det tysta.
Alternativ B: ett HTTP-API
Med ett API görs det tunga arbetet på någon annans GPU:er, och ditt skript handlar mest om att hantera nätverket väl. Exemplet använder removebackground.devs API eftersom dess kontrakt är publicerat som OpenAPI 3.1 på /openapi.json; samma mönster gäller för alla liknande tjänster.
Kontraktet
POST https://removebackground.dev/v1/removemed din nyckel i headernx-api-key.- Skicka bilden som multipart-fältet
image_file(JPG, PNG eller WebP, upp till 25 MB), eller som JSON medimage_url. - Valfria fält är bland annat
format(png,jpgellerwebp),bg_color,size(preview,medium,hd,full) ochcrop. - 200 betyder att svaret är den färdiga bilden. 202 betyder att den fortfarande bearbetas efter cirka 55 sekunder: svaret är JSON med ett jobb-
id, och du frågarGET /v1/jobs/{id}/result, som svarar 409not_readymedRetry-Aftertills bilden är klar. Spara aldrig ett 202-svar som en bild. - Upp till 60 bearbetningsanrop per minut per konto; över det får du 429
rate_limitedmedRetry-After. - En header
Idempotency-Keygör omförsök säkra: samma nyckel med samma anrop returnerar det ursprungliga jobbet i stället för att debitera igen. Samma nyckel med ett annat anrop ger 409idempotency_key_reused. - Resultaten raderas efter 48 timmar, så spara dem när du får dem.
Regler för omförsök så att du inte betalar två gånger
| Svar | Vad du ska göra |
|---|---|
| 200 | Spara bilden |
| 202 | Fråga efter jobbets resultat; ladda inte upp igen |
| 400, 401, 402, 413, 422 | Rätta anropet, nyckeln, krediterna eller bilden; loopa inte |
| 429 | Vänta Retry-After sekunder, skicka igen med samma nyckel |
| 500, 503, timeout, bruten anslutning | Vänta och skicka igen med samma nyckel |
| 502 | Den bilden misslyckades och debiterades inte; logga den |
Tricket är att göra idempotensnyckeln deterministisk: en hash av bildens byte plus alternativen. Om skriptet kraschar och du kör det igen har varje nytt anrop samma nyckel, så inget bearbetas eller debiteras två gånger.
Python-skriptet
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])Kör det med REMOVEBG_API_KEY=... python batch_api.py photos cutouts. Fyra workers är en försiktig början; om snabba svar tar dig över minutgränsen väntar hanteringen av 429 och skickar igen med samma nyckel. För att skicka URL:er i stället för filer, skicka JSON:
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),
)För långa listor med URL:er har samma API POST /v1/batch, som köar upp till 100 bild-URL:er som ett jobb som du frågar efter.
Gör alla massjobb robusta
- Hoppa över färdiga resultat så att en ny körning fortsätter i stället för att börja om. Båda skripten gör det.
- Se upp för namnkrockar.
shoe.jpgochshoe.pngi samma mapp blir bådashoe.png; byt namn på indata eller ta med den ursprungliga filändelsen i utdatanamnet. - Logga misslyckanden till en fil och kör bara om dem.
- Stickprova ett urval i 100 % zoom på mörka och ljusa bakgrunder innan du bearbetar allt.
- Låt originalen vara orörda. Skriv till en separat utdatamapp.
- Välj utdataformat efter destinationen. PNG eller WebP för transparens, JPG på vitt för marknadsplatser. Se PNG, JPEG eller WebP.
Frågor
Är rembg gratis för kommersiell användning?
rembg i sig är MIT-licensierat, men varje modell har en egen licens. Standardmodellen, BRIA:s RMBG-2.0 (bria-rmbg), kräver ett betalt avtal för kommersiell användning, så kontrollera licensen för modellen du använder eller välj en annan.
Använder rembg min GPU automatiskt?
Ja, om du installerar rembg[gpu] och ONNX Runtime kan ladda CUDA-providern (vilket kräver matchande CUDA och cuDNN). rembg använder CUDA eller ROCm när de finns och varnar när den faller tillbaka på CPU:n. Kontrollera onnxruntime.get_available_providers().
Vilken rembg-modell ger bäst kvalitet?
De nyare modellerna, bria-rmbg (standard), birefnet-familjen och isnet-general-use, ger mjukare och bättre formade kanter än den äldre u2net-familjen. birefnet-portrait är en bra start för personer. Testa ett urval av dina egna bilder, eftersom resultaten varierar med motivet.
Hur undviker jag att debiteras två gånger när jag gör om API-anrop?
Skicka en header Idempotency-Key och återanvänd den vid varje omförsök för samma bild. Härleder du den från en hash av bildens byte och alternativen återanvänder till och med en ny körning av hela skriptet samma nycklar.
Vad ska mitt skript göra med ett 202-svar?
Behandla det som att bilden fortfarande bearbetas, inte som en bild. Läs jobbets id från JSON-svaret och fråga GET /v1/jobs/{id}/result, och vänta Retry-After varje gång det svarar 409 not_ready. Ladda inte upp bilden igen.
Hur snabbt kan jag skicka anrop till removebackground.devs API?
Upp till 60 bearbetningsanrop per minut per konto. Över det svarar API:t 429 rate_limited med en header Retry-After. För många URL:er tar POST /v1/batch emot upp till 100 per anrop.
Prova med din egen bild
Nya konton får 50 gratis krediter. En kredit per bild, ingen prenumeration, och krediterna går aldrig ut.
Ta bort en bakgrundKällor
- rembg on GitHub (README: installation, models, edge modes)
- rembg on PyPI (version and Python requirement)
- BRIA RMBG-2.0 model card and license
- ONNX Runtime: Get started and installation matrix
- removebackground.dev API reference and guides
- removebackground.dev OpenAPI 3.1 schema
- Requests: Quickstart (multipart file uploads, timeouts)