File size: 5,871 Bytes
5ee72d2 fe84436 5ee72d2 c2389fb 5ee72d2 ea232a6 5ee72d2 7d9e5d0 7e96cef 66c272f 7d9e5d0 8c14ebe 7d9e5d0 7e96cef 7d9e5d0 7e96cef 4f85e22 7e96cef 4f85e22 7e96cef 8c14ebe 7e96cef 4f85e22 7e96cef 39754cf 7e96cef 4f85e22 7e96cef 66c272f 4f85e22 ea232a6 7e96cef | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | # pyrefly: ignore [missing-import]
import gradio as gr
# pyrefly: ignore [missing-import]
import spaces
# pyrefly: ignore [missing-import]
import numpy as np
# pyrefly: ignore [missing-import]
from PIL import Image
from rembg import remove, new_session
import base64
import io
# ββ Cache model βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
_SESSIONS = {}
def get_session(model_name: str):
if model_name not in _SESSIONS:
print(f"[INFO] Sedang download/load model: {model_name} ...")
_SESSIONS[model_name] = new_session(model_name)
return _SESSIONS[model_name]
def process_image(img: Image.Image, model_name: str, alpha_matting: bool) -> Image.Image:
img = img.convert("RGB")
session = get_session(model_name)
kwargs = {}
if alpha_matting:
kwargs.update(
alpha_matting=True,
alpha_matting_foreground_threshold=240,
alpha_matting_background_threshold=10,
alpha_matting_erode_size=10,
)
return remove(img, session=session, **kwargs)
# ββ Handler untuk HuggingFace Web UI ββββββββββββββββββββββββββββββββββββββββββ
@spaces.GPU(duration=60)
def remove_bg_ui(img, model_name, alpha_matting):
if img is None:
return None
if not isinstance(img, Image.Image):
img = Image.fromarray(np.uint8(img))
return process_image(img, model_name, alpha_matting)
# ββ Handler untuk API Eksternal (Vercel / Next.js) ββββββββββββββββββββββββββββ
def process_api_image(img_data, model_name, alpha_matting):
"""
Helper untuk memproses base64 data URL atau objek {path: ...}.
Mengembalikan data:image/png;base64,... secara langsung tanpa perlu file upload terpisah.
"""
if not img_data:
return None
try:
if isinstance(img_data, str):
# Jika berupa data URL atau base64 murni
if "," in img_data:
img_data = img_data.split(",", 1)[1]
img_bytes = base64.b64decode(img_data)
pil_img = Image.open(io.BytesIO(img_bytes))
elif isinstance(img_data, dict) and "path" in img_data:
pil_img = Image.open(img_data["path"])
else:
return None
result_img = process_image(pil_img, model_name, alpha_matting)
# Encode hasil ke base64 PNG
buffered = io.BytesIO()
result_img.save(buffered, format="PNG")
b64_str = base64.b64encode(buffered.getvalue()).decode("utf-8")
return f"data:image/png;base64,{b64_str}"
except Exception as e:
print(f"[ERROR] API processing failed: {e}")
raise e
@spaces.GPU(duration=60)
def remove_bg_api(img_data, model_name, alpha_matting):
"""Endpoint API GPU untuk Vercel / Next.js (akselerasi ZeroGPU)."""
return process_api_image(img_data, model_name, alpha_matting)
def remove_bg_cpu_api(img_data, model_name, alpha_matting):
"""Endpoint API CPU fallback jika ZeroGPU quota tercapai atau sedang antre."""
return process_api_image(img_data, model_name, alpha_matting)
# ββ Gradio Blocks Interface βββββββββββββββββββββββββββββββββββββββββββββββββββ
with gr.Blocks(title="Background Remover AI") as demo:
gr.Markdown("# π AI Background Remover")
gr.Markdown("Hapus background gambar dengan presisi tinggi menggunakan ZeroGPU.")
# Tampilan UI untuk pengunjung HuggingFace Space
with gr.Row():
with gr.Column():
ui_input = gr.Image(type="pil", label="Upload Gambar")
ui_model = gr.Dropdown(
choices=[
"birefnet-portrait",
"birefnet-general",
"isnet-general-use",
"isnet-anime",
"u2net",
"u2net_human_seg",
],
value="birefnet-portrait",
label="Model AI",
)
ui_alpha = gr.Checkbox(value=False, label="Alpha Matting (haluskan edge rambut)")
ui_btn = gr.Button("Hapus Background", variant="primary")
with gr.Column():
ui_output = gr.Image(type="pil", label="Hasil (PNG Transparan)")
ui_btn.click(
fn=remove_bg_ui,
inputs=[ui_input, ui_model, ui_alpha],
outputs=ui_output,
)
# Komponen API untuk Vercel / endpoint /gradio_api/call/remove_bg (ZeroGPU)
with gr.Row(visible=False):
api_input = gr.Textbox(label="Image Base64")
api_model = gr.Textbox(value="birefnet-portrait", label="Model")
api_alpha = gr.Checkbox(value=False, label="Alpha Matting")
api_output = gr.Textbox(label="Result Base64")
api_btn = gr.Button("API Trigger")
api_btn.click(
fn=remove_bg_api,
inputs=[api_input, api_model, api_alpha],
outputs=api_output,
api_name="remove_bg",
)
# Komponen API CPU Fallback / endpoint /gradio_api/call/remove_bg_cpu (Bebas Quota ZeroGPU)
with gr.Row(visible=False):
cpu_input = gr.Textbox(label="Image Base64 CPU")
cpu_model = gr.Textbox(value="birefnet-portrait", label="Model CPU")
cpu_alpha = gr.Checkbox(value=False, label="Alpha Matting CPU")
cpu_output = gr.Textbox(label="Result Base64 CPU")
cpu_btn = gr.Button("API CPU Trigger")
cpu_btn.click(
fn=remove_bg_cpu_api,
inputs=[cpu_input, cpu_model, cpu_alpha],
outputs=cpu_output,
api_name="remove_bg_cpu",
)
if __name__ == "__main__":
demo.launch() |