|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import gradio as gr |
|
import numpy as np |
|
import torch |
|
import torch.nn.functional as F |
|
from PIL import Image |
|
from huggingface_hub import hf_hub_download |
|
from torch.autograd import Variable |
|
from torchvision.transforms.functional import normalize |
|
from itertools import islice |
|
|
|
|
|
from models.isnet import ISNetDIS |
|
|
|
REPO_ID = "leonelhs/removators" |
|
|
|
device = 'cuda' if torch.cuda.is_available() else 'cpu' |
|
|
|
net = ISNetDIS() |
|
|
|
model_path = hf_hub_download(repo_id=REPO_ID, filename='isnet.pth') |
|
net.load_state_dict(torch.load(model_path, map_location=device)) |
|
net.to(device) |
|
net.eval() |
|
|
|
def im_preprocess(im, size): |
|
if len(im.shape) < 3: |
|
im = im[:, :, np.newaxis] |
|
if im.shape[2] == 1: |
|
im = np.repeat(im, 3, axis=2) |
|
if im.shape[2] == 4: |
|
im = im[:, :, :3] |
|
im_tensor = torch.tensor(im.copy(), dtype=torch.float32) |
|
im_tensor = torch.transpose(torch.transpose(im_tensor,1,2),0,1) |
|
if len(size)<2: |
|
return im_tensor, im.shape[0:2] |
|
else: |
|
im_tensor = torch.unsqueeze(im_tensor,0) |
|
im_tensor = F.interpolate(im_tensor, size, mode="bilinear") |
|
im_tensor = torch.squeeze(im_tensor,0) |
|
|
|
return im_tensor.type(torch.uint8), im.shape[0:2] |
|
|
|
|
|
def predict(image): |
|
""" |
|
Remove the background from an image. |
|
The function extracts the foreground and generates both a background-removed |
|
image and a binary mask. |
|
|
|
Parameters: |
|
image (string): File path to the input image. |
|
Returns: |
|
image (string): paths for image cutting mask. |
|
""" |
|
im_tensor, shapes = im_preprocess(image, [1024, 1024]) |
|
shapes = torch.from_numpy(np.array(shapes)).unsqueeze(0) |
|
|
|
im_tensor = torch.divide(im_tensor, 255.0) |
|
im_tensor = normalize(im_tensor, mean=[0.5, 0.5, 0.5], std=[1.0, 1.0, 1.0]).unsqueeze(0) |
|
im_tensor_v = Variable(im_tensor, requires_grad=False) |
|
ds_val = net(im_tensor_v)[0] |
|
prediction = ds_val[0][0, :, :, :] |
|
|
|
size = (shapes[0][0], shapes[0][1]) |
|
prediction = F.interpolate(torch.unsqueeze(prediction, 0), size, mode='bilinear') |
|
prediction = torch.squeeze(prediction) |
|
|
|
ma = torch.max(prediction) |
|
mi = torch.min(prediction) |
|
prediction = (prediction - mi) / (ma - mi) |
|
|
|
torch.cuda.empty_cache() |
|
return (prediction.detach().cpu().numpy() * 255).astype(np.uint8) |
|
|
|
def cuts(image): |
|
mask = predict(image) |
|
mask = Image.fromarray(mask).convert('L') |
|
cutted = Image.fromarray(image).convert("RGB") |
|
cutted.putalpha(mask) |
|
return [image, cutted], mask |
|
|
|
|
|
with gr.Blocks(title="DIS") as app: |
|
navbar = gr.Navbar(visible=True, main_page_name="Workspace") |
|
gr.Markdown("## Dichotomous Image Segmentation") |
|
with gr.Row(): |
|
with gr.Column(scale=1): |
|
inp_image = gr.Image(type="numpy", label="Upload Image") |
|
btn_predict = gr.Button(variant="primary", value="Remove background") |
|
with gr.Column(scale=2): |
|
with gr.Row(): |
|
preview = gr.ImageSlider(type="filepath", label="Comparer") |
|
|
|
btn_predict.click(cuts, inputs=[inp_image], outputs=[preview, inp_image]) |
|
|
|
with app.route("Readme", "/readme"): |
|
with open("README.md") as f: |
|
for line in islice(f, 12, None): |
|
gr.Markdown(line.strip()) |
|
|
|
|
|
app.launch(share=False, debug=True, show_error=True, mcp_server=True, pwa=True) |
|
app.queue() |
|
|