LI Junxing commited on
Commit
ec737d7
·
0 Parent(s):

Initial RankSEG demo import

Browse files
.gitattributes ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tar filter=lfs diff=lfs merge=lfs -text
29
+ *.tflite filter=lfs diff=lfs merge=lfs -text
30
+ *.tgz filter=lfs diff=lfs merge=lfs -text
31
+ *.wasm filter=lfs diff=lfs merge=lfs -text
32
+ *.xz filter=lfs diff=lfs merge=lfs -text
33
+ *.zip filter=lfs diff=lfs merge=lfs -text
34
+ *.zst filter=lfs diff=lfs merge=lfs -text
35
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ *.jpg filter=lfs diff=lfs merge=lfs -text
.gitignore ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ flagged/
2
+
3
+ __pycache__/
4
+
5
+ .DS_Store
README.md ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: BiRefNet Demo
3
+ emoji: 👁
4
+ colorFrom: purple
5
+ colorTo: green
6
+ sdk: gradio
7
+ python_version: 3.12.12
8
+ sdk_version: 5.35.0
9
+ app_file: app.py
10
+ pinned: false
11
+ license: mit
12
+ models:
13
+ - ZhengPeng7/BiRefNet
14
+ - ZhengPeng7/BiRefNet_HR
15
+ - ZhengPeng7/BiRefNet_HR-matting
16
+ - ZhengPeng7/BiRefNet-matting
17
+ - ZhengPeng7/BiRefNet-portrait
18
+ - ZhengPeng7/BiRefNet_lite
19
+ preload_from_hub:
20
+ - ZhengPeng7/BiRefNet
21
+ - ZhengPeng7/BiRefNet_HR
22
+ - ZhengPeng7/BiRefNet_HR-matting
23
+ - ZhengPeng7/BiRefNet-matting
24
+ - ZhengPeng7/BiRefNet-portrait
25
+ - ZhengPeng7/BiRefNet_lite
26
+ ---
27
+
28
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
app.py ADDED
@@ -0,0 +1,414 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import cv2
3
+ import numpy as np
4
+ import torch
5
+ import gradio as gr
6
+ import spaces
7
+
8
+ from glob import glob
9
+ from typing import Tuple
10
+
11
+ from PIL import Image
12
+ import torch
13
+ from torchvision import transforms
14
+
15
+ import requests
16
+ from io import BytesIO
17
+ import zipfile
18
+
19
+ # Fix the HF space permission error -- redirect ALL HF cache to a writable location
20
+ os.environ["HF_HOME"] = "/tmp/hf_cache"
21
+ os.environ["HF_MODULES_CACHE"] = os.path.join("/tmp/hf_cache", "modules")
22
+
23
+ import transformers
24
+ from rankseg import RankSEG
25
+
26
+
27
+ torch.set_float32_matmul_precision('high')
28
+ torch.jit.script = lambda f: f
29
+
30
+ device = "cuda" if torch.cuda.is_available() else "cpu"
31
+ RANKSEG_METRICS = ["dice", "iou"]
32
+
33
+
34
+ def rgba2rgb(img):
35
+ """
36
+ Convert RGBA image to RGB with white background.
37
+ Supports both PIL.Image and numpy.ndarray.
38
+ """
39
+
40
+ # 1. Handle PIL Image
41
+ if isinstance(img, Image.Image):
42
+ img = img.convert("RGBA")
43
+ bg = Image.new("RGBA", img.size, (255, 255, 255))
44
+ return Image.alpha_composite(bg, img).convert("RGB")
45
+
46
+ # 2. Handle Numpy Array (OpenCV)
47
+ elif isinstance(img, np.ndarray):
48
+ # Grayscale to RGB
49
+ if img.ndim == 2:
50
+ return np.stack([img] * 3, axis=-1)
51
+
52
+ # Already 3 channels
53
+ if img.shape[2] == 3:
54
+ return img
55
+
56
+ # RGBA to RGB (blending with white)
57
+ elif img.shape[2] == 4:
58
+ # Normalize alpha to 0-1 and keep shape (H, W, 1)
59
+ alpha = img[..., 3:4].astype(float) / 255.0
60
+ foreground = img[..., :3].astype(float)
61
+ background = 255.0
62
+
63
+ # Blend formula: source * alpha + bg * (1 - alpha)
64
+ out = foreground * alpha + background * (1.0 - alpha)
65
+
66
+ return out.clip(0, 255).astype(np.uint8)
67
+
68
+ else:
69
+ raise TypeError(f"Unsupported type: {type(img)}")
70
+
71
+
72
+ ## CPU version refinement
73
+ def FB_blur_fusion_foreground_estimator_cpu(image, FG, B, alpha, r=90):
74
+ if isinstance(image, Image.Image):
75
+ image = np.array(image) / 255.0
76
+ blurred_alpha = cv2.blur(alpha, (r, r))[:, :, None]
77
+
78
+ blurred_FGA = cv2.blur(FG * alpha, (r, r))
79
+ blurred_FG = blurred_FGA / (blurred_alpha + 1e-5)
80
+
81
+ blurred_B1A = cv2.blur(B * (1 - alpha), (r, r))
82
+ blurred_B = blurred_B1A / ((1 - blurred_alpha) + 1e-5)
83
+ FG = blurred_FG + alpha * (image - alpha * blurred_FG - (1 - alpha) * blurred_B)
84
+ FG = np.clip(FG, 0, 1)
85
+ return FG, blurred_B
86
+
87
+
88
+ def FB_blur_fusion_foreground_estimator_cpu_2(image, alpha, r=90):
89
+ # Thanks to the source: https://github.com/Photoroom/fast-foreground-estimation
90
+ alpha = alpha[:, :, None]
91
+ FG, blur_B = FB_blur_fusion_foreground_estimator_cpu(image, image, image, alpha, r)
92
+ return FB_blur_fusion_foreground_estimator_cpu(image, FG, blur_B, alpha, r=6)[0]
93
+
94
+
95
+ ## GPU version refinement
96
+ def mean_blur(x, kernel_size):
97
+ """
98
+ equivalent to cv.blur
99
+ x: [B, C, H, W]
100
+ """
101
+ if kernel_size % 2 == 0:
102
+ pad_l = kernel_size // 2 - 1
103
+ pad_r = kernel_size // 2
104
+ pad_t = kernel_size // 2 - 1
105
+ pad_b = kernel_size // 2
106
+ else:
107
+ pad_l = pad_r = pad_t = pad_b = kernel_size // 2
108
+
109
+ x_padded = torch.nn.functional.pad(x, (pad_l, pad_r, pad_t, pad_b), mode='replicate')
110
+
111
+ return torch.nn.functional.avg_pool2d(x_padded, kernel_size=(kernel_size, kernel_size), stride=1, count_include_pad=False)
112
+
113
+ def FB_blur_fusion_foreground_estimator_gpu(image, FG, B, alpha, r=90):
114
+ as_dtype = lambda x, dtype: x.to(dtype) if x.dtype != dtype else x
115
+
116
+ input_dtype = image.dtype
117
+ # convert image to float to avoid overflow
118
+ image = as_dtype(image, torch.float32)
119
+ FG = as_dtype(FG, torch.float32)
120
+ B = as_dtype(B, torch.float32)
121
+ alpha = as_dtype(alpha, torch.float32)
122
+
123
+ blurred_alpha = mean_blur(alpha, kernel_size=r)
124
+
125
+ blurred_FGA = mean_blur(FG * alpha, kernel_size=r)
126
+ blurred_FG = blurred_FGA / (blurred_alpha + 1e-5)
127
+
128
+ blurred_B1A = mean_blur(B * (1 - alpha), kernel_size=r)
129
+ blurred_B = blurred_B1A / ((1 - blurred_alpha) + 1e-5)
130
+
131
+ FG_output = blurred_FG + alpha * (image - alpha * blurred_FG - (1 - alpha) * blurred_B)
132
+ FG_output = torch.clamp(FG_output, 0, 1)
133
+
134
+ return as_dtype(FG_output, input_dtype), as_dtype(blurred_B, input_dtype)
135
+
136
+
137
+ def FB_blur_fusion_foreground_estimator_gpu_2(image, alpha, r=90):
138
+ # Thanks to the source: https://github.com/ZhengPeng7/BiRefNet/issues/226#issuecomment-3016433728
139
+ FG, blur_B = FB_blur_fusion_foreground_estimator_gpu(image, image, image, alpha, r)
140
+ return FB_blur_fusion_foreground_estimator_gpu(image, FG, blur_B, alpha, r=6)[0]
141
+
142
+
143
+ def refine_foreground(image, mask, r=90, device='cuda'):
144
+ """both image and mask are in range of [0, 1]"""
145
+ if mask.size != image.size:
146
+ mask = mask.resize(image.size)
147
+
148
+ if device == 'cuda':
149
+ image = transforms.functional.to_tensor(image).float().cuda()
150
+ mask = transforms.functional.to_tensor(mask).float().cuda()
151
+ image = image.unsqueeze(0)
152
+ mask = mask.unsqueeze(0)
153
+
154
+ estimated_foreground = FB_blur_fusion_foreground_estimator_gpu_2(image, mask, r=r)
155
+
156
+ estimated_foreground = estimated_foreground.squeeze()
157
+ estimated_foreground = (estimated_foreground.mul(255.0)).to(torch.uint8)
158
+ estimated_foreground = estimated_foreground.permute(1, 2, 0).contiguous().cpu().numpy().astype(np.uint8)
159
+ else:
160
+ image = np.array(image, dtype=np.float32) / 255.0
161
+ mask = np.array(mask, dtype=np.float32) / 255.0
162
+ estimated_foreground = FB_blur_fusion_foreground_estimator_cpu_2(image, mask, r=r)
163
+ estimated_foreground = (estimated_foreground * 255.0).astype(np.uint8)
164
+
165
+ estimated_foreground = Image.fromarray(np.ascontiguousarray(estimated_foreground))
166
+
167
+ return estimated_foreground
168
+
169
+
170
+ def get_rankseg_mask(pred: torch.Tensor, metric: str) -> Image.Image:
171
+ rankseg = RankSEG(metric=metric, output_mode='multiclass', solver='RMA')
172
+ probs = pred.unsqueeze(0).unsqueeze(0)
173
+ rankseg_pred = rankseg.predict(probs).squeeze(0).to(torch.float32)
174
+ return transforms.ToPILImage()(rankseg_pred)
175
+
176
+
177
+ def build_masked_image(image: Image.Image, mask: Image.Image) -> Image.Image:
178
+ refined = refine_foreground(image, mask, device=device)
179
+ refined.putalpha(mask.resize(image.size))
180
+ return refined
181
+
182
+
183
+ def load_image(image_src):
184
+ if isinstance(image_src, str):
185
+ if os.path.isfile(image_src):
186
+ image_ori = Image.open(image_src)
187
+ else:
188
+ response = requests.get(image_src)
189
+ response.raise_for_status()
190
+ image_data = BytesIO(response.content)
191
+ image_ori = Image.open(image_data)
192
+ else:
193
+ image_ori = Image.fromarray(image_src)
194
+
195
+ if image_ori.mode == 'RGBA':
196
+ image_ori = rgba2rgb(image_ori)
197
+
198
+ return image_ori.convert('RGB')
199
+
200
+
201
+ class ImagePreprocessor():
202
+ def __init__(self, resolution: Tuple[int, int] = (1024, 1024)) -> None:
203
+ # Input resolution is on WxH.
204
+ self.transform_image = transforms.Compose([
205
+ transforms.Resize(resolution[::-1]),
206
+ transforms.ToTensor(),
207
+ transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]),
208
+ ])
209
+
210
+ def proc(self, image: Image.Image) -> torch.Tensor:
211
+ image = self.transform_image(image)
212
+ return image
213
+
214
+
215
+ usage_to_weights_file = {
216
+ 'General': 'BiRefNet',
217
+ 'General-HR': 'BiRefNet_HR',
218
+ 'Matting-HR': 'BiRefNet_HR-matting',
219
+ 'Matting': 'BiRefNet-matting',
220
+ 'Portrait': 'BiRefNet-portrait',
221
+ 'General-reso_512': 'BiRefNet_512x512',
222
+ 'General-Lite': 'BiRefNet_lite',
223
+ 'General-Lite-2K': 'BiRefNet_lite-2K',
224
+ # 'Anime-Lite': 'BiRefNet_lite-Anime',
225
+ 'DIS': 'BiRefNet-DIS5K',
226
+ 'HRSOD': 'BiRefNet-HRSOD',
227
+ 'COD': 'BiRefNet-COD',
228
+ 'DIS-TR_TEs': 'BiRefNet-DIS5K-TR_TEs',
229
+ 'General-legacy': 'BiRefNet-legacy',
230
+ 'General-dynamic': 'BiRefNet_dynamic',
231
+ 'Matting-dynamic': 'BiRefNet_dynamic-matting',
232
+ }
233
+
234
+ birefnet = transformers.AutoModelForImageSegmentation.from_pretrained('/'.join(('zhengpeng7', usage_to_weights_file['General'])), trust_remote_code=True)
235
+ birefnet.to(device)
236
+ birefnet.eval(); birefnet.half()
237
+
238
+
239
+ @spaces.GPU
240
+ def predict(images, resolution, weights_file, enable_rankseg, rankseg_metric):
241
+ assert (images is not None), 'AssertionError: images cannot be None.'
242
+
243
+ global birefnet
244
+ # Load BiRefNet with chosen weights
245
+ _weights_file = '/'.join(('zhengpeng7', usage_to_weights_file[weights_file] if weights_file is not None else usage_to_weights_file['General']))
246
+ print('Using weights: {}.'.format(_weights_file))
247
+ birefnet = transformers.AutoModelForImageSegmentation.from_pretrained(_weights_file, trust_remote_code=True)
248
+ birefnet.to(device)
249
+ birefnet.eval(); birefnet.half()
250
+
251
+ try:
252
+ resolution = [int(int(reso)//32*32) for reso in resolution.strip().split('x')]
253
+ except:
254
+ if weights_file in ['General-HR', 'Matting-HR']:
255
+ resolution = (2048, 2048)
256
+ elif weights_file in ['General-Lite-2K']:
257
+ resolution = (2560, 1440)
258
+ elif weights_file in ['General-reso_512']:
259
+ resolution = (512, 512)
260
+ else:
261
+ if '_dynamic' in weights_file:
262
+ resolution = None
263
+ print('Using the original size (div by 32) for inference.')
264
+ else:
265
+ resolution = (1024, 1024)
266
+ print('Invalid resolution input. Automatically changed to 1024x1024 / 2048x2048 / 2560x1440.')
267
+
268
+ if isinstance(images, list):
269
+ raw_save_paths = []
270
+ rankseg_save_paths = []
271
+ save_dir = 'preds-BiRefNet'
272
+ if not os.path.exists(save_dir):
273
+ os.makedirs(save_dir)
274
+ tab_is_batch = True
275
+ else:
276
+ images = [images]
277
+ tab_is_batch = False
278
+
279
+ rankseg_metric = (rankseg_metric or 'dice').lower()
280
+ if rankseg_metric not in RANKSEG_METRICS:
281
+ rankseg_metric = 'dice'
282
+
283
+ for image_src in images:
284
+ image = load_image(image_src)
285
+ # Preprocess the image
286
+ if resolution is None:
287
+ resolution_div_by_32 = [int(int(reso)//32*32) for reso in image.size]
288
+ if resolution_div_by_32 != resolution:
289
+ resolution = resolution_div_by_32
290
+ image_preprocessor = ImagePreprocessor(resolution=tuple(resolution))
291
+ image_proc = image_preprocessor.proc(image)
292
+ image_proc = image_proc.unsqueeze(0)
293
+
294
+ # Prediction
295
+ with torch.no_grad():
296
+ preds = birefnet(image_proc.to(device).half())[-1].sigmoid().cpu()
297
+ pred = preds[0].squeeze()
298
+
299
+ pred_pil = transforms.ToPILImage()(pred)
300
+ raw_image_masked = build_masked_image(image, pred_pil)
301
+ rankseg_image_masked = None
302
+ if enable_rankseg:
303
+ rankseg_mask = get_rankseg_mask(pred, rankseg_metric)
304
+ rankseg_image_masked = build_masked_image(image, rankseg_mask)
305
+
306
+ if device == 'cuda':
307
+ torch.cuda.empty_cache()
308
+
309
+ if tab_is_batch:
310
+ image_name = os.path.splitext(os.path.basename(image_src))[0]
311
+ raw_save_file_path = os.path.join(save_dir, f"{image_name}_raw.png")
312
+ raw_image_masked.save(raw_save_file_path)
313
+ raw_save_paths.append(raw_save_file_path)
314
+ if enable_rankseg and rankseg_image_masked is not None:
315
+ rankseg_save_file_path = os.path.join(save_dir, f"{image_name}_rankseg.png")
316
+ rankseg_image_masked.save(rankseg_save_file_path)
317
+ rankseg_save_paths.append(rankseg_save_file_path)
318
+
319
+ if tab_is_batch:
320
+ zip_file_path = os.path.join(save_dir, "{}.zip".format(save_dir))
321
+ with zipfile.ZipFile(zip_file_path, 'w') as zipf:
322
+ for file in raw_save_paths + rankseg_save_paths:
323
+ zipf.write(file, os.path.basename(file))
324
+ return raw_save_paths, rankseg_save_paths, zip_file_path
325
+ else:
326
+ return image, raw_image_masked, rankseg_image_masked
327
+
328
+
329
+ examples = [[_] for _ in glob('examples/*')][:]
330
+ # Add the option of resolution in a text box.
331
+ for idx_example, example in enumerate(examples):
332
+ if 'My_' in example[0]:
333
+ example_resolution = '2048x2048'
334
+ model_choice = 'Matting-HR'
335
+ else:
336
+ example_resolution = '1024x1024'
337
+ model_choice = 'General'
338
+ examples[idx_example] = examples[idx_example] + [example_resolution, model_choice, True, 'dice']
339
+
340
+ examples_url = [
341
+ ['https://hips.hearstapps.com/hmg-prod/images/gettyimages-1229892983-square.jpg'],
342
+ ]
343
+ for idx_example_url, example_url in enumerate(examples_url):
344
+ examples_url[idx_example_url] = examples_url[idx_example_url] + ['1024x1024', 'General', True, 'dice']
345
+
346
+ descriptions = ('Upload a picture, our model will extract a highly accurate segmentation of the subject in it.\n)'
347
+ ' The resolution used in our training was `1024x1024`, which is the suggested resolution to obtain good results! `2048x2048` is suggested for BiRefNet_HR.\n'
348
+ ' Our codes can be found at https://github.com/ZhengPeng7/BiRefNet.\n'
349
+ ' We also maintain the HF model of BiRefNet at https://huggingface.co/ZhengPeng7/BiRefNet for easier access.')
350
+
351
+ tab_image = gr.Interface(
352
+ fn=predict,
353
+ inputs=[
354
+ gr.Image(label='Upload an image', image_mode='RGBA'), # Keep alpha channel
355
+ gr.Textbox(lines=1, placeholder="Type the resolution (`WxH`) you want, e.g., `1024x1024`.", label="Resolution"),
356
+ gr.Radio(list(usage_to_weights_file.keys()), value='General', label="Weights", info="Choose the weights you want."),
357
+ gr.Checkbox(value=True, label="Enable RankSEG"),
358
+ gr.Radio(RANKSEG_METRICS, value='dice', label="RankSEG metric", info="Choose the target metric for RankSEG post-processing.")
359
+ ],
360
+ outputs=[
361
+ gr.Image(label="Original image", type="pil", format='png'),
362
+ gr.Image(label="BiRefNet result", type="pil", format='png'),
363
+ gr.Image(label="BiRefNet + RankSEG", type="pil", format='png'),
364
+ ],
365
+ examples=examples,
366
+ api_name="image",
367
+ description=descriptions,
368
+ )
369
+
370
+ tab_text = gr.Interface(
371
+ fn=predict,
372
+ inputs=[
373
+ gr.Textbox(label="Paste an image URL"),
374
+ gr.Textbox(lines=1, placeholder="Type the resolution (`WxH`) you want, e.g., `1024x1024`.", label="Resolution"),
375
+ gr.Radio(list(usage_to_weights_file.keys()), value='General', label="Weights", info="Choose the weights you want."),
376
+ gr.Checkbox(value=True, label="Enable RankSEG"),
377
+ gr.Radio(RANKSEG_METRICS, value='dice', label="RankSEG metric", info="Choose the target metric for RankSEG post-processing.")
378
+ ],
379
+ outputs=[
380
+ gr.Image(label="Original image", type="pil", format='png'),
381
+ gr.Image(label="BiRefNet result", type="pil", format='png'),
382
+ gr.Image(label="BiRefNet + RankSEG", type="pil", format='png'),
383
+ ],
384
+ examples=examples_url,
385
+ api_name="URL",
386
+ description=descriptions+'\nTab-URL is partially modified from https://huggingface.co/spaces/not-lain/background-removal, thanks to this great work!',
387
+ )
388
+
389
+ tab_batch = gr.Interface(
390
+ fn=predict,
391
+ inputs=[
392
+ gr.File(label="Upload multiple images", type="filepath", file_count="multiple"),
393
+ gr.Textbox(lines=1, placeholder="Type the resolution (`WxH`) you want, e.g., `1024x1024`.", label="Resolution"),
394
+ gr.Radio(list(usage_to_weights_file.keys()), value='General', label="Weights", info="Choose the weights you want."),
395
+ gr.Checkbox(value=True, label="Enable RankSEG"),
396
+ gr.Radio(RANKSEG_METRICS, value='dice', label="RankSEG metric", info="Choose the target metric for RankSEG post-processing.")
397
+ ],
398
+ outputs=[
399
+ gr.Gallery(label="BiRefNet results"),
400
+ gr.Gallery(label="BiRefNet + RankSEG results"),
401
+ gr.File(label="Download masked images."),
402
+ ],
403
+ api_name="batch",
404
+ description=descriptions+'\nTab-batch is partially modified from https://huggingface.co/spaces/NegiTurkey/Multi_Birefnetfor_Background_Removal, thanks to this great work!',
405
+ )
406
+
407
+ demo = gr.TabbedInterface(
408
+ [tab_image, tab_text, tab_batch],
409
+ ['image', 'URL', 'batch'],
410
+ title="Official Online Demo of BiRefNet",
411
+ )
412
+
413
+ if __name__ == "__main__":
414
+ demo.launch(debug=True)
app_local.py ADDED
@@ -0,0 +1,410 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import cv2
3
+ import numpy as np
4
+ import torch
5
+ import gradio as gr
6
+ # import spaces
7
+
8
+ from glob import glob
9
+ from typing import Tuple
10
+
11
+ from PIL import Image
12
+ # from gradio_imageslider import ImageSlider
13
+ import transformers
14
+ import torch
15
+ from torchvision import transforms
16
+
17
+ import requests
18
+ from io import BytesIO
19
+ import zipfile
20
+
21
+ from rankseg import RankSEG
22
+
23
+
24
+ torch.set_float32_matmul_precision('high')
25
+ # torch.jit.script = lambda f: f
26
+
27
+ device = "cuda" if torch.cuda.is_available() else "cpu"
28
+ RANKSEG_METRICS = ["dice", "iou"]
29
+
30
+
31
+ def rgba2rgb(img):
32
+ """
33
+ Convert RGBA image to RGB with white background.
34
+ Supports both PIL.Image and numpy.ndarray.
35
+ """
36
+
37
+ # 1. Handle PIL Image
38
+ if isinstance(img, Image.Image):
39
+ img = img.convert("RGBA")
40
+ bg = Image.new("RGBA", img.size, (255, 255, 255))
41
+ return Image.alpha_composite(bg, img).convert("RGB")
42
+
43
+ # 2. Handle Numpy Array (OpenCV)
44
+ elif isinstance(img, np.ndarray):
45
+ # Grayscale to RGB
46
+ if img.ndim == 2:
47
+ return np.stack([img] * 3, axis=-1)
48
+
49
+ # Already 3 channels
50
+ if img.shape[2] == 3:
51
+ return img
52
+
53
+ # RGBA to RGB (blending with white)
54
+ elif img.shape[2] == 4:
55
+ # Normalize alpha to 0-1 and keep shape (H, W, 1)
56
+ alpha = img[..., 3:4].astype(float) / 255.0
57
+ foreground = img[..., :3].astype(float)
58
+ background = 255.0
59
+
60
+ # Blend formula: source * alpha + bg * (1 - alpha)
61
+ out = foreground * alpha + background * (1.0 - alpha)
62
+
63
+ return out.clip(0, 255).astype(np.uint8)
64
+
65
+ else:
66
+ raise TypeError(f"Unsupported type: {type(img)}")
67
+
68
+
69
+ ## CPU version refinement
70
+ def FB_blur_fusion_foreground_estimator_cpu(image, FG, B, alpha, r=90):
71
+ if isinstance(image, Image.Image):
72
+ image = np.array(image) / 255.0
73
+ blurred_alpha = cv2.blur(alpha, (r, r))[:, :, None]
74
+
75
+ blurred_FGA = cv2.blur(FG * alpha, (r, r))
76
+ blurred_FG = blurred_FGA / (blurred_alpha + 1e-5)
77
+
78
+ blurred_B1A = cv2.blur(B * (1 - alpha), (r, r))
79
+ blurred_B = blurred_B1A / ((1 - blurred_alpha) + 1e-5)
80
+ FG = blurred_FG + alpha * (image - alpha * blurred_FG - (1 - alpha) * blurred_B)
81
+ FG = np.clip(FG, 0, 1)
82
+ return FG, blurred_B
83
+
84
+
85
+ def FB_blur_fusion_foreground_estimator_cpu_2(image, alpha, r=90):
86
+ # Thanks to the source: https://github.com/Photoroom/fast-foreground-estimation
87
+ alpha = alpha[:, :, None]
88
+ FG, blur_B = FB_blur_fusion_foreground_estimator_cpu(image, image, image, alpha, r)
89
+ return FB_blur_fusion_foreground_estimator_cpu(image, FG, blur_B, alpha, r=6)[0]
90
+
91
+
92
+ ## GPU version refinement
93
+ def mean_blur(x, kernel_size):
94
+ """
95
+ equivalent to cv.blur
96
+ x: [B, C, H, W]
97
+ """
98
+ if kernel_size % 2 == 0:
99
+ pad_l = kernel_size // 2 - 1
100
+ pad_r = kernel_size // 2
101
+ pad_t = kernel_size // 2 - 1
102
+ pad_b = kernel_size // 2
103
+ else:
104
+ pad_l = pad_r = pad_t = pad_b = kernel_size // 2
105
+
106
+ x_padded = torch.nn.functional.pad(x, (pad_l, pad_r, pad_t, pad_b), mode='replicate')
107
+
108
+ return torch.nn.functional.avg_pool2d(x_padded, kernel_size=(kernel_size, kernel_size), stride=1, count_include_pad=False)
109
+
110
+ def FB_blur_fusion_foreground_estimator_gpu(image, FG, B, alpha, r=90):
111
+ as_dtype = lambda x, dtype: x.to(dtype) if x.dtype != dtype else x
112
+
113
+ input_dtype = image.dtype
114
+ # convert image to float to avoid overflow
115
+ image = as_dtype(image, torch.float32)
116
+ FG = as_dtype(FG, torch.float32)
117
+ B = as_dtype(B, torch.float32)
118
+ alpha = as_dtype(alpha, torch.float32)
119
+
120
+ blurred_alpha = mean_blur(alpha, kernel_size=r)
121
+
122
+ blurred_FGA = mean_blur(FG * alpha, kernel_size=r)
123
+ blurred_FG = blurred_FGA / (blurred_alpha + 1e-5)
124
+
125
+ blurred_B1A = mean_blur(B * (1 - alpha), kernel_size=r)
126
+ blurred_B = blurred_B1A / ((1 - blurred_alpha) + 1e-5)
127
+
128
+ FG_output = blurred_FG + alpha * (image - alpha * blurred_FG - (1 - alpha) * blurred_B)
129
+ FG_output = torch.clamp(FG_output, 0, 1)
130
+
131
+ return as_dtype(FG_output, input_dtype), as_dtype(blurred_B, input_dtype)
132
+
133
+
134
+ def FB_blur_fusion_foreground_estimator_gpu_2(image, alpha, r=90):
135
+ # Thanks to the source: https://github.com/ZhengPeng7/BiRefNet/issues/226#issuecomment-3016433728
136
+ FG, blur_B = FB_blur_fusion_foreground_estimator_gpu(image, image, image, alpha, r)
137
+ return FB_blur_fusion_foreground_estimator_gpu(image, FG, blur_B, alpha, r=6)[0]
138
+
139
+
140
+ def refine_foreground(image, mask, r=90, device='cuda'):
141
+ """both image and mask are in range of [0, 1]"""
142
+ if mask.size != image.size:
143
+ mask = mask.resize(image.size)
144
+
145
+ if device == 'cuda':
146
+ image = transforms.functional.to_tensor(image).float().cuda()
147
+ mask = transforms.functional.to_tensor(mask).float().cuda()
148
+ image = image.unsqueeze(0)
149
+ mask = mask.unsqueeze(0)
150
+
151
+ estimated_foreground = FB_blur_fusion_foreground_estimator_gpu_2(image, mask, r=r)
152
+
153
+ estimated_foreground = estimated_foreground.squeeze()
154
+ estimated_foreground = (estimated_foreground.mul(255.0)).to(torch.uint8)
155
+ estimated_foreground = estimated_foreground.permute(1, 2, 0).contiguous().cpu().numpy().astype(np.uint8)
156
+ else:
157
+ image = np.array(image, dtype=np.float32) / 255.0
158
+ mask = np.array(mask, dtype=np.float32) / 255.0
159
+ estimated_foreground = FB_blur_fusion_foreground_estimator_cpu_2(image, mask, r=r)
160
+ estimated_foreground = (estimated_foreground * 255.0).astype(np.uint8)
161
+
162
+ estimated_foreground = Image.fromarray(np.ascontiguousarray(estimated_foreground))
163
+
164
+ return estimated_foreground
165
+
166
+
167
+ def get_rankseg_mask(pred: torch.Tensor, metric: str) -> Image.Image:
168
+ rankseg = RankSEG(metric=metric, output_mode='multiclass', solver='RMA')
169
+ probs = pred.unsqueeze(0).unsqueeze(0)
170
+ rankseg_pred = rankseg.predict(probs).squeeze(0).to(torch.float32)
171
+ return transforms.ToPILImage()(rankseg_pred)
172
+
173
+
174
+ def build_masked_image(image: Image.Image, mask: Image.Image) -> Image.Image:
175
+ refined = refine_foreground(image, mask, device=device)
176
+ refined.putalpha(mask.resize(image.size))
177
+ return refined
178
+
179
+
180
+ def load_image(image_src):
181
+ if isinstance(image_src, str):
182
+ if os.path.isfile(image_src):
183
+ image_ori = Image.open(image_src)
184
+ else:
185
+ response = requests.get(image_src)
186
+ response.raise_for_status()
187
+ image_data = BytesIO(response.content)
188
+ image_ori = Image.open(image_data)
189
+ else:
190
+ image_ori = Image.fromarray(image_src)
191
+
192
+ if image_ori.mode == 'RGBA':
193
+ image_ori = rgba2rgb(image_ori)
194
+
195
+ return image_ori.convert('RGB')
196
+
197
+
198
+ class ImagePreprocessor():
199
+ def __init__(self, resolution: Tuple[int, int] = (1024, 1024)) -> None:
200
+ # Input resolution is on WxH.
201
+ self.transform_image = transforms.Compose([
202
+ transforms.Resize(resolution[::-1]),
203
+ transforms.ToTensor(),
204
+ transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]),
205
+ ])
206
+
207
+ def proc(self, image: Image.Image) -> torch.Tensor:
208
+ image = self.transform_image(image)
209
+ return image
210
+
211
+
212
+ usage_to_weights_file = {
213
+ 'General': 'BiRefNet',
214
+ 'General-HR': 'BiRefNet_HR',
215
+ 'Matting-HR': 'BiRefNet_HR-matting',
216
+ 'Matting': 'BiRefNet-matting',
217
+ 'Portrait': 'BiRefNet-portrait',
218
+ 'General-reso_512': 'BiRefNet_512x512',
219
+ 'General-Lite': 'BiRefNet_lite',
220
+ 'General-Lite-2K': 'BiRefNet_lite-2K',
221
+ 'Anime-Lite': 'BiRefNet_lite-Anime',
222
+ 'DIS': 'BiRefNet-DIS5K',
223
+ 'HRSOD': 'BiRefNet-HRSOD',
224
+ 'COD': 'BiRefNet-COD',
225
+ 'DIS-TR_TEs': 'BiRefNet-DIS5K-TR_TEs',
226
+ 'General-legacy': 'BiRefNet-legacy',
227
+ 'General-dynamic': 'BiRefNet_dynamic',
228
+ }
229
+
230
+ birefnet = transformers.AutoModelForImageSegmentation.from_pretrained('/'.join(('zhengpeng7', usage_to_weights_file['General'])), trust_remote_code=True)
231
+ birefnet.to(device)
232
+ birefnet.eval(); birefnet.half()
233
+
234
+
235
+ # @spaces.GPU
236
+ def predict(images, resolution, weights_file, enable_rankseg, rankseg_metric):
237
+ assert (images is not None), 'AssertionError: images cannot be None.'
238
+
239
+ global birefnet
240
+ # Load BiRefNet with chosen weights
241
+ _weights_file = '/'.join(('zhengpeng7', usage_to_weights_file[weights_file] if weights_file is not None else usage_to_weights_file['General']))
242
+ print('Using weights: {}.'.format(_weights_file))
243
+ birefnet = transformers.AutoModelForImageSegmentation.from_pretrained(_weights_file, trust_remote_code=True)
244
+ birefnet.to(device)
245
+ birefnet.eval(); birefnet.half()
246
+
247
+ try:
248
+ resolution = [int(int(reso)//32*32) for reso in resolution.strip().split('x')]
249
+ except:
250
+ if weights_file in ['General-HR', 'Matting-HR']:
251
+ resolution = (2048, 2048)
252
+ elif weights_file in ['General-Lite-2K']:
253
+ resolution = (2560, 1440)
254
+ elif weights_file in ['General-reso_512']:
255
+ resolution = (512, 512)
256
+ else:
257
+ if weights_file in ['General-dynamic']:
258
+ resolution = None
259
+ print('Using the original size (div by 32) for inference.')
260
+ else:
261
+ resolution = (1024, 1024)
262
+ print('Invalid resolution input. Automatically changed to 1024x1024 / 2048x2048 / 2560x1440.')
263
+
264
+ if isinstance(images, list):
265
+ raw_save_paths = []
266
+ rankseg_save_paths = []
267
+ save_dir = 'preds-BiRefNet'
268
+ if not os.path.exists(save_dir):
269
+ os.makedirs(save_dir)
270
+ tab_is_batch = True
271
+ else:
272
+ images = [images]
273
+ tab_is_batch = False
274
+
275
+ rankseg_metric = (rankseg_metric or 'dice').lower()
276
+ if rankseg_metric not in RANKSEG_METRICS:
277
+ rankseg_metric = 'dice'
278
+
279
+ for image_src in images:
280
+ image = load_image(image_src)
281
+ # Preprocess the image
282
+ if resolution is None:
283
+ resolution_div_by_32 = [int(int(reso)//32*32) for reso in image.size]
284
+ if resolution_div_by_32 != resolution:
285
+ resolution = resolution_div_by_32
286
+ image_preprocessor = ImagePreprocessor(resolution=tuple(resolution))
287
+ image_proc = image_preprocessor.proc(image)
288
+ image_proc = image_proc.unsqueeze(0)
289
+
290
+ # Prediction
291
+ with torch.no_grad():
292
+ preds = birefnet(image_proc.to(device).half())[-1].sigmoid().cpu()
293
+ pred = preds[0].squeeze()
294
+
295
+ pred_pil = transforms.ToPILImage()(pred)
296
+ raw_image_masked = build_masked_image(image, pred_pil)
297
+ rankseg_image_masked = None
298
+ if enable_rankseg:
299
+ rankseg_mask = get_rankseg_mask(pred, rankseg_metric)
300
+ rankseg_image_masked = build_masked_image(image, rankseg_mask)
301
+
302
+ if device == 'cuda':
303
+ torch.cuda.empty_cache()
304
+
305
+ if tab_is_batch:
306
+ image_name = os.path.splitext(os.path.basename(image_src))[0]
307
+ raw_save_file_path = os.path.join(save_dir, f"{image_name}_raw.png")
308
+ raw_image_masked.save(raw_save_file_path)
309
+ raw_save_paths.append(raw_save_file_path)
310
+ if enable_rankseg and rankseg_image_masked is not None:
311
+ rankseg_save_file_path = os.path.join(save_dir, f"{image_name}_rankseg.png")
312
+ rankseg_image_masked.save(rankseg_save_file_path)
313
+ rankseg_save_paths.append(rankseg_save_file_path)
314
+
315
+ if tab_is_batch:
316
+ zip_file_path = os.path.join(save_dir, "{}.zip".format(save_dir))
317
+ with zipfile.ZipFile(zip_file_path, 'w') as zipf:
318
+ for file in raw_save_paths + rankseg_save_paths:
319
+ zipf.write(file, os.path.basename(file))
320
+ return raw_save_paths, rankseg_save_paths, zip_file_path
321
+ else:
322
+ return image, raw_image_masked, rankseg_image_masked
323
+
324
+
325
+ examples = [[_] for _ in glob('examples/*')][:]
326
+ # Add the option of resolution in a text box.
327
+ for idx_example, example in enumerate(examples):
328
+ if 'My_' in example[0]:
329
+ example_resolution = '2048x2048'
330
+ model_choice = 'Matting-HR'
331
+ else:
332
+ example_resolution = '1024x1024'
333
+ model_choice = 'General'
334
+ examples[idx_example] = examples[idx_example] + [example_resolution, model_choice, True, 'dice']
335
+
336
+ examples_url = [
337
+ ['https://hips.hearstapps.com/hmg-prod/images/gettyimages-1229892983-square.jpg'],
338
+ ]
339
+ for idx_example_url, example_url in enumerate(examples_url):
340
+ examples_url[idx_example_url] = examples_url[idx_example_url] + ['1024x1024', 'General', True, 'dice']
341
+
342
+ descriptions = ('Upload a picture, our model will extract a highly accurate segmentation of the subject in it.\n)'
343
+ ' The resolution used in our training was `1024x1024`, which is the suggested resolution to obtain good results! `2048x2048` is suggested for BiRefNet_HR.\n'
344
+ ' Our codes can be found at https://github.com/ZhengPeng7/BiRefNet.\n'
345
+ ' We also maintain the HF model of BiRefNet at https://huggingface.co/ZhengPeng7/BiRefNet for easier access.')
346
+
347
+ tab_image = gr.Interface(
348
+ fn=predict,
349
+ inputs=[
350
+ gr.Image(label='Upload an image', image_mode='RGBA'), # Keep alpha channel
351
+ gr.Textbox(lines=1, placeholder="Type the resolution (`WxH`) you want, e.g., `1024x1024`.", label="Resolution"),
352
+ gr.Radio(list(usage_to_weights_file.keys()), value='General', label="Weights", info="Choose the weights you want."),
353
+ gr.Checkbox(value=True, label="Enable RankSEG"),
354
+ gr.Radio(RANKSEG_METRICS, value='dice', label="RankSEG metric", info="Choose the target metric for RankSEG post-processing.")
355
+ ],
356
+ outputs=[
357
+ gr.Image(label="Original image", type="pil", format='png'),
358
+ gr.Image(label="BiRefNet result", type="pil", format='png'),
359
+ gr.Image(label="BiRefNet + RankSEG", type="pil", format='png'),
360
+ ],
361
+ examples=examples,
362
+ api_name="image",
363
+ description=descriptions,
364
+ )
365
+
366
+ tab_text = gr.Interface(
367
+ fn=predict,
368
+ inputs=[
369
+ gr.Textbox(label="Paste an image URL"),
370
+ gr.Textbox(lines=1, placeholder="Type the resolution (`WxH`) you want, e.g., `1024x1024`.", label="Resolution"),
371
+ gr.Radio(list(usage_to_weights_file.keys()), value='General', label="Weights", info="Choose the weights you want."),
372
+ gr.Checkbox(value=True, label="Enable RankSEG"),
373
+ gr.Radio(RANKSEG_METRICS, value='dice', label="RankSEG metric", info="Choose the target metric for RankSEG post-processing.")
374
+ ],
375
+ outputs=[
376
+ gr.Image(label="Original image", type="pil", format='png'),
377
+ gr.Image(label="BiRefNet result", type="pil", format='png'),
378
+ gr.Image(label="BiRefNet + RankSEG", type="pil", format='png'),
379
+ ],
380
+ examples=examples_url,
381
+ api_name="URL",
382
+ description=descriptions+'\nTab-URL is partially modified from https://huggingface.co/spaces/not-lain/background-removal, thanks to this great work!',
383
+ )
384
+
385
+ tab_batch = gr.Interface(
386
+ fn=predict,
387
+ inputs=[
388
+ gr.File(label="Upload multiple images", type="filepath", file_count="multiple"),
389
+ gr.Textbox(lines=1, placeholder="Type the resolution (`WxH`) you want, e.g., `1024x1024`.", label="Resolution"),
390
+ gr.Radio(list(usage_to_weights_file.keys()), value='General', label="Weights", info="Choose the weights you want."),
391
+ gr.Checkbox(value=True, label="Enable RankSEG"),
392
+ gr.Radio(RANKSEG_METRICS, value='dice', label="RankSEG metric", info="Choose the target metric for RankSEG post-processing.")
393
+ ],
394
+ outputs=[
395
+ gr.Gallery(label="BiRefNet results"),
396
+ gr.Gallery(label="BiRefNet + RankSEG results"),
397
+ gr.File(label="Download masked images."),
398
+ ],
399
+ api_name="batch",
400
+ description=descriptions+'\nTab-batch is partially modified from https://huggingface.co/spaces/NegiTurkey/Multi_Birefnetfor_Background_Removal, thanks to this great work!',
401
+ )
402
+
403
+ demo = gr.TabbedInterface(
404
+ [tab_image, tab_text, tab_batch],
405
+ ['image', 'URL', 'batch'],
406
+ title="Official Online Demo of BiRefNet",
407
+ )
408
+
409
+ if __name__ == "__main__":
410
+ demo.launch(debug=True)
examples/Helicopter.jpg ADDED

Git LFS Details

  • SHA256: 087aa9cb63a3a9c644be02f576db4ffcc113a1031d55107d6372bc67d8e09aed
  • Pointer size: 131 Bytes
  • Size of remote file: 639 kB
examples/Jewelry.jpg ADDED

Git LFS Details

  • SHA256: 7ac3b5f61ca2d282901d0932921f500b65344a0f0e91b3dc81599cf39c1d7262
  • Pointer size: 131 Bytes
  • Size of remote file: 986 kB
examples/My_Love.jpg ADDED

Git LFS Details

  • SHA256: ffca8347b4e2bbc4e064f02b1aaf93cd53a8834e6fd210200172b913206c2aef
  • Pointer size: 132 Bytes
  • Size of remote file: 1.47 MB
examples/My_Love_1.jpg ADDED

Git LFS Details

  • SHA256: 5eaff4519be9e5e32bcf214d72418a2fd1259f3bfea4678fdc5f84eb329eb977
  • Pointer size: 131 Bytes
  • Size of remote file: 164 kB
examples/My_Love_2.jpg ADDED

Git LFS Details

  • SHA256: 55060d321436a58d17b98f1f10de546ef638bcf2b6774c8d714a3e2d1851cf55
  • Pointer size: 132 Bytes
  • Size of remote file: 1.25 MB
examples/My_MiSheng.jpg ADDED

Git LFS Details

  • SHA256: 0eb9960dbeb7e9ace2e1c9a20cdad9405983d182bad4ce337527f13be45af230
  • Pointer size: 132 Bytes
  • Size of remote file: 2.05 MB
examples/Windmill.jpg ADDED

Git LFS Details

  • SHA256: cb2eada821fc6eb5ea9d9a2b1c3134111341116ce1c674a9c8499d8c9ab41320
  • Pointer size: 131 Bytes
  • Size of remote file: 477 kB
requirements.txt ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ torch==2.9.1
2
+ torchvision
3
+ numpy
4
+ opencv-python
5
+ tqdm
6
+ timm
7
+ prettytable
8
+ scipy
9
+ scikit-image
10
+ kornia
11
+ gradio_imageslider>=0.0.18
12
+ transformers
13
+ huggingface_hub>=0.30
14
+ einops
15
+ requests
16
+ rankseg