update workflow

This commit is contained in:
KBRASK
2025-08-17 11:54:01 +08:00
parent e409c9ea13
commit feb48d12c6
2 changed files with 151 additions and 106 deletions
+146 -98
View File
@@ -1,8 +1,8 @@
{
"id": "206247b6-9fec-4ed2-8927-e4f388c674d4",
"revision": 0,
"last_node_id": 142,
"last_link_id": 251,
"last_node_id": 145,
"last_link_id": 254,
"nodes": [
{
"id": 50,
@@ -16,7 +16,7 @@
200
],
"flags": {},
"order": 17,
"order": 18,
"mode": 2,
"inputs": [
{
@@ -56,7 +56,7 @@
200
],
"flags": {},
"order": 16,
"order": 17,
"mode": 2,
"inputs": [
{
@@ -202,7 +202,7 @@
46
],
"flags": {},
"order": 26,
"order": 27,
"mode": 0,
"inputs": [
{
@@ -289,7 +289,7 @@
198
],
"flags": {},
"order": 32,
"order": 33,
"mode": 0,
"inputs": [
{
@@ -406,7 +406,7 @@
46
],
"flags": {},
"order": 29,
"order": 30,
"mode": 0,
"inputs": [
{
@@ -502,7 +502,7 @@
274
],
"flags": {},
"order": 19,
"order": 20,
"mode": 0,
"inputs": [
{
@@ -588,7 +588,7 @@
"flags": {
"collapsed": true
},
"order": 21,
"order": 22,
"mode": 2,
"inputs": [
{
@@ -629,7 +629,7 @@
246
],
"flags": {},
"order": 22,
"order": 23,
"mode": 0,
"inputs": [
{
@@ -727,7 +727,7 @@
57.857322692871094
],
"flags": {},
"order": 30,
"order": 31,
"mode": 0,
"inputs": [
{
@@ -769,7 +769,7 @@
873.39453125
],
"flags": {},
"order": 31,
"order": 32,
"mode": 0,
"inputs": [
{
@@ -871,6 +871,15 @@
"shape": 7,
"type": "FREEINITARGS",
"link": null
},
{
"name": "denoise_strength",
"shape": 7,
"type": "FLOAT",
"widget": {
"name": "denoise_strength"
},
"link": 252
}
],
"outputs": [
@@ -963,7 +972,7 @@
355.67169189453125
],
"flags": {},
"order": 25,
"order": 26,
"mode": 0,
"inputs": [
{
@@ -1050,7 +1059,7 @@
198
],
"flags": {},
"order": 18,
"order": 19,
"mode": 0,
"inputs": [
{
@@ -1095,58 +1104,6 @@
false
]
},
{
"id": 138,
"type": "VideoInputPreprocessor",
"pos": [
-274.0709533691406,
247.68026733398438
],
"size": [
306.6597595214844,
194
],
"flags": {},
"order": 24,
"mode": 0,
"inputs": [
{
"name": "face_processor",
"type": "FACE_PROCESSOR",
"link": 242
},
{
"name": "images",
"type": "IMAGE",
"link": 244
},
{
"name": "face_rgba",
"type": "IMAGE",
"link": 243
}
],
"outputs": [
{
"name": "processed_images",
"type": "IMAGE",
"links": [
245
]
}
],
"properties": {
"aux_id": "WeChatCV/Stand-In_Preprocessor_ComfyUI",
"ver": "db0d3d966dada4c5c242f9da5287988b533120e4",
"Node name for S&R": "VideoInputPreprocessor"
},
"widgets_values": [
0.5,
1.5,
10,
true
]
},
{
"id": 134,
"type": "WanVideoEncode",
@@ -1159,7 +1116,7 @@
242
],
"flags": {},
"order": 28,
"order": 29,
"mode": 0,
"inputs": [
{
@@ -1215,7 +1172,7 @@
150
],
"flags": {},
"order": 33,
"order": 34,
"mode": 0,
"inputs": [
{
@@ -1261,7 +1218,7 @@
334
],
"flags": {},
"order": 34,
"order": 35,
"mode": 0,
"inputs": [
{
@@ -1338,7 +1295,7 @@
242
],
"flags": {},
"order": 23,
"order": 24,
"mode": 0,
"inputs": [
{
@@ -1443,7 +1400,7 @@
126
],
"flags": {},
"order": 27,
"order": 28,
"mode": 0,
"inputs": [
{
@@ -1630,29 +1587,6 @@
}
}
},
{
"id": 126,
"type": "MarkdownNote",
"pos": [
-286.70123291015625,
-406.58197021484375
],
"size": [
362.6117858886719,
143.0945281982422
],
"flags": {},
"order": 15,
"mode": 0,
"inputs": [],
"outputs": [],
"properties": {},
"widgets_values": [
"LoRA link:\n\n[https://huggingface.co/BowenXue/Stand-In](https://huggingface.co/BowenXue/Stand-In)\n\nThis LoRA is not the traditional kind and it HAS TO connect to the model loader directly."
],
"color": "#432",
"bgcolor": "#653"
},
{
"id": 142,
"type": "VHS_VideoInfo",
@@ -1665,7 +1599,7 @@
206
],
"flags": {},
"order": 20,
"order": 21,
"mode": 0,
"inputs": [
{
@@ -1736,6 +1670,112 @@
"Node name for S&R": "VHS_VideoInfo"
},
"widgets_values": {}
},
{
"id": 126,
"type": "MarkdownNote",
"pos": [
-286.70123291015625,
-406.58197021484375
],
"size": [
362.6117858886719,
143.0945281982422
],
"flags": {},
"order": 15,
"mode": 0,
"inputs": [],
"outputs": [],
"properties": {},
"widgets_values": [
"LoRA link:\n\n[https://huggingface.co/BowenXue/Stand-In](https://huggingface.co/BowenXue/Stand-In)\n\nThis LoRA is not the traditional kind and it HAS TO connect to the model loader directly."
],
"color": "#432",
"bgcolor": "#653"
},
{
"id": 143,
"type": "MarkdownNote",
"pos": [
-270.9808044433594,
479.54229736328125
],
"size": [
300,
240
],
"flags": {},
"order": 16,
"mode": 0,
"inputs": [],
"outputs": [],
"properties": {},
"widgets_values": [
"## **With a higher denoise strength, the face blends better with the background, but the background changes slightly more. With a lower denoise strength, the background changes less. You can adjust it according to your needs.**\n"
],
"color": "#432",
"bgcolor": "#653"
},
{
"id": 138,
"type": "VideoInputPreprocessor",
"pos": [
-274.0709533691406,
247.68026733398438
],
"size": [
306.6597595214844,
194
],
"flags": {},
"order": 25,
"mode": 0,
"inputs": [
{
"name": "face_processor",
"type": "FACE_PROCESSOR",
"link": 242
},
{
"name": "images",
"type": "IMAGE",
"link": 244
},
{
"name": "face_rgba",
"type": "IMAGE",
"link": 243
}
],
"outputs": [
{
"name": "processed_images",
"type": "IMAGE",
"links": [
245
]
},
{
"name": "denoise_strength",
"type": "FLOAT",
"links": [
252
]
}
],
"properties": {
"aux_id": "WeChatCV/Stand-In_Preprocessor_ComfyUI",
"ver": "db0d3d966dada4c5c242f9da5287988b533120e4",
"Node name for S&R": "VideoInputPreprocessor"
},
"widgets_values": [
0.5,
0.5,
1.5,
10,
true
]
}
],
"links": [
@@ -2034,6 +2074,14 @@
103,
3,
"INT"
],
[
252,
138,
1,
27,
17,
"FLOAT"
]
],
"groups": [
@@ -2054,10 +2102,10 @@
"config": {},
"extra": {
"ds": {
"scale": 0.6115909044841601,
"scale": 0.8140274938684186,
"offset": [
1552.3325791014386,
871.5007309079728
1354.2272102810791,
250.24273344699088
]
},
"frontendVersion": "1.24.4",
+5 -8
View File
@@ -28,6 +28,7 @@ class VideoInputPreprocessor:
"face_processor": ("FACE_PROCESSOR",),
"images": ("IMAGE",),
"face_rgba": ("IMAGE",),
"denoise_strength": ("FLOAT", {"default": 0.5, "min": 0.1, "max": 1.0, "step": 0.01}),
"confidence_threshold": ("FLOAT", {"default": 0.5, "min": 0.1, "max": 1.0, "step": 0.05}),
"face_crop_scale": ("FLOAT", {"default": 1.5, "min": 1.0, "max": 3.0, "step": 0.1}),
"dilation_kernel_size": ("INT", {"default": 10, "min": 0, "max": 50, "step": 1}),
@@ -35,12 +36,12 @@ class VideoInputPreprocessor:
}
}
RETURN_TYPES = ("IMAGE",)
RETURN_NAMES = ("processed_images",)
RETURN_TYPES = ("IMAGE", "FLOAT")
RETURN_NAMES = ("processed_images", "denoise_strength")
FUNCTION = "generate_mask_and_paste"
CATEGORY = "Stand-In"
def generate_mask_and_paste(self, face_processor, images: torch.Tensor, face_rgba: torch.Tensor, confidence_threshold: float, face_crop_scale: float, dilation_kernel_size: int, with_neck: bool):
def generate_mask_and_paste(self, face_processor, images: torch.Tensor, face_rgba: torch.Tensor, denoise_strength: float, confidence_threshold: float, face_crop_scale: float, dilation_kernel_size: int, with_neck: bool):
detection_model, parsing_model, device = face_processor
total_frames, h, w = images.shape[0], images.shape[1], images.shape[2]
@@ -59,7 +60,6 @@ class VideoInputPreprocessor:
frame_tensor = images[i]
frame_bgr = tensor_to_cv2_img(frame_tensor)
# --- 1. Generate Face Mask (same logic as before) ---
results = detection_model(frame_bgr, verbose=False)
confident_boxes = results[0].boxes.xyxy[results[0].boxes.conf > confidence_threshold]
@@ -101,11 +101,8 @@ class VideoInputPreprocessor:
mask_resized_to_crop = cv2.resize(final_mask_512, (face_crop_bgr.shape[1], face_crop_bgr.shape[0]), interpolation=cv2.INTER_NEAREST)
full_mask_np[crop_y1:crop_y2, crop_x1:crop_x2] = mask_resized_to_crop
# --- 2. Paste Image onto Frame ---
# Use a copy to avoid modifying the original data
target_frame_pil = tensor_to_pil(frame_tensor).copy()
# Find the bounding box of the largest contour in the mask
if confident_boxes.shape[0] > 0 and 'face_crop_bgr' in locals() and face_crop_bgr.size > 0:
x = crop_x1
@@ -125,7 +122,7 @@ class VideoInputPreprocessor:
output_image_batch = torch.stack(processed_frames_tensors)
return (output_image_batch,)
return (output_image_batch,denoise_strength)
NODE_CLASS_MAPPINGS = {
"VideoInputPreprocessor": VideoInputPreprocessor,