diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..78dfaa8 --- /dev/null +++ b/__init__.py @@ -0,0 +1,37 @@ +import logging +import os + +log_level = os.getenv("LOG_LEVEL", "INFO").upper() +logging.basicConfig( + level=getattr(logging, log_level, logging.INFO), + format="%(asctime)s - %(name)s - %(levelname)s - %(message)s" +) +logger = logging.getLogger(__name__) + +NODE_PACK_NAME = "Stand-In" +logger.info("=" * 40 + f" {NODE_PACK_NAME} " + "=" * 40) + +NODE_CLASS_MAPPINGS = {} +NODE_DISPLAY_NAME_MAPPINGS = {} + +try: + from .nodes import FaceProcessorLoader, ApplyFaceProcessor + + # Map the class names to the classes themselves + NODE_CLASS_MAPPINGS["FaceProcessorLoader"] = FaceProcessorLoader + NODE_CLASS_MAPPINGS["ApplyFaceProcessor"] = ApplyFaceProcessor + + NODE_DISPLAY_NAME_MAPPINGS["FaceProcessorLoader"] = "Stand-In Processor Loader" + NODE_DISPLAY_NAME_MAPPINGS["ApplyFaceProcessor"] = "Apply Stand-In Processor" + + logger.info("Successfully loaded all Stand-In nodes.") + +except ImportError: + logger.exception(f"Failed to import nodes for {NODE_PACK_NAME}. Please ensure all dependencies are installed.") +except Exception as e: + logger.exception(f"An unexpected error occurred while loading nodes for {NODE_PACK_NAME}: {e}") + +__all__ = ["NODE_CLASS_MAPPINGS", "NODE_DISPLAY_NAME_MAPPINGS"] + +# --- Footer Banner --- +logger.info("=" * (82 + len(NODE_PACK_NAME))) \ No newline at end of file diff --git a/Stand-In_preprocessor.py b/nodes.py similarity index 90% rename from Stand-In_preprocessor.py rename to nodes.py index 2cba3cd..884da6a 100644 --- a/Stand-In_preprocessor.py +++ b/nodes.py @@ -5,16 +5,13 @@ import torch import numpy as np import PIL.Image import PIL.ImageOps -# The ultralytics library is required for YOLOv8. Install with: pip install ultralytics from ultralytics import YOLO from facexlib.parsing import init_parsing_model from torchvision.transforms.functional import normalize from typing import Union, Optional import folder_paths -# This code now requires the 'ultralytics' package. -# Please install it via pip: -# pip install ultralytics + LOADED_PROCESSORS = {} @@ -32,7 +29,6 @@ def set_extra_config_model_path(extra_config_models_dir_key, models_dir_name: st else: folder_paths.add_model_folder_path(extra_config_models_dir_key, models_dir_default, is_default=True) -# Set up paths for YOLO and face parsing models set_extra_config_model_path("yolo", "yolo") set_extra_config_model_path("face_parsing", "face_parsing") @@ -41,12 +37,10 @@ def download_yolo_model(model_name="model.pt"): """ Checks if a YOLO model exists and downloads it from a public source if not. """ - # Publicly accessible model URL model_url = f"https://huggingface.co/arnabdhar/YOLOv8-Face-Detection/resolve/main/{model_name}" yolo_dir = os.path.join(folder_paths.get_folder_paths("yolo")[0]) model_path = os.path.join(yolo_dir, model_name) - # Ensure the target directory exists os.makedirs(yolo_dir, exist_ok=True) if not os.path.exists(model_path): @@ -64,7 +58,6 @@ def download_yolo_model(model_name="model.pt"): for chunk in r.iter_content(chunk_size=8192): f.write(chunk) downloaded += len(chunk) - # Simple progress bar done = int(50 * downloaded / total_size) if total_size > 0 else 0 progress_mb = downloaded / (1024*1024) total_mb = total_size / (1024*1024) @@ -72,16 +65,11 @@ def download_yolo_model(model_name="model.pt"): print(f"\nModel successfully downloaded to: {model_path}") except Exception as e: print(f"\nFailed to download model: {e}") - print("Please check your internet connection or try downloading the model manually from:") - print(model_url) - print(f"And place it in the '{yolo_dir}' directory.") - # Clean up incomplete file if download failed if os.path.exists(model_path): os.remove(model_path) raise e return model_path -# --- Utility Functions --- def _img2tensor(img: np.ndarray, bgr2rgb: bool = True) -> torch.Tensor: if bgr2rgb: @@ -141,7 +129,6 @@ class FaceProcessorLoader: if not yolo_model_name.endswith(('.pt', '.onnx')): raise ValueError(f"Invalid model name: '{yolo_model_name}'. Model filename must end with '.pt' or '.onnx'.") - # Call the download function to ensure the model file exists model_path = download_yolo_model(yolo_model_name) print(f"Loading YOLO model from local path: {model_path}") @@ -176,14 +163,16 @@ class ApplyFaceProcessor: "border_thresh": ("INT", {"default": 10, "min": 0, "max": 100, "step": 1}), "face_crop_scale": ("FLOAT", {"default": 1.5, "min": 1.0, "max": 3.0, "step": 0.1}), "confidence_threshold": ("FLOAT", {"default": 0.5, "min": 0.1, "max": 1.0, "step": 0.05}), + # --- NEW INPUT --- + "with_neck": ("BOOLEAN", {"default": False, "label_on": "enabled", "label_off": "disabled"}), } } RETURN_TYPES = ("IMAGE",) FUNCTION = "apply_processing" - CATEGORY = "FaceUtils" + CATEGORY = "Stand-In" - def apply_processing(self, face_processor, image, resize_to, border_thresh, face_crop_scale, confidence_threshold): + def apply_processing(self, face_processor, image, resize_to, border_thresh, face_crop_scale, confidence_threshold, with_neck): detection_model, parsing_model, device = face_processor frame = tensor_to_cv2_img(image) @@ -228,12 +217,18 @@ class ApplyFaceProcessor: with torch.no_grad(): normalized_face = normalize(face_tensor, [0.5, 0.5, 0.5], [0.5, 0.5, 0.5]) parsing_out = parsing_model(normalized_face)[0] - parsing_mask = parsing_out.argmax(dim=1, keepdim=True) + parsing_map_tensor = parsing_out.argmax(dim=1, keepdim=True) - mask = (parsing_mask.squeeze().cpu().numpy() != 0).astype(np.uint8) + parsing_map_np = parsing_map_tensor.squeeze().cpu().numpy().astype(np.uint8) + + if with_neck: + final_mask_np = (parsing_map_np != 0).astype(np.uint8) + else: + parts_to_remove = [0, 14, 16] + final_mask_np = np.isin(parsing_map_np, parts_to_remove, invert=True).astype(np.uint8) white_background = np.ones_like(image_resized, dtype=np.uint8) * 255 - mask_3channel = cv2.cvtColor(mask * 255, cv2.COLOR_GRAY2BGR) + mask_3channel = cv2.cvtColor(final_mask_np * 255, cv2.COLOR_GRAY2BGR) result_img_bgr = np.where(mask_3channel != 0, image_resized, white_background) @@ -250,4 +245,4 @@ NODE_CLASS_MAPPINGS = { NODE_DISPLAY_NAME_MAPPINGS = { "FaceProcessorLoader": "Stand-In Processor Loader", "ApplyFaceProcessor": "Apply Stand-In Processor" -} +} \ No newline at end of file diff --git a/wanvideo_Stand-In_reference_example.json b/wanvideo_Stand-In_reference_example.json index e995d73..7c7e7c6 100644 --- a/wanvideo_Stand-In_reference_example.json +++ b/wanvideo_Stand-In_reference_example.json @@ -1,8 +1,8 @@ { "id": "206247b6-9fec-4ed2-8927-e4f388c674d4", "revision": 0, - "last_node_id": 129, - "last_link_id": 229, + "last_node_id": 130, + "last_link_id": 231, "nodes": [ { "id": 50, @@ -235,159 +235,6 @@ "color": "#223", "bgcolor": "#335" }, - { - "id": 27, - "type": "WanVideoSampler", - "pos": [ - 1434.9656982421875, - -536.9714965820312 - ], - "size": [ - 315, - 873.39453125 - ], - "flags": {}, - "order": 29, - "mode": 0, - "inputs": [ - { - "name": "model", - "type": "WANVIDEOMODEL", - "link": 108 - }, - { - "name": "image_embeds", - "type": "WANVIDIMAGE_EMBEDS", - "link": 172 - }, - { - "name": "text_embeds", - "shape": 7, - "type": "WANVIDEOTEXTEMBEDS", - "link": 30 - }, - { - "name": "samples", - "shape": 7, - "type": "LATENT", - "link": null - }, - { - "name": "feta_args", - "shape": 7, - "type": "FETAARGS", - "link": null - }, - { - "name": "context_options", - "shape": 7, - "type": "WANVIDCONTEXT", - "link": null - }, - { - "name": "cache_args", - "shape": 7, - "type": "CACHEARGS", - "link": null - }, - { - "name": "flowedit_args", - "shape": 7, - "type": "FLOWEDITARGS", - "link": null - }, - { - "name": "slg_args", - "shape": 7, - "type": "SLGARGS", - "link": null - }, - { - "name": "loop_args", - "shape": 7, - "type": "LOOPARGS", - "link": null - }, - { - "name": "experimental_args", - "shape": 7, - "type": "EXPERIMENTALARGS", - "link": null - }, - { - "name": "sigmas", - "shape": 7, - "type": "SIGMAS", - "link": null - }, - { - "name": "unianimate_poses", - "shape": 7, - "type": "UNIANIMATE_POSE", - "link": null - }, - { - "name": "fantasytalking_embeds", - "shape": 7, - "type": "FANTASYTALKING_EMBEDS", - "link": null - }, - { - "name": "uni3c_embeds", - "shape": 7, - "type": "UNI3C_EMBEDS", - "link": null - }, - { - "name": "multitalk_embeds", - "shape": 7, - "type": "MULTITALK_EMBEDS", - "link": null - }, - { - "name": "freeinit_args", - "shape": 7, - "type": "FREEINITARGS", - "link": null - } - ], - "outputs": [ - { - "name": "samples", - "type": "LATENT", - "slot_index": 0, - "links": [ - 33 - ] - }, - { - "name": "denoised_samples", - "type": "LATENT", - "links": null - } - ], - "properties": { - "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "d9b1f4d1a5aea91d101ae97a54714a5861af3f50", - "Node name for S&R": "WanVideoSampler" - }, - "widgets_values": [ - 4, - 1, - 5, - 44, - "fixed", - true, - "dpm++_sde", - 0, - 1, - "", - "comfy", - 0, - -1, - false - ] - }, { "id": 35, "type": "WanVideoTorchCompileSettings", @@ -778,62 +625,6 @@ "color": "#2a363b", "bgcolor": "#3f5159" }, - { - "id": 104, - "type": "WanVideoEncode", - "pos": [ - 193.28677368164062, - -85.77310180664062 - ], - "size": [ - 270, - 242 - ], - "flags": {}, - "order": 26, - "mode": 0, - "inputs": [ - { - "name": "vae", - "type": "WANVAE", - "link": 175 - }, - { - "name": "image", - "type": "IMAGE", - "link": 228 - }, - { - "name": "mask", - "shape": 7, - "type": "MASK", - "link": null - } - ], - "outputs": [ - { - "name": "samples", - "type": "LATENT", - "links": [ - 174 - ] - } - ], - "properties": { - "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "06863fe2d283e89ba2386260ad2700557dda1897", - "Node name for S&R": "WanVideoEncode" - }, - "widgets_values": [ - false, - 272, - 272, - 144, - 128, - 0, - 1 - ] - }, { "id": 38, "type": "WanVideoVAELoader", @@ -1144,6 +935,124 @@ "color": "#223", "bgcolor": "#335" }, + { + "id": 46, + "type": "WanVideoTextEmbedBridge", + "pos": [ + 943.1697387695312, + 1096.8651123046875 + ], + "size": [ + 315, + 46 + ], + "flags": { + "collapsed": true + }, + "order": 22, + "mode": 2, + "inputs": [ + { + "name": "positive", + "type": "CONDITIONING", + "link": 54 + }, + { + "name": "negative", + "shape": 7, + "type": "CONDITIONING", + "link": 55 + } + ], + "outputs": [ + { + "name": "text_embeds", + "type": "WANVIDEOTEXTEMBEDS", + "links": null + } + ], + "properties": { + "cnr_id": "ComfyUI-WanVideoWrapper", + "ver": "d9b1f4d1a5aea91d101ae97a54714a5861af3f50", + "Node name for S&R": "WanVideoTextEmbedBridge" + }, + "widgets_values": [] + }, + { + "id": 126, + "type": "MarkdownNote", + "pos": [ + -653.9163818359375, + -382.01556396484375 + ], + "size": [ + 362.6117858886719, + 143.0945281982422 + ], + "flags": {}, + "order": 13, + "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": 121, + "type": "PreviewImage", + "pos": [ + 37.458839416503906, + -72.97832489013672 + ], + "size": [ + 140, + 246 + ], + "flags": {}, + "order": 25, + "mode": 0, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 227 + } + ], + "outputs": [], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.49", + "Node name for S&R": "PreviewImage" + }, + "widgets_values": [] + }, + { + "id": 129, + "type": "MarkdownNote", + "pos": [ + 791.3861694335938, + -356.8863830566406 + ], + "size": [ + 362.6117858886719, + 143.0945281982422 + ], + "flags": {}, + "order": 14, + "mode": 0, + "inputs": [], + "outputs": [], + "properties": {}, + "widgets_values": [ + "Prompt Writing Tip: If you do not wish to alter the subject's facial features, simply use \"a man\" or \"a woman\" without adding extra descriptions of their appearance. Prompts support both Chinese and English input. The prompt is intended for generating frontal, medium-to-close-up videos.\n\nInput Image Recommendation: For best results, use a high-resolution frontal face image. There are no restrictions on resolution or file extension, as our built-in preprocessing pipeline will handle them automatically.\n\n[https://github.com/WeChatCV/Stand-In](https://github.com/WeChatCV/Stand-In)" + ], + "color": "#322", + "bgcolor": "#533" + }, { "id": 16, "type": "WanVideoTextEncode", @@ -1188,7 +1097,7 @@ "Node name for S&R": "WanVideoTextEncode" }, "widgets_values": [ - "一位男性舒适地坐在书桌前,正对着镜头,仿佛在与屏幕前的亲友对话。他的眼神专注而温柔,嘴角带着自然的笑意。背景是他精心布置的个人空间,墙上贴着照片和一张世界地图,传达出一种亲密而现代的沟通感。", + "一位男性舒适地坐在书桌前,正对着镜头,仿佛在与屏幕前的亲友对话。他的眼神专注而温柔,嘴角带着自然的笑意。背景是他精心布置的个人空间,墙上贴着照片和一张世界地图,传达出一种亲密而现代的沟通感", "色调艳丽,过曝,静态,细节模糊不清,字幕,风格,作品,画作,画面,静止,整体发灰,最差质量,低质量,JPEG压缩残留,丑陋的,残缺的,多余的手指,画得不好的手部,画得不好的脸部,畸形的,毁容的,形态畸形的肢体,手指融合,静止不动的画面,杂乱的背景,三条腿,背景人很多,倒着走", true, false, @@ -1197,6 +1106,200 @@ "color": "#332922", "bgcolor": "#593930" }, + { + "id": 27, + "type": "WanVideoSampler", + "pos": [ + 1434.9656982421875, + -536.9714965820312 + ], + "size": [ + 315, + 873.39453125 + ], + "flags": {}, + "order": 29, + "mode": 0, + "inputs": [ + { + "name": "model", + "type": "WANVIDEOMODEL", + "link": 108 + }, + { + "name": "image_embeds", + "type": "WANVIDIMAGE_EMBEDS", + "link": 172 + }, + { + "name": "text_embeds", + "shape": 7, + "type": "WANVIDEOTEXTEMBEDS", + "link": 30 + }, + { + "name": "samples", + "shape": 7, + "type": "LATENT", + "link": null + }, + { + "name": "feta_args", + "shape": 7, + "type": "FETAARGS", + "link": null + }, + { + "name": "context_options", + "shape": 7, + "type": "WANVIDCONTEXT", + "link": null + }, + { + "name": "cache_args", + "shape": 7, + "type": "CACHEARGS", + "link": null + }, + { + "name": "flowedit_args", + "shape": 7, + "type": "FLOWEDITARGS", + "link": null + }, + { + "name": "slg_args", + "shape": 7, + "type": "SLGARGS", + "link": null + }, + { + "name": "loop_args", + "shape": 7, + "type": "LOOPARGS", + "link": null + }, + { + "name": "experimental_args", + "shape": 7, + "type": "EXPERIMENTALARGS", + "link": null + }, + { + "name": "sigmas", + "shape": 7, + "type": "SIGMAS", + "link": null + }, + { + "name": "unianimate_poses", + "shape": 7, + "type": "UNIANIMATE_POSE", + "link": null + }, + { + "name": "fantasytalking_embeds", + "shape": 7, + "type": "FANTASYTALKING_EMBEDS", + "link": null + }, + { + "name": "uni3c_embeds", + "shape": 7, + "type": "UNI3C_EMBEDS", + "link": null + }, + { + "name": "multitalk_embeds", + "shape": 7, + "type": "MULTITALK_EMBEDS", + "link": null + }, + { + "name": "freeinit_args", + "shape": 7, + "type": "FREEINITARGS", + "link": null + } + ], + "outputs": [ + { + "name": "samples", + "type": "LATENT", + "slot_index": 0, + "links": [ + 33 + ] + }, + { + "name": "denoised_samples", + "type": "LATENT", + "links": null + } + ], + "properties": { + "cnr_id": "ComfyUI-WanVideoWrapper", + "ver": "d9b1f4d1a5aea91d101ae97a54714a5861af3f50", + "Node name for S&R": "WanVideoSampler" + }, + "widgets_values": [ + 4, + 1, + 5, + 44, + "fixed", + true, + "dpm++_sde", + 0, + 1, + "", + "comfy", + 0, + -1, + false + ] + }, + { + "id": 58, + "type": "LoadImage", + "pos": [ + -737.1319580078125, + -174.04302978515625 + ], + "size": [ + 413.10479736328125, + 498.3180847167969 + ], + "flags": {}, + "order": 15, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 226 + ] + }, + { + "name": "MASK", + "type": "MASK", + "links": [] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.26", + "Node name for S&R": "LoadImage" + }, + "widgets_values": [ + "GettyImages-540680934-thumb.webp", + "image" + ], + "color": "#2a363b", + "bgcolor": "#3f5159" + }, { "id": 74, "type": "VHS_VideoCombine", @@ -1206,7 +1309,7 @@ ], "size": [ 959.076171875, - 691.564453125 + 334 ], "flags": {}, "order": 32, @@ -1275,58 +1378,102 @@ } }, { - "id": 46, - "type": "WanVideoTextEmbedBridge", + "id": 104, + "type": "WanVideoEncode", "pos": [ - 943.1697387695312, - 1096.8651123046875 + 185.17897033691406, + -134.4200897216797 ], "size": [ - 315, - 46 + 270, + 242 ], - "flags": { - "collapsed": true - }, - "order": 22, - "mode": 2, + "flags": {}, + "order": 26, + "mode": 0, "inputs": [ { - "name": "positive", - "type": "CONDITIONING", - "link": 54 + "name": "vae", + "type": "WANVAE", + "link": 175 }, { - "name": "negative", + "name": "image", + "type": "IMAGE", + "link": 231 + }, + { + "name": "mask", "shape": 7, - "type": "CONDITIONING", - "link": 55 + "type": "MASK", + "link": null } ], "outputs": [ { - "name": "text_embeds", - "type": "WANVIDEOTEXTEMBEDS", - "links": null + "name": "samples", + "type": "LATENT", + "links": [ + 174 + ] } ], "properties": { "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "d9b1f4d1a5aea91d101ae97a54714a5861af3f50", - "Node name for S&R": "WanVideoTextEmbedBridge" + "ver": "06863fe2d283e89ba2386260ad2700557dda1897", + "Node name for S&R": "WanVideoEncode" }, - "widgets_values": [] + "widgets_values": [ + false, + 272, + 272, + 144, + 128, + 0, + 1 + ] + }, + { + "id": 130, + "type": "FaceProcessorLoader", + "pos": [ + -299.8837890625, + 128.56805419921875 + ], + "size": [ + 319.3335876464844, + 58 + ], + "flags": {}, + "order": 16, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "face_processor", + "type": "FACE_PROCESSOR", + "links": [ + 230 + ] + } + ], + "properties": { + "Node name for S&R": "FaceProcessorLoader" + }, + "widgets_values": [ + "model.pt" + ] }, { "id": 128, "type": "ApplyFaceProcessor", "pos": [ - -297.2541198730469, - -77.13932037353516 + -258.21417236328125, + -111.67808532714844 ], "size": [ 270, - 126 + 174 ], "flags": {}, "order": 21, @@ -1335,7 +1482,7 @@ { "name": "face_processor", "type": "FACE_PROCESSOR", - "link": 223 + "link": 230 }, { "name": "image", @@ -1349,8 +1496,8 @@ "type": "IMAGE", "links": [ 227, - 228, - 229 + 229, + 231 ] } ], @@ -1360,155 +1507,10 @@ "widgets_values": [ 512, 10, - 1.5 + 1.5, + 0.5, + false ] - }, - { - "id": 127, - "type": "FaceProcessorLoader", - "pos": [ - -294.2811279296875, - 107.27786254882812 - ], - "size": [ - 270, - 58 - ], - "flags": {}, - "order": 13, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "face_processor", - "type": "FACE_PROCESSOR", - "links": [ - 223 - ] - } - ], - "properties": { - "Node name for S&R": "FaceProcessorLoader" - }, - "widgets_values": [ - "models/insightface" - ] - }, - { - "id": 126, - "type": "MarkdownNote", - "pos": [ - -653.9163818359375, - -382.01556396484375 - ], - "size": [ - 362.6117858886719, - 143.0945281982422 - ], - "flags": {}, - "order": 14, - "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": 121, - "type": "PreviewImage", - "pos": [ - 37.458839416503906, - -72.97832489013672 - ], - "size": [ - 140, - 246 - ], - "flags": {}, - "order": 25, - "mode": 0, - "inputs": [ - { - "name": "images", - "type": "IMAGE", - "link": 227 - } - ], - "outputs": [], - "properties": { - "cnr_id": "comfy-core", - "ver": "0.3.49", - "Node name for S&R": "PreviewImage" - }, - "widgets_values": [] - }, - { - "id": 58, - "type": "LoadImage", - "pos": [ - -737.1319580078125, - -174.04302978515625 - ], - "size": [ - 413.10479736328125, - 498.3180847167969 - ], - "flags": {}, - "order": 15, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "IMAGE", - "type": "IMAGE", - "links": [ - 226 - ] - }, - { - "name": "MASK", - "type": "MASK", - "links": [] - } - ], - "properties": { - "cnr_id": "comfy-core", - "ver": "0.3.26", - "Node name for S&R": "LoadImage" - }, - "widgets_values": [ - "clipspace/clipspace-mask-379138.7999999998.png [input]", - "image" - ], - "color": "#2a363b", - "bgcolor": "#3f5159" - }, - { - "id": 129, - "type": "MarkdownNote", - "pos": [ - 791.3861694335938, - -356.8863830566406 - ], - "size": [ - 362.6117858886719, - 143.0945281982422 - ], - "flags": {}, - "order": 16, - "mode": 0, - "inputs": [], - "outputs": [], - "properties": {}, - "widgets_values": [ - "Prompt Writing Tip: If you do not wish to alter the subject's facial features, simply use \"a man\" or \"a woman\" without adding extra descriptions of their appearance. Prompts support both Chinese and English input. The prompt is intended for generating frontal, medium-to-close-up videos.\n\nInput Image Recommendation: For best results, use a high-resolution frontal face image. There are no restrictions on resolution or file extension, as our built-in preprocessing pipeline will handle them automatically.\n\n[https://github.com/WeChatCV/Stand-In](https://github.com/WeChatCV/Stand-In)" - ], - "color": "#322", - "bgcolor": "#533" } ], "links": [ @@ -1704,14 +1706,6 @@ 3, "INT" ], - [ - 223, - 127, - 0, - 128, - 0, - "FACE_PROCESSOR" - ], [ 226, 58, @@ -1728,14 +1722,6 @@ 0, "IMAGE" ], - [ - 228, - 128, - 0, - 104, - 1, - "IMAGE" - ], [ 229, 128, @@ -1743,6 +1729,22 @@ 122, 1, "IMAGE" + ], + [ + 230, + 130, + 0, + 128, + 0, + "FACE_PROCESSOR" + ], + [ + 231, + 128, + 0, + 104, + 1, + "IMAGE" ] ], "groups": [ @@ -1763,10 +1765,10 @@ "config": {}, "extra": { "ds": { - "scale": 0.6727499949326107, + "scale": 0.7400249944258753, "offset": [ - 1220.5620388990717, - 479.6860694347906 + 1050.1092033816878, + 678.2426041646066 ] }, "frontendVersion": "1.24.4",