From 93dd37017c32787a94aff17526c5ce1ee7b99f36 Mon Sep 17 00:00:00 2001 From: Siddharth Kumar Sah Date: Sun, 12 Apr 2026 18:09:59 +0800 Subject: [PATCH] feat: add Ultra quality mode with BiRefNet-matting for people photos Adds a new "Ultra" quality tier for People subject type that uses BiRefNet-matting (ONNX, 928MB) for true alpha matting instead of binary segmentation. Produces per-pixel transparency for hair wisps and fine edges that standard models miss. - Custom rembg session class loads BiRefNet-matting ONNX from GitHub releases - Zero new Python dependencies (reuses existing onnxruntime) - Model pre-downloaded in Docker build alongside existing models - Ultra option only visible when subject is People - Falls back to Best when switching to Products/General --- .../components/tools/remove-bg-settings.tsx | 33 +++++++++++++---- docker/download_models.py | 30 +++++++++++++++ packages/ai/python/remove_bg.py | 37 +++++++++++++++++++ tests/e2e/remove-bg.spec.ts | 27 ++++++++++++++ 4 files changed, 119 insertions(+), 8 deletions(-) diff --git a/apps/web/src/components/tools/remove-bg-settings.tsx b/apps/web/src/components/tools/remove-bg-settings.tsx index a6a7a6e6..012654ac 100644 --- a/apps/web/src/components/tools/remove-bg-settings.tsx +++ b/apps/web/src/components/tools/remove-bg-settings.tsx @@ -13,18 +13,24 @@ import { useToolProcessor } from "@/hooks/use-tool-processor"; import { useFileStore } from "@/stores/file-store"; type SubjectType = "people" | "products" | "general"; -type Quality = "fast" | "balanced" | "best"; +type Quality = "fast" | "balanced" | "best" | "ultra"; type BackgroundType = "transparent" | "color" | "gradient" | "image"; type BgModel = | "birefnet-general" | "birefnet-general-lite" + | "birefnet-matting" | "birefnet-portrait" | "bria-rmbg" | "u2net"; -const MODEL_MAP: Record> = { - people: { fast: "u2net", balanced: "birefnet-portrait", best: "birefnet-portrait" }, +const MODEL_MAP: Record>> = { + people: { + fast: "u2net", + balanced: "birefnet-portrait", + best: "birefnet-portrait", + ultra: "birefnet-matting", + }, products: { fast: "u2net", balanced: "bria-rmbg", best: "birefnet-general" }, general: { fast: "u2net", balanced: "birefnet-general-lite", best: "birefnet-general" }, }; @@ -35,10 +41,11 @@ const SUBJECT_OPTIONS: { value: SubjectType; label: string; icon: typeof User }[ { value: "general", label: "General", icon: ImageIcon }, ]; -const QUALITY_OPTIONS: { value: Quality; label: string }[] = [ +const ALL_QUALITY_OPTIONS: { value: Quality; label: string; peopleOnly?: boolean }[] = [ { value: "fast", label: "Fast" }, { value: "balanced", label: "Balanced" }, { value: "best", label: "Best" }, + { value: "ultra", label: "Ultra", peopleOnly: true }, ]; const COLOR_PRESETS = [ @@ -97,8 +104,18 @@ export function RemoveBgControls({ settings, onChange }: RemoveBgControlsProps) // Expandable sections const [effectsOpen, setEffectsOpen] = useState(false); + // Filter quality options based on subject (Ultra only for People) + const qualityOptions = ALL_QUALITY_OPTIONS.filter( + (opt) => !opt.peopleOnly || subject === "people", + ); + + // If switching away from People while on Ultra, fall back to Best + const effectiveQuality = quality === "ultra" && subject !== "people" ? "best" : quality; + const model = - isPassport && subject === "people" ? "birefnet-portrait" : MODEL_MAP[subject][quality]; + isPassport && subject === "people" + ? "birefnet-portrait" + : MODEL_MAP[subject][effectiveQuality] || "birefnet-general"; const onChangeRef = useRef(onChange); useEffect(() => { @@ -190,14 +207,14 @@ export function RemoveBgControls({ settings, onChange }: RemoveBgControlsProps) {/* Quality */} Quality -
- {QUALITY_OPTIONS.map((opt) => ( +
3 ? "grid-cols-4" : "grid-cols-3"}`}> + {qualityOptions.map((opt) => (