diff --git a/BiRefNet_config.py b/BiRefNet_config.py
new file mode 100644
index 0000000..37c8ac5
--- /dev/null
+++ b/BiRefNet_config.py
@@ -0,0 +1,11 @@
+from transformers import PretrainedConfig
+
+class BiRefNetConfig(PretrainedConfig):
+ model_type = "SegformerForSemanticSegmentation"
+ def __init__(
+ self,
+ bb_pretrained=False,
+ **kwargs
+ ):
+ self.bb_pretrained = bb_pretrained
+ super().__init__(**kwargs)
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..757e7f1
--- /dev/null
+++ b/README.md
@@ -0,0 +1,59 @@
+# ComfyUI-BiRefNet-Hugo
+
+## 介绍 | Introduction
+
+本仓库将BiRefNet最新模型封装为ComfyUI节点来使用,相较于旧模型,最新模型的抠图精度更高更好。
+This repository wraps the latest BiRefNet model as ComfyUI nodes. Compared to the previous model, the latest model offers higher and better matting accuracy.
+
+## 安装 | Installation
+
+1. 进入节点目录, `ComfyUI/custom_nodes/`
+2. `git clone https://github.com/MoonHugo/ComfyUI-BiRefNet-Hugo.git`
+3. `cd ComfyUI-BiRefNet-Hugo`
+4. `pip install -r requirements.txt`
+___
+
+1. Go to comfyUI custom_nodes folder, `ComfyUI/custom_nodes/`
+2. `git clone https://github.com/MoonHugo/ComfyUI-BiRefNet-Hugo.git`
+3. `cd ComfyUI-BiRefNet-Hugo`
+4. `pip install -r requirements.txt`
+
+## 使用 | Usage
+
+示例工作流放置在`ComfyUI-BiRefNet-Hugo/workflow`中
+The demo workflow placed in `ComfyUI-BiRefNet-Hugo/workflow`
+___
+工作流workflow.json的使用
+The use of workflow.json
+
+
+
+工作流video_workflow.json的使用
+The use of video_workflow.json
+___
+
+
+## 效果演示 | Sample Result
+
+
+
+
+
+
+
+## 社交账号 | Social Account Homepage
+- Bilibili:[我的B站主页](https://space.bilibili.com/1303099255)
+
+## 感谢 | Acknowledgments
+
+感谢BiRefNet仓库的所有作者 [ZhengPeng7/BiRefNet](https://github.com/zhengpeng7/birefnet)
+
+Thanks to BiRefNet repo owner [ZhengPeng7/BiRefNet](https://github.com/zhengpeng7/birefnet)
+
+部分代码参考了 [ZHO-ZHO-ZHO/ComfyUI-BiRefNet-ZHO](https://github.com/ZHO-ZHO-ZHO/ComfyUI-BiRefNet-ZHO) 感谢!
+
+Some of the code references [ZHO-ZHO-ZHO/ComfyUI-BiRefNet-ZHO](https://github.com/ZHO-ZHO-ZHO/ComfyUI-BiRefNet-ZHO) Thanks!
+
+## 关注历史 | star history
+
+[](https://star-history.com/#MoonHugo/ComfyUI-BiRefNet-Hugo&Date)
\ No newline at end of file
diff --git a/__init__.py b/__init__.py
new file mode 100644
index 0000000..d721463
--- /dev/null
+++ b/__init__.py
@@ -0,0 +1,3 @@
+from .nodes import NODE_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS
+
+__all__ = ['NODE_CLASS_MAPPINGS', 'NODE_DISPLAY_NAME_MAPPINGS']
\ No newline at end of file
diff --git a/assets/2de5b085-1125-46f9-8ef3-06706743f182.png b/assets/2de5b085-1125-46f9-8ef3-06706743f182.png
new file mode 100644
index 0000000..6d07113
Binary files /dev/null and b/assets/2de5b085-1125-46f9-8ef3-06706743f182.png differ
diff --git a/assets/d0a22b2a-ceb3-4205-9b4e-f6a68e4337c7.png b/assets/d0a22b2a-ceb3-4205-9b4e-f6a68e4337c7.png
new file mode 100644
index 0000000..53a1562
Binary files /dev/null and b/assets/d0a22b2a-ceb3-4205-9b4e-f6a68e4337c7.png differ
diff --git a/assets/demo1.gif b/assets/demo1.gif
new file mode 100644
index 0000000..9e7ccaa
Binary files /dev/null and b/assets/demo1.gif differ
diff --git a/assets/demo2.gif b/assets/demo2.gif
new file mode 100644
index 0000000..e7549bb
Binary files /dev/null and b/assets/demo2.gif differ
diff --git a/assets/demo3.gif b/assets/demo3.gif
new file mode 100644
index 0000000..b2cee1f
Binary files /dev/null and b/assets/demo3.gif differ
diff --git a/config.py b/config.py
new file mode 100644
index 0000000..3ddd09f
--- /dev/null
+++ b/config.py
@@ -0,0 +1,148 @@
+### config.py
+
+import os
+import math
+from folder_paths import models_dir
+os.environ['HOME'] = os.path.expanduser("~")
+class Config():
+ def __init__(self) -> None:
+ # PATH settings
+ self.sys_home_dir = os.environ['HOME'] # Make up your file system as: SYS_HOME_DIR/codes/dis/BiRefNet, SYS_HOME_DIR/datasets/dis/xx, SYS_HOME_DIR/weights/xx
+ # TASK settings
+ self.task = ['DIS5K', 'COD', 'HRSOD', 'DIS5K+HRSOD+HRS10K', 'P3M-10k'][0]
+ self.training_set = {
+ 'DIS5K': ['DIS-TR', 'DIS-TR+DIS-TE1+DIS-TE2+DIS-TE3+DIS-TE4'][0],
+ 'COD': 'TR-COD10K+TR-CAMO',
+ 'HRSOD': ['TR-DUTS', 'TR-HRSOD', 'TR-UHRSD', 'TR-DUTS+TR-HRSOD', 'TR-DUTS+TR-UHRSD', 'TR-HRSOD+TR-UHRSD', 'TR-DUTS+TR-HRSOD+TR-UHRSD'][5],
+ 'DIS5K+HRSOD+HRS10K': 'DIS-TE1+DIS-TE2+DIS-TE3+DIS-TE4+DIS-TR+TE-HRS10K+TE-HRSOD+TE-UHRSD+TR-HRS10K+TR-HRSOD+TR-UHRSD', # leave DIS-VD for evaluation.
+ 'P3M-10k': 'TR-P3M-10k',
+ }[self.task]
+ self.prompt4loc = ['dense', 'sparse'][0]
+
+ # Faster-Training settings
+ self.load_all = True
+ self.compile = True # 1. Trigger CPU memory leak in some extend, which is an inherent problem of PyTorch.
+ # Machines with > 70GB CPU memory can run the whole training on DIS5K with default setting.
+ # 2. Higher PyTorch version may fix it: https://github.com/pytorch/pytorch/issues/119607.
+ # 3. But compile in Pytorch > 2.0.1 seems to bring no acceleration for training.
+ self.precisionHigh = True
+
+ # MODEL settings
+ self.ms_supervision = True
+ self.out_ref = self.ms_supervision and True
+ self.dec_ipt = True
+ self.dec_ipt_split = True
+ self.cxt_num = [0, 3][1] # multi-scale skip connections from encoder
+ self.mul_scl_ipt = ['', 'add', 'cat'][2]
+ self.dec_att = ['', 'ASPP', 'ASPPDeformable'][2]
+ self.squeeze_block = ['', 'BasicDecBlk_x1', 'ResBlk_x4', 'ASPP_x3', 'ASPPDeformable_x3'][1]
+ self.dec_blk = ['BasicDecBlk', 'ResBlk', 'HierarAttDecBlk'][0]
+
+ # TRAINING settings
+ self.batch_size = 4
+ self.IoU_finetune_last_epochs = [
+ 0,
+ {
+ 'DIS5K': -50,
+ 'COD': -20,
+ 'HRSOD': -20,
+ 'DIS5K+HRSOD+HRS10K': -20,
+ 'P3M-10k': -20,
+ }[self.task]
+ ][1] # choose 0 to skip
+ self.lr = (1e-4 if 'DIS5K' in self.task else 1e-5) * math.sqrt(self.batch_size / 4) # DIS needs high lr to converge faster. Adapt the lr linearly
+ self.size = 1024
+ self.num_workers = max(4, self.batch_size) # will be decrease to min(it, batch_size) at the initialization of the data_loader
+
+ # Backbone settings
+ self.bb = [
+ 'vgg16', 'vgg16bn', 'resnet50', # 0, 1, 2
+ 'swin_v1_t', 'swin_v1_s', # 3, 4
+ 'swin_v1_b', 'swin_v1_l', # 5-bs9, 6-bs4
+ 'pvt_v2_b0', 'pvt_v2_b1', # 7, 8
+ 'pvt_v2_b2', 'pvt_v2_b5', # 9-bs10, 10-bs5
+ ][6]
+ self.lateral_channels_in_collection = {
+ 'vgg16': [512, 256, 128, 64], 'vgg16bn': [512, 256, 128, 64], 'resnet50': [1024, 512, 256, 64],
+ 'pvt_v2_b2': [512, 320, 128, 64], 'pvt_v2_b5': [512, 320, 128, 64],
+ 'swin_v1_b': [1024, 512, 256, 128], 'swin_v1_l': [1536, 768, 384, 192],
+ 'swin_v1_t': [768, 384, 192, 96], 'swin_v1_s': [768, 384, 192, 96],
+ 'pvt_v2_b0': [256, 160, 64, 32], 'pvt_v2_b1': [512, 320, 128, 64],
+ }[self.bb]
+ if self.mul_scl_ipt == 'cat':
+ self.lateral_channels_in_collection = [channel * 2 for channel in self.lateral_channels_in_collection]
+ self.cxt = self.lateral_channels_in_collection[1:][::-1][-self.cxt_num:] if self.cxt_num else []
+
+ # MODEL settings - inactive
+ self.lat_blk = ['BasicLatBlk'][0]
+ self.dec_channels_inter = ['fixed', 'adap'][0]
+ self.refine = ['', 'itself', 'RefUNet', 'Refiner', 'RefinerPVTInChannels4'][0]
+ self.progressive_ref = self.refine and True
+ self.ender = self.progressive_ref and False
+ self.scale = self.progressive_ref and 2
+ self.auxiliary_classification = False # Only for DIS5K, where class labels are saved in `dataset.py`.
+ self.refine_iteration = 1
+ self.freeze_bb = False
+ self.model = [
+ 'BiRefNet',
+ ][0]
+ if self.dec_blk == 'HierarAttDecBlk':
+ self.batch_size = 2 ** [0, 1, 2, 3, 4][2]
+
+ # TRAINING settings - inactive
+ self.preproc_methods = ['flip', 'enhance', 'rotate', 'pepper', 'crop'][:4]
+ self.optimizer = ['Adam', 'AdamW'][1]
+ self.lr_decay_epochs = [1e5] # Set to negative N to decay the lr in the last N-th epoch.
+ self.lr_decay_rate = 0.5
+ # Loss
+ self.lambdas_pix_last = {
+ # not 0 means opening this loss
+ # original rate -- 1 : 30 : 1.5 : 0.2, bce x 30
+ 'bce': 30 * 1, # high performance
+ 'iou': 0.5 * 1, # 0 / 255
+ 'iou_patch': 0.5 * 0, # 0 / 255, win_size = (64, 64)
+ 'mse': 150 * 0, # can smooth the saliency map
+ 'triplet': 3 * 0,
+ 'reg': 100 * 0,
+ 'ssim': 10 * 1, # help contours,
+ 'cnt': 5 * 0, # help contours
+ 'structure': 5 * 0, # structure loss from codes of MVANet. A little improvement on DIS-TE[1,2,3], a bit more decrease on DIS-TE4.
+ }
+ self.lambdas_cls = {
+ 'ce': 5.0
+ }
+ # Adv
+ self.lambda_adv_g = 10. * 0 # turn to 0 to avoid adv training
+ self.lambda_adv_d = 3. * (self.lambda_adv_g > 0)
+
+ # PATH settings - inactive
+ self.data_root_dir = os.path.join(self.sys_home_dir, 'datasets/dis')
+ self.weights_root_dir = os.path.join(self.sys_home_dir, 'weights')
+ self.weights = {
+ 'pvt_v2_b2': os.path.join(self.weights_root_dir, 'pvt_v2_b2.pth'),
+ 'pvt_v2_b5': os.path.join(self.weights_root_dir, ['pvt_v2_b5.pth', 'pvt_v2_b5_22k.pth'][0]),
+ 'swin_v1_b': os.path.join(self.weights_root_dir, ['swin_base_patch4_window12_384_22kto1k.pth', 'swin_base_patch4_window12_384_22k.pth'][0]),
+ 'swin_v1_l': os.path.join(self.weights_root_dir, ['swin_large_patch4_window12_384_22kto1k.pth', 'swin_large_patch4_window12_384_22k.pth'][0]),
+ 'swin_v1_t': os.path.join(self.weights_root_dir, ['swin_tiny_patch4_window7_224_22kto1k_finetune.pth'][0]),
+ 'swin_v1_s': os.path.join(self.weights_root_dir, ['swin_small_patch4_window7_224_22kto1k_finetune.pth'][0]),
+ 'pvt_v2_b0': os.path.join(self.weights_root_dir, ['pvt_v2_b0.pth'][0]),
+ 'pvt_v2_b1': os.path.join(self.weights_root_dir, ['pvt_v2_b1.pth'][0]),
+ }
+
+ # Callbacks - inactive
+ self.verbose_eval = True
+ self.only_S_MAE = False
+ self.use_fp16 = False # Bugs. It may cause nan in training.
+ self.SDPA_enabled = False # Bugs. Slower and errors occur in multi-GPUs
+
+ # others
+ self.device = [0, 'cpu'][0] # .to(0) == .to('cuda:0')
+
+ self.batch_size_valid = 1
+ self.rand_seed = 7
+ # run_sh_file = [f for f in os.listdir('.') if 'train.sh' == f] + [os.path.join('..', f) for f in os.listdir('..') if 'train.sh' == f]
+ # with open(run_sh_file[0], 'r') as f:
+ # lines = f.readlines()
+ # self.save_last = int([l.strip() for l in lines if '"{}")'.format(self.task) in l and 'val_last=' in l][0].split('val_last=')[-1].split()[0])
+ # self.save_step = int([l.strip() for l in lines if '"{}")'.format(self.task) in l and 'step=' in l][0].split('step=')[-1].split()[0])
+ # self.val_step = [0, self.save_step][0]
\ No newline at end of file
diff --git a/nodes.py b/nodes.py
new file mode 100644
index 0000000..f99438b
--- /dev/null
+++ b/nodes.py
@@ -0,0 +1,95 @@
+from transformers import AutoModelForImageSegmentation
+import torch
+from torchvision import transforms
+import numpy as np
+from PIL import Image
+import torch.nn.functional as F
+from .config import Config
+
+Config()
+
+torch.set_float32_matmul_precision(["high", "highest"][0])
+
+birefnet = AutoModelForImageSegmentation.from_pretrained(
+ "ZhengPeng7/BiRefNet", trust_remote_code=True
+)
+
+birefnet.to("cuda")
+
+transform_image = transforms.Compose(
+ [
+ transforms.Resize((1024, 1024)),
+ transforms.ToTensor(),
+ transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]),
+ ]
+)
+
+def tensor2pil(image):
+ return Image.fromarray(np.clip(255. * image.cpu().numpy().squeeze(), 0, 255).astype(np.uint8))
+
+def pil2tensor(image):
+ return torch.from_numpy(np.array(image).astype(np.float32) / 255.0).unsqueeze(0)
+
+def resize_image(image):
+ image = image.convert('RGB')
+ model_input_size = (1024, 1024)
+ image = image.resize(model_input_size, Image.BILINEAR)
+ return image
+
+
+class BiRefNet_Hugo:
+ def __init__(self):
+ pass
+
+ @classmethod
+ def INPUT_TYPES(cls):
+ return {
+ "required": {
+ "image": ("IMAGE",),
+ }
+ }
+
+ RETURN_TYPES = ("IMAGE", "MASK",)
+ RETURN_NAMES = ("image", "mask",)
+ FUNCTION = "background_remove"
+ CATEGORY = "🔥BiRefNet"
+
+ def background_remove(self, image):
+ processed_images = []
+ processed_masks = []
+ for image in image:
+ orig_image = tensor2pil(image)
+ w,h = orig_image.size
+ image = resize_image(orig_image)
+ im_tensor = transform_image(image).unsqueeze(0)
+ if torch.cuda.is_available():
+ im_tensor=im_tensor.cuda()
+ with torch.no_grad():
+ result = birefnet(im_tensor)[-1].sigmoid().cpu()
+ result = torch.squeeze(F.interpolate(result, size=(h,w)))
+ ma = torch.max(result)
+ mi = torch.min(result)
+ result = (result-mi)/(ma-mi)
+ im_array = (result*255).cpu().data.numpy().astype(np.uint8)
+ pil_im = Image.fromarray(np.squeeze(im_array))
+ new_im = Image.new("RGBA", pil_im.size, (0,0,0,0))
+ new_im.paste(orig_image, mask=pil_im)
+ new_im_tensor = pil2tensor(new_im)
+ pil_im_tensor = pil2tensor(pil_im)
+ processed_images.append(new_im_tensor)
+ processed_masks.append(pil_im_tensor)
+
+ new_ims = torch.cat(processed_images, dim=0)
+ new_masks = torch.cat(processed_masks, dim=0)
+
+ return new_ims, new_masks
+
+
+NODE_CLASS_MAPPINGS = {
+ "BiRefNet_Hugo": BiRefNet_Hugo
+}
+
+# A dictionary that contains the friendly/humanly readable titles for the nodes
+NODE_DISPLAY_NAME_MAPPINGS = {
+ "BiRefNet_Hugo": "🔥BiRefNet"
+}
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..22380da
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,2 @@
+numpy
+timm
\ No newline at end of file
diff --git a/workflow/image.webp b/workflow/image.webp
new file mode 100644
index 0000000..73f818b
Binary files /dev/null and b/workflow/image.webp differ
diff --git a/workflow/video_workflow.json b/workflow/video_workflow.json
new file mode 100644
index 0000000..6ef5786
--- /dev/null
+++ b/workflow/video_workflow.json
@@ -0,0 +1,378 @@
+{
+ "last_node_id": 15,
+ "last_link_id": 16,
+ "nodes": [
+ {
+ "id": 11,
+ "type": "VHS_LoadVideo",
+ "pos": [
+ 840,
+ -90
+ ],
+ "size": [
+ 210,
+ 480
+ ],
+ "flags": {},
+ "order": 0,
+ "mode": 0,
+ "inputs": [
+ {
+ "name": "meta_batch",
+ "type": "VHS_BatchManager",
+ "link": null,
+ "label": "批次管理"
+ },
+ {
+ "name": "vae",
+ "type": "VAE",
+ "link": null
+ }
+ ],
+ "outputs": [
+ {
+ "name": "IMAGE",
+ "type": "IMAGE",
+ "links": [
+ 12
+ ],
+ "shape": 3,
+ "label": "图像",
+ "slot_index": 0
+ },
+ {
+ "name": "frame_count",
+ "type": "INT",
+ "links": null,
+ "shape": 3,
+ "label": "帧计数"
+ },
+ {
+ "name": "audio",
+ "type": "AUDIO",
+ "links": null,
+ "shape": 3,
+ "label": "音频"
+ },
+ {
+ "name": "video_info",
+ "type": "VHS_VIDEOINFO",
+ "links": null,
+ "shape": 3,
+ "label": "视频信息"
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "VHS_LoadVideo"
+ },
+ "widgets_values": {
+ "video": "6月28日(1).mp4",
+ "force_rate": 0,
+ "force_size": "Disabled",
+ "custom_width": 512,
+ "custom_height": 512,
+ "frame_load_cap": 0,
+ "skip_first_frames": 0,
+ "select_every_nth": 1,
+ "choose video to upload": "image",
+ "videopreview": {
+ "hidden": false,
+ "paused": false,
+ "params": {
+ "frame_load_cap": 0,
+ "skip_first_frames": 0,
+ "force_rate": 0,
+ "filename": "6月28日(1).mp4",
+ "type": "input",
+ "format": "video/mp4",
+ "select_every_nth": 1
+ },
+ "muted": false
+ }
+ }
+ },
+ {
+ "id": 1,
+ "type": "BiRefNet_Hugo",
+ "pos": [
+ 1110,
+ -60
+ ],
+ "size": {
+ "0": 210,
+ "1": 60
+ },
+ "flags": {},
+ "order": 1,
+ "mode": 0,
+ "inputs": [
+ {
+ "name": "image",
+ "type": "IMAGE",
+ "link": 12,
+ "slot_index": 0,
+ "label": "image"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "image",
+ "type": "IMAGE",
+ "links": [
+ 14
+ ],
+ "slot_index": 0,
+ "shape": 3,
+ "label": "image"
+ },
+ {
+ "name": "mask",
+ "type": "MASK",
+ "links": [
+ 15
+ ],
+ "slot_index": 1,
+ "shape": 3,
+ "label": "mask"
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "BiRefNet_Hugo"
+ }
+ },
+ {
+ "id": 14,
+ "type": "MaskToImage",
+ "pos": [
+ 1410,
+ 30
+ ],
+ "size": {
+ "0": 210,
+ "1": 30
+ },
+ "flags": {},
+ "order": 3,
+ "mode": 0,
+ "inputs": [
+ {
+ "name": "mask",
+ "type": "MASK",
+ "link": 15,
+ "label": "遮罩"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "IMAGE",
+ "type": "IMAGE",
+ "links": [
+ 16
+ ],
+ "shape": 3,
+ "label": "图像",
+ "slot_index": 0
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "MaskToImage"
+ }
+ },
+ {
+ "id": 15,
+ "type": "VHS_VideoCombine",
+ "pos": [
+ 1410,
+ 120
+ ],
+ "size": [
+ 360,
+ 660
+ ],
+ "flags": {},
+ "order": 4,
+ "mode": 0,
+ "inputs": [
+ {
+ "name": "images",
+ "type": "IMAGE",
+ "link": 16,
+ "label": "图像"
+ },
+ {
+ "name": "audio",
+ "type": "AUDIO",
+ "link": null,
+ "label": "音频"
+ },
+ {
+ "name": "meta_batch",
+ "type": "VHS_BatchManager",
+ "link": null,
+ "label": "批次管理"
+ },
+ {
+ "name": "vae",
+ "type": "VAE",
+ "link": null
+ }
+ ],
+ "outputs": [
+ {
+ "name": "Filenames",
+ "type": "VHS_FILENAMES",
+ "links": null,
+ "shape": 3,
+ "label": "文件名"
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "VHS_VideoCombine"
+ },
+ "widgets_values": {
+ "frame_rate": 30,
+ "loop_count": 0,
+ "filename_prefix": "AnimateDiff",
+ "format": "video/h265-mp4",
+ "pix_fmt": "yuv420p10le",
+ "crf": 22,
+ "save_metadata": true,
+ "pingpong": false,
+ "save_output": true,
+ "videopreview": {
+ "hidden": false,
+ "paused": false,
+ "params": {
+ "filename": "AnimateDiff_00005.mp4",
+ "subfolder": "",
+ "type": "output",
+ "format": "video/h265-mp4",
+ "frame_rate": 30
+ },
+ "muted": false
+ }
+ }
+ },
+ {
+ "id": 13,
+ "type": "VHS_VideoCombine",
+ "pos": [
+ 1830,
+ -180
+ ],
+ "size": [
+ 360,
+ 660
+ ],
+ "flags": {},
+ "order": 2,
+ "mode": 0,
+ "inputs": [
+ {
+ "name": "images",
+ "type": "IMAGE",
+ "link": 14,
+ "label": "图像"
+ },
+ {
+ "name": "audio",
+ "type": "AUDIO",
+ "link": null,
+ "label": "音频"
+ },
+ {
+ "name": "meta_batch",
+ "type": "VHS_BatchManager",
+ "link": null,
+ "label": "批次管理"
+ },
+ {
+ "name": "vae",
+ "type": "VAE",
+ "link": null
+ }
+ ],
+ "outputs": [
+ {
+ "name": "Filenames",
+ "type": "VHS_FILENAMES",
+ "links": null,
+ "shape": 3,
+ "label": "文件名"
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "VHS_VideoCombine"
+ },
+ "widgets_values": {
+ "frame_rate": 30,
+ "loop_count": 0,
+ "filename_prefix": "AnimateDiff",
+ "format": "video/h265-mp4",
+ "pix_fmt": "yuv420p10le",
+ "crf": 22,
+ "save_metadata": true,
+ "pingpong": false,
+ "save_output": true,
+ "videopreview": {
+ "hidden": false,
+ "paused": false,
+ "params": {
+ "filename": "AnimateDiff_00004.mp4",
+ "subfolder": "",
+ "type": "output",
+ "format": "video/h265-mp4",
+ "frame_rate": 30
+ },
+ "muted": false
+ }
+ }
+ }
+ ],
+ "links": [
+ [
+ 12,
+ 11,
+ 0,
+ 1,
+ 0,
+ "IMAGE"
+ ],
+ [
+ 14,
+ 1,
+ 0,
+ 13,
+ 0,
+ "IMAGE"
+ ],
+ [
+ 15,
+ 1,
+ 1,
+ 14,
+ 0,
+ "MASK"
+ ],
+ [
+ 16,
+ 14,
+ 0,
+ 15,
+ 0,
+ "IMAGE"
+ ]
+ ],
+ "groups": [],
+ "config": {},
+ "extra": {
+ "ds": {
+ "scale": 0.8390545288824037,
+ "offset": [
+ -471.7394319558889,
+ 296.200180526101
+ ]
+ }
+ },
+ "version": 0.4
+}
\ No newline at end of file
diff --git a/workflow/workflow.json b/workflow/workflow.json
new file mode 100644
index 0000000..ed4f754
--- /dev/null
+++ b/workflow/workflow.json
@@ -0,0 +1,231 @@
+{
+ "last_node_id": 5,
+ "last_link_id": 4,
+ "nodes": [
+ {
+ "id": 1,
+ "type": "BiRefNet_Hugo",
+ "pos": [
+ 921,
+ 256
+ ],
+ "size": {
+ "0": 210,
+ "1": 46
+ },
+ "flags": {},
+ "order": 1,
+ "mode": 0,
+ "inputs": [
+ {
+ "name": "image",
+ "type": "IMAGE",
+ "link": 1,
+ "label": "image",
+ "slot_index": 0
+ }
+ ],
+ "outputs": [
+ {
+ "name": "image",
+ "type": "IMAGE",
+ "links": [
+ 2
+ ],
+ "shape": 3,
+ "label": "image",
+ "slot_index": 0
+ },
+ {
+ "name": "mask",
+ "type": "MASK",
+ "links": [
+ 3
+ ],
+ "shape": 3,
+ "label": "mask",
+ "slot_index": 1
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "BiRefNet_Hugo"
+ }
+ },
+ {
+ "id": 4,
+ "type": "MaskToImage",
+ "pos": [
+ 922,
+ 352
+ ],
+ "size": {
+ "0": 210,
+ "1": 26
+ },
+ "flags": {},
+ "order": 3,
+ "mode": 0,
+ "inputs": [
+ {
+ "name": "mask",
+ "type": "MASK",
+ "link": 3,
+ "label": "遮罩"
+ }
+ ],
+ "outputs": [
+ {
+ "name": "IMAGE",
+ "type": "IMAGE",
+ "links": [
+ 4
+ ],
+ "shape": 3,
+ "label": "图像",
+ "slot_index": 0
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "MaskToImage"
+ }
+ },
+ {
+ "id": 5,
+ "type": "PreviewImage",
+ "pos": [
+ 1299,
+ 410
+ ],
+ "size": [
+ 210,
+ 246
+ ],
+ "flags": {},
+ "order": 4,
+ "mode": 0,
+ "inputs": [
+ {
+ "name": "images",
+ "type": "IMAGE",
+ "link": 4,
+ "label": "图像"
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "PreviewImage"
+ }
+ },
+ {
+ "id": 3,
+ "type": "PreviewImage",
+ "pos": [
+ 1295,
+ 74
+ ],
+ "size": [
+ 210,
+ 246
+ ],
+ "flags": {},
+ "order": 2,
+ "mode": 0,
+ "inputs": [
+ {
+ "name": "images",
+ "type": "IMAGE",
+ "link": 2,
+ "label": "图像"
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "PreviewImage"
+ }
+ },
+ {
+ "id": 2,
+ "type": "LoadImage",
+ "pos": [
+ 561,
+ 254
+ ],
+ "size": [
+ 315,
+ 314
+ ],
+ "flags": {},
+ "order": 0,
+ "mode": 0,
+ "outputs": [
+ {
+ "name": "IMAGE",
+ "type": "IMAGE",
+ "links": [
+ 1
+ ],
+ "shape": 3,
+ "label": "图像"
+ },
+ {
+ "name": "MASK",
+ "type": "MASK",
+ "links": null,
+ "shape": 3,
+ "label": "遮罩"
+ }
+ ],
+ "properties": {
+ "Node name for S&R": "LoadImage"
+ },
+ "widgets_values": [
+ "image.webp",
+ "image"
+ ]
+ }
+ ],
+ "links": [
+ [
+ 1,
+ 2,
+ 0,
+ 1,
+ 0,
+ "IMAGE"
+ ],
+ [
+ 2,
+ 1,
+ 0,
+ 3,
+ 0,
+ "IMAGE"
+ ],
+ [
+ 3,
+ 1,
+ 1,
+ 4,
+ 0,
+ "MASK"
+ ],
+ [
+ 4,
+ 4,
+ 0,
+ 5,
+ 0,
+ "IMAGE"
+ ]
+ ],
+ "groups": [],
+ "config": {},
+ "extra": {
+ "ds": {
+ "scale": 1.2100000000000002,
+ "offset": [
+ -299.9616678351899,
+ 94.8424540865177
+ ]
+ }
+ },
+ "version": 0.4
+}
\ No newline at end of file