Update After RCFG experiment
- Update readme to log the RCFG experiment - Refactor code - Add delta parameter on Animate_Anyone_Sampler node - Add ComfyUI Sampler progress bar
This commit is contained in:
@@ -35,12 +35,15 @@
|
||||
- I tried to break it down into as many modules as possible, so the workflow in ComfyUI would closely resemble the original pipeline from AnimateAnyone paper:
|
||||
<br>
|
||||
|
||||
## Will Do Next
|
||||
- Train a LCM Lora for denoise unet (**Estimated speed up: 5X**)
|
||||
- Convert Model using [stable-fast](https://github.com/chengzeyi/stable-fast) (**Estimated speed up: 2X**)
|
||||
- Implement the compoents (Residual CFG) proposed in [StreamDiffusion](https://github.com/cumulo-autumn/StreamDiffusion?tab=readme-ov-file) (**Estimated speed up: 2X**)
|
||||
- Incorporate the implementation & Pre-trained Models from [Open-AnimateAnyone](https://github.com/guoqincode/Open-AnimateAnyone) & [AnimateAnyone](https://github.com/HumanAIGC/AnimateAnyone) once they released
|
||||
- Training a new Model using better dataset to improve results quality (Optional, we'll see if there is any need for me to do it ;)
|
||||
## Roadmap
|
||||
- [x] Implement the compoents (Residual CFG) proposed in [StreamDiffusion](https://github.com/cumulo-autumn/StreamDiffusion?tab=readme-ov-file) (**Estimated speed up: 2X**)
|
||||
- **Result:**
|
||||
Generated result is not good enough when using DDIM Scheduler togather with RCFG, even though it speed up the generating process by about 4X.<br>
|
||||
In StreamDiffusion, RCFG works with LCM, could also be the case here, so keep it in another branch for now.
|
||||
- [ ] Convert Model using [stable-fast](https://github.com/chengzeyi/stable-fast) (**Estimated speed up: 2X**)
|
||||
- [ ] Train a LCM Lora for denoise unet (**Estimated speed up: 5X**)
|
||||
- [ ] Incorporate the implementation & Pre-trained Models from [Open-AnimateAnyone](https://github.com/guoqincode/Open-AnimateAnyone) & [AnimateAnyone](https://github.com/HumanAIGC/AnimateAnyone) once they released
|
||||
- [ ] Training a new Model using better dataset to improve results quality (Optional, we'll see if there is any need for me to do it ;)
|
||||
- Continuous research, always moving towards something better & faster🚀
|
||||
|
||||
## Install (Will add it to ComfyUI Manager Soon!)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"last_node_id": 26,
|
||||
"last_link_id": 32,
|
||||
"last_node_id": 31,
|
||||
"last_link_id": 56,
|
||||
"nodes": [
|
||||
{
|
||||
"id": 15,
|
||||
@@ -56,7 +56,7 @@
|
||||
{
|
||||
"name": "samples",
|
||||
"type": "LATENT",
|
||||
"link": 23
|
||||
"link": 56
|
||||
},
|
||||
{
|
||||
"name": "vae",
|
||||
@@ -79,121 +79,6 @@
|
||||
"Node name for S&R": "VAEDecode"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 11,
|
||||
"type": "[ComfyUI-3D] Load UNet2D ConditionModel",
|
||||
"pos": [
|
||||
1435,
|
||||
195
|
||||
],
|
||||
"size": {
|
||||
"0": 407.1247863769531,
|
||||
"1": 86.651123046875
|
||||
},
|
||||
"flags": {},
|
||||
"order": 0,
|
||||
"mode": 0,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "unet2d",
|
||||
"type": "UNET2D",
|
||||
"links": [
|
||||
18
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "[ComfyUI-3D] Load UNet2D ConditionModel"
|
||||
},
|
||||
"widgets_values": [
|
||||
"./pretrained_weights/stable-diffusion-v1-5/unet/",
|
||||
"./pretrained_weights/reference_unet.pth"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 12,
|
||||
"type": "[ComfyUI-3D] Load UNet3D ConditionModel",
|
||||
"pos": [
|
||||
1471,
|
||||
358
|
||||
],
|
||||
"size": {
|
||||
"0": 409.384033203125,
|
||||
"1": 106
|
||||
},
|
||||
"flags": {},
|
||||
"order": 1,
|
||||
"mode": 0,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "unet3d",
|
||||
"type": "UNET3D",
|
||||
"links": [
|
||||
19
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "[ComfyUI-3D] Load UNet3D ConditionModel"
|
||||
},
|
||||
"widgets_values": [
|
||||
"./pretrained_weights/stable-diffusion-v1-5/unet/",
|
||||
"./pretrained_weights/denoising_unet.pth",
|
||||
"./pretrained_weights/motion_module.pth"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"type": "VAEEncode",
|
||||
"pos": [
|
||||
1542,
|
||||
88
|
||||
],
|
||||
"size": {
|
||||
"0": 210,
|
||||
"1": 46
|
||||
},
|
||||
"flags": {},
|
||||
"order": 12,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "pixels",
|
||||
"type": "IMAGE",
|
||||
"link": 24
|
||||
},
|
||||
{
|
||||
"name": "vae",
|
||||
"type": "VAE",
|
||||
"link": 1
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "LATENT",
|
||||
"type": "LATENT",
|
||||
"links": [
|
||||
20
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "VAEEncode",
|
||||
"ttNbgOverride": {
|
||||
"color": "#223",
|
||||
"bgcolor": "#335",
|
||||
"groupcolor": "#88A"
|
||||
}
|
||||
},
|
||||
"color": "#223",
|
||||
"bgcolor": "#335"
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"type": "[ComfyUI-3D] Load Pose Guider",
|
||||
@@ -206,7 +91,7 @@
|
||||
"1": 58
|
||||
},
|
||||
"flags": {},
|
||||
"order": 2,
|
||||
"order": 0,
|
||||
"mode": 0,
|
||||
"outputs": [
|
||||
{
|
||||
@@ -226,47 +111,6 @@
|
||||
"./pretrained_weights/pose_guider.pth"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"type": "[ComfyUI-3D] Pose Guider Encode",
|
||||
"pos": [
|
||||
1668,
|
||||
704
|
||||
],
|
||||
"size": {
|
||||
"0": 292.20001220703125,
|
||||
"1": 46
|
||||
},
|
||||
"flags": {},
|
||||
"order": 14,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "pose_guider",
|
||||
"type": "POSE_GUIDER",
|
||||
"link": 5
|
||||
},
|
||||
{
|
||||
"name": "pose_images",
|
||||
"type": "IMAGE",
|
||||
"link": 27
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "pose_latent",
|
||||
"type": "POSE_LATENT",
|
||||
"links": [
|
||||
22
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "[ComfyUI-3D] Pose Guider Encode"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"type": "CLIPVisionLoader",
|
||||
@@ -279,7 +123,7 @@
|
||||
"1": 58
|
||||
},
|
||||
"flags": {},
|
||||
"order": 3,
|
||||
"order": 1,
|
||||
"mode": 0,
|
||||
"outputs": [
|
||||
{
|
||||
@@ -299,47 +143,6 @@
|
||||
"pytorch_model.bin"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"type": "CLIPVisionEncode",
|
||||
"pos": [
|
||||
1544,
|
||||
592
|
||||
],
|
||||
"size": {
|
||||
"0": 380.4000244140625,
|
||||
"1": 46
|
||||
},
|
||||
"flags": {},
|
||||
"order": 13,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "clip_vision",
|
||||
"type": "CLIP_VISION",
|
||||
"link": 3
|
||||
},
|
||||
{
|
||||
"name": "image",
|
||||
"type": "IMAGE",
|
||||
"link": 25
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "CLIP_VISION_OUTPUT",
|
||||
"type": "CLIP_VISION_OUTPUT",
|
||||
"links": [
|
||||
21
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "CLIPVisionEncode"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"type": "LoadImage",
|
||||
@@ -352,7 +155,7 @@
|
||||
"1": 314
|
||||
},
|
||||
"flags": {},
|
||||
"order": 4,
|
||||
"order": 2,
|
||||
"mode": 0,
|
||||
"outputs": [
|
||||
{
|
||||
@@ -391,7 +194,7 @@
|
||||
"1": 58
|
||||
},
|
||||
"flags": {},
|
||||
"order": 5,
|
||||
"order": 3,
|
||||
"mode": 0,
|
||||
"outputs": [
|
||||
{
|
||||
@@ -426,7 +229,7 @@
|
||||
"1": 58
|
||||
},
|
||||
"flags": {},
|
||||
"order": 6,
|
||||
"order": 4,
|
||||
"mode": 0,
|
||||
"outputs": [
|
||||
{
|
||||
@@ -461,7 +264,7 @@
|
||||
"1": 60.091087341308594
|
||||
},
|
||||
"flags": {},
|
||||
"order": 7,
|
||||
"order": 5,
|
||||
"mode": 0,
|
||||
"outputs": [
|
||||
{
|
||||
@@ -655,7 +458,7 @@
|
||||
"hidden": false,
|
||||
"paused": false,
|
||||
"params": {
|
||||
"filename": "video_00019.mp4",
|
||||
"filename": "video_00087.mp4",
|
||||
"subfolder": "AnimateAnyone",
|
||||
"type": "output",
|
||||
"format": "video/h265-mp4"
|
||||
@@ -664,15 +467,212 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 21,
|
||||
"type": "[ComfyUI-3D] Animate Anyone Sampler",
|
||||
"id": 11,
|
||||
"type": "[ComfyUI-3D] Load UNet2D ConditionModel",
|
||||
"pos": [
|
||||
2159,
|
||||
48
|
||||
1435,
|
||||
195
|
||||
],
|
||||
"size": {
|
||||
"0": 328.86407470703125,
|
||||
"1": 594
|
||||
"0": 407.1247863769531,
|
||||
"1": 86.651123046875
|
||||
},
|
||||
"flags": {},
|
||||
"order": 6,
|
||||
"mode": 0,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "unet2d",
|
||||
"type": "UNET2D",
|
||||
"links": [
|
||||
51
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "[ComfyUI-3D] Load UNet2D ConditionModel"
|
||||
},
|
||||
"widgets_values": [
|
||||
"./pretrained_weights/stable-diffusion-v1-5/unet/",
|
||||
"./pretrained_weights/reference_unet.pth"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 12,
|
||||
"type": "[ComfyUI-3D] Load UNet3D ConditionModel",
|
||||
"pos": [
|
||||
1471,
|
||||
358
|
||||
],
|
||||
"size": {
|
||||
"0": 409.384033203125,
|
||||
"1": 106
|
||||
},
|
||||
"flags": {},
|
||||
"order": 7,
|
||||
"mode": 0,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "unet3d",
|
||||
"type": "UNET3D",
|
||||
"links": [
|
||||
52
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "[ComfyUI-3D] Load UNet3D ConditionModel"
|
||||
},
|
||||
"widgets_values": [
|
||||
"./pretrained_weights/stable-diffusion-v1-5/unet/",
|
||||
"./pretrained_weights/denoising_unet.pth",
|
||||
"./pretrained_weights/motion_module.pth"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"type": "VAEEncode",
|
||||
"pos": [
|
||||
1542,
|
||||
88
|
||||
],
|
||||
"size": {
|
||||
"0": 210,
|
||||
"1": 46
|
||||
},
|
||||
"flags": {},
|
||||
"order": 12,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "pixels",
|
||||
"type": "IMAGE",
|
||||
"link": 24
|
||||
},
|
||||
{
|
||||
"name": "vae",
|
||||
"type": "VAE",
|
||||
"link": 1
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "LATENT",
|
||||
"type": "LATENT",
|
||||
"links": [
|
||||
53
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "VAEEncode",
|
||||
"ttNbgOverride": {
|
||||
"color": "#223",
|
||||
"bgcolor": "#335",
|
||||
"groupcolor": "#88A"
|
||||
}
|
||||
},
|
||||
"color": "#223",
|
||||
"bgcolor": "#335"
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"type": "CLIPVisionEncode",
|
||||
"pos": [
|
||||
1544,
|
||||
592
|
||||
],
|
||||
"size": {
|
||||
"0": 380.4000244140625,
|
||||
"1": 46
|
||||
},
|
||||
"flags": {},
|
||||
"order": 13,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "clip_vision",
|
||||
"type": "CLIP_VISION",
|
||||
"link": 3
|
||||
},
|
||||
{
|
||||
"name": "image",
|
||||
"type": "IMAGE",
|
||||
"link": 25
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "CLIP_VISION_OUTPUT",
|
||||
"type": "CLIP_VISION_OUTPUT",
|
||||
"links": [
|
||||
54
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "CLIPVisionEncode"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"type": "[ComfyUI-3D] Pose Guider Encode",
|
||||
"pos": [
|
||||
1668,
|
||||
704
|
||||
],
|
||||
"size": {
|
||||
"0": 292.20001220703125,
|
||||
"1": 46
|
||||
},
|
||||
"flags": {},
|
||||
"order": 14,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "pose_guider",
|
||||
"type": "POSE_GUIDER",
|
||||
"link": 5
|
||||
},
|
||||
{
|
||||
"name": "pose_images",
|
||||
"type": "IMAGE",
|
||||
"link": 27
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "pose_latent",
|
||||
"type": "POSE_LATENT",
|
||||
"links": [
|
||||
55
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "[ComfyUI-3D] Pose Guider Encode"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 31,
|
||||
"type": "[ComfyUI-3D] Animate Anyone Sampler",
|
||||
"pos": [
|
||||
2091,
|
||||
47
|
||||
],
|
||||
"size": {
|
||||
"0": 315,
|
||||
"1": 618
|
||||
},
|
||||
"flags": {},
|
||||
"order": 15,
|
||||
@@ -681,27 +681,27 @@
|
||||
{
|
||||
"name": "reference_unet",
|
||||
"type": "UNET2D",
|
||||
"link": 18
|
||||
"link": 51
|
||||
},
|
||||
{
|
||||
"name": "denoising_unet",
|
||||
"type": "UNET3D",
|
||||
"link": 19
|
||||
"link": 52
|
||||
},
|
||||
{
|
||||
"name": "ref_image_latent",
|
||||
"type": "LATENT",
|
||||
"link": 20
|
||||
"link": 53
|
||||
},
|
||||
{
|
||||
"name": "clip_image_embeds",
|
||||
"type": "CLIP_VISION_OUTPUT",
|
||||
"link": 21
|
||||
"link": 54
|
||||
},
|
||||
{
|
||||
"name": "pose_latent",
|
||||
"type": "POSE_LATENT",
|
||||
"link": 22
|
||||
"link": 55
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
@@ -709,7 +709,7 @@
|
||||
"name": "latent",
|
||||
"type": "LATENT",
|
||||
"links": [
|
||||
23
|
||||
56
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
@@ -723,22 +723,23 @@
|
||||
"fixed",
|
||||
20,
|
||||
3.5,
|
||||
1,
|
||||
24,
|
||||
1,
|
||||
4,
|
||||
1,
|
||||
1,
|
||||
"DDIM",
|
||||
0.0008500000000000001,
|
||||
0.00085,
|
||||
0.012,
|
||||
"linear",
|
||||
"v_prediction",
|
||||
"trailing",
|
||||
1,
|
||||
false,
|
||||
"cammy_white_v1.safetensors",
|
||||
true,
|
||||
false,
|
||||
"lcm-lora-sdv1-5.safetensors"
|
||||
"cammy_white_v1.safetensors"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -856,54 +857,6 @@
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
18,
|
||||
11,
|
||||
0,
|
||||
21,
|
||||
0,
|
||||
"UNET2D"
|
||||
],
|
||||
[
|
||||
19,
|
||||
12,
|
||||
0,
|
||||
21,
|
||||
1,
|
||||
"UNET3D"
|
||||
],
|
||||
[
|
||||
20,
|
||||
2,
|
||||
0,
|
||||
21,
|
||||
2,
|
||||
"LATENT"
|
||||
],
|
||||
[
|
||||
21,
|
||||
5,
|
||||
0,
|
||||
21,
|
||||
3,
|
||||
"CLIP_VISION_OUTPUT"
|
||||
],
|
||||
[
|
||||
22,
|
||||
8,
|
||||
0,
|
||||
21,
|
||||
4,
|
||||
"POSE_LATENT"
|
||||
],
|
||||
[
|
||||
23,
|
||||
21,
|
||||
0,
|
||||
14,
|
||||
0,
|
||||
"LATENT"
|
||||
],
|
||||
[
|
||||
24,
|
||||
22,
|
||||
@@ -975,6 +928,54 @@
|
||||
23,
|
||||
2,
|
||||
"INT"
|
||||
],
|
||||
[
|
||||
51,
|
||||
11,
|
||||
0,
|
||||
31,
|
||||
0,
|
||||
"UNET2D"
|
||||
],
|
||||
[
|
||||
52,
|
||||
12,
|
||||
0,
|
||||
31,
|
||||
1,
|
||||
"UNET3D"
|
||||
],
|
||||
[
|
||||
53,
|
||||
2,
|
||||
0,
|
||||
31,
|
||||
2,
|
||||
"LATENT"
|
||||
],
|
||||
[
|
||||
54,
|
||||
5,
|
||||
0,
|
||||
31,
|
||||
3,
|
||||
"CLIP_VISION_OUTPUT"
|
||||
],
|
||||
[
|
||||
55,
|
||||
8,
|
||||
0,
|
||||
31,
|
||||
4,
|
||||
"POSE_LATENT"
|
||||
],
|
||||
[
|
||||
56,
|
||||
31,
|
||||
0,
|
||||
14,
|
||||
0,
|
||||
"LATENT"
|
||||
]
|
||||
],
|
||||
"groups": [],
|
||||
|
||||
@@ -1,13 +1,38 @@
|
||||
import inspect
|
||||
from diffusers.schedulers import (
|
||||
DDIMScheduler,
|
||||
DPMSolverMultistepScheduler,
|
||||
LCMScheduler,
|
||||
EulerDiscreteScheduler,
|
||||
EulerAncestralDiscreteScheduler,
|
||||
LMSDiscreteScheduler,
|
||||
PNDMScheduler,
|
||||
)
|
||||
import time
|
||||
import torch
|
||||
from diffusers import (StableDiffusionPipeline,
|
||||
EulerAncestralDiscreteScheduler)
|
||||
from sfast.compilers.diffusion_pipeline_compiler import (compile,
|
||||
CompilationConfig)
|
||||
|
||||
print("clip_samples" in inspect.signature(DDIMScheduler.__init__).parameters)
|
||||
|
||||
def load_model():
|
||||
model = StableDiffusionPipeline.from_pretrained(
|
||||
'runwayml/stable-diffusion-v1-5',
|
||||
torch_dtype=torch.float16)
|
||||
|
||||
model.scheduler = EulerAncestralDiscreteScheduler.from_config(
|
||||
model.scheduler.config)
|
||||
model.safety_checker = None
|
||||
model.to(torch.device('cuda'))
|
||||
return model
|
||||
|
||||
model = load_model()
|
||||
|
||||
config = CompilationConfig.Default()
|
||||
# xformers and Triton are suggested for achieving best performance.
|
||||
try:
|
||||
import xformers
|
||||
config.enable_xformers = True
|
||||
except ImportError:
|
||||
print('xformers not installed, skip')
|
||||
try:
|
||||
import triton
|
||||
config.enable_triton = True
|
||||
except ImportError:
|
||||
print('Triton not installed, skip')
|
||||
# CUDA Graph is suggested for small batch sizes and small resolutions to reduce CPU overhead.
|
||||
# But it can increase the amount of GPU memory used.
|
||||
# For StableVideoDiffusionPipeline it is not needed.
|
||||
config.enable_cuda_graph = True
|
||||
|
||||
model = compile(model, config)
|
||||
@@ -18,11 +18,9 @@ from diffusers.schedulers import (
|
||||
PNDMScheduler,
|
||||
)
|
||||
|
||||
from .src.models.mutual_self_attention import ReferenceAttentionControl
|
||||
from .src.models.pose_guider import PoseGuider
|
||||
from .src.models.unet_2d_condition import UNet2DConditionModel
|
||||
from .src.models.unet_3d import UNet3DConditionModel
|
||||
from .src.models.main_model_patcher import AnimateAnyoneModelPatcher
|
||||
from .src.models.main_diffuser import AADiffusion
|
||||
|
||||
ROOT_PATH = os.path.join(comfy_paths.get_folder_paths("custom_nodes")[0], "./ComfyUI-AnimateAnyone-Evolved")
|
||||
@@ -55,7 +53,8 @@ class Animate_Anyone_Sampler:
|
||||
"seed": ("INT", {"default": 999999999, "min": 0, "max": 0xffffffffffffffff}),
|
||||
"steps": ("INT", {"default": 20, "min": 1, "max": 10000}),
|
||||
"cfg": ("FLOAT", {"default": 3.5, "min": 0.0, "max": 100.0, "step":0.1, "round": 0.01}),
|
||||
"context_frames": ("INT", {"default": 12, "min": 1}),
|
||||
"delta": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 100.0, "step":0.1, "round": 0.01}),
|
||||
"context_frames": ("INT", {"default": 24, "min": 1}),
|
||||
"context_stride": ("INT", {"default": 1, "min": 1}),
|
||||
"context_overlap": ("INT", {"default": 4, "min": 0}),
|
||||
"context_batch_size": ("INT", {"default": 1, "min": 1}),
|
||||
@@ -95,7 +94,8 @@ class Animate_Anyone_Sampler:
|
||||
pose_latent,
|
||||
seed,
|
||||
steps,
|
||||
cfg,
|
||||
cfg,
|
||||
delta,
|
||||
context_frames,
|
||||
context_stride,
|
||||
context_overlap,
|
||||
@@ -179,7 +179,9 @@ class Animate_Anyone_Sampler:
|
||||
|
||||
samples = diffuser(
|
||||
steps,
|
||||
cfg,
|
||||
cfg,
|
||||
delta,
|
||||
ref_image_latent,
|
||||
pose_latent,
|
||||
encoder_hidden_states,
|
||||
seed,
|
||||
|
||||
+223
-73
@@ -3,8 +3,10 @@ import inspect
|
||||
import math
|
||||
from typing import Callable, List, Optional, Union
|
||||
|
||||
import comfy.utils
|
||||
|
||||
import torch
|
||||
from diffusers import DiffusionPipeline
|
||||
from diffusers import DiffusionPipeline, StableDiffusionPipeline
|
||||
from diffusers.loaders import LoraLoaderMixin
|
||||
from diffusers.schedulers import (
|
||||
DDIMScheduler,
|
||||
@@ -18,11 +20,11 @@ from diffusers.schedulers import (
|
||||
from diffusers.utils.torch_utils import randn_tensor
|
||||
|
||||
from ..utils.util import get_tensor_interpolation_method, get_context_scheduler
|
||||
|
||||
|
||||
class AADiffusion(DiffusionPipeline, LoraLoaderMixin):
|
||||
def __init__(
|
||||
self,
|
||||
reference_unet,
|
||||
unet,
|
||||
scheduler: Union[
|
||||
DDIMScheduler,
|
||||
@@ -36,9 +38,11 @@ class AADiffusion(DiffusionPipeline, LoraLoaderMixin):
|
||||
):
|
||||
super().__init__()
|
||||
self.register_modules(
|
||||
reference_unet=reference_unet,
|
||||
unet=unet,
|
||||
scheduler=scheduler,
|
||||
)
|
||||
self.reference_unet = reference_unet
|
||||
self.unet = unet
|
||||
self.scheduler = scheduler
|
||||
|
||||
@@ -160,13 +164,199 @@ class AADiffusion(DiffusionPipeline, LoraLoaderMixin):
|
||||
new_index += 1
|
||||
|
||||
return new_latents
|
||||
|
||||
def perform_guidance(
|
||||
self,
|
||||
noise_pred,
|
||||
counter,
|
||||
cfg,
|
||||
delta,
|
||||
do_double_pass,
|
||||
):
|
||||
|
||||
# perform CFG
|
||||
if do_double_pass:
|
||||
noise_pred_uncond, noise_pred_cond = (noise_pred / counter).chunk(2)
|
||||
else:
|
||||
noise_pred_cond = noise_pred_uncond = noise_pred / counter
|
||||
cfg = 0.0
|
||||
noise_pred = delta * noise_pred_uncond + cfg * (noise_pred_cond - delta * noise_pred_uncond)
|
||||
|
||||
return noise_pred
|
||||
|
||||
def denoise_all_one_step(
|
||||
self,
|
||||
t,
|
||||
latents,
|
||||
encoder_hidden_states,
|
||||
pose_latent,
|
||||
global_context,
|
||||
do_double_pass,
|
||||
device,
|
||||
):
|
||||
noise_pred = torch.zeros(
|
||||
(
|
||||
latents.shape[0] * (2 if do_double_pass else 1),
|
||||
*latents.shape[1:],
|
||||
),
|
||||
device=device,
|
||||
dtype=latents.dtype,
|
||||
)
|
||||
counter = torch.zeros(
|
||||
(1, 1, latents.shape[2], 1, 1),
|
||||
device=device,
|
||||
dtype=latents.dtype,
|
||||
)
|
||||
|
||||
for context in global_context:
|
||||
# 3.1 expand the latents if we are doing classifier free guidance
|
||||
latent_model_input = (
|
||||
torch.cat([latents[:, :, c] for c in context]) # Concatenates the context in the same batch
|
||||
.to(device)
|
||||
.repeat(2 if do_double_pass else 1, 1, 1, 1, 1)
|
||||
)
|
||||
latent_model_input = self.scheduler.scale_model_input(
|
||||
latent_model_input, t
|
||||
)
|
||||
b, c, f, h, w = latent_model_input.shape
|
||||
latent_pose_input = torch.cat(
|
||||
[pose_latent[:, :, c] for c in context]
|
||||
).repeat(2 if do_double_pass else 1, 1, 1, 1, 1)
|
||||
pred = self.unet(
|
||||
latent_model_input, # torch.Size([2, 4, 24, 96, 64])
|
||||
t,
|
||||
encoder_hidden_states=encoder_hidden_states[:b],
|
||||
pose_cond_fea=latent_pose_input, # torch.Size([2, 320, 24, 96, 64])
|
||||
return_dict=False,
|
||||
)[0]
|
||||
|
||||
for j, c in enumerate(context):
|
||||
noise_pred[:, :, c] = noise_pred[:, :, c] + pred
|
||||
counter[:, :, c] = counter[:, :, c] + 1
|
||||
|
||||
return noise_pred, counter
|
||||
|
||||
def solve_one_step(
|
||||
self,
|
||||
t,
|
||||
latents,
|
||||
encoder_hidden_states,
|
||||
pose_latent,
|
||||
global_context,
|
||||
cfg,
|
||||
delta,
|
||||
do_double_pass,
|
||||
device,
|
||||
extra_step_kwargs,
|
||||
):
|
||||
|
||||
noise_pred, counter = self.denoise_all_one_step(
|
||||
t=t,
|
||||
latents=latents,
|
||||
encoder_hidden_states=encoder_hidden_states,
|
||||
pose_latent=pose_latent,
|
||||
global_context=global_context,
|
||||
do_double_pass=do_double_pass,
|
||||
device=device,
|
||||
)
|
||||
|
||||
noise_pred = self.perform_guidance(
|
||||
noise_pred=noise_pred,
|
||||
counter=counter,
|
||||
cfg=cfg,
|
||||
delta=delta,
|
||||
do_double_pass=do_double_pass,
|
||||
)
|
||||
|
||||
scheduler_output = self.scheduler.step(noise_pred, t, latents, **extra_step_kwargs)
|
||||
|
||||
return scheduler_output.prev_sample
|
||||
|
||||
def denoise_loop(
|
||||
self,
|
||||
ref_image_latent,
|
||||
loop_steps,
|
||||
latents,
|
||||
encoder_hidden_states,
|
||||
pose_latent,
|
||||
global_context,
|
||||
cfg,
|
||||
delta,
|
||||
do_double_pass,
|
||||
interpolation_factor,
|
||||
device,
|
||||
extra_step_kwargs,
|
||||
):
|
||||
# Prepare confitional embeds
|
||||
if do_double_pass:
|
||||
uncond_encoder_hidden_states = torch.zeros_like(encoder_hidden_states)
|
||||
encoder_hidden_states=torch.cat(
|
||||
[uncond_encoder_hidden_states, encoder_hidden_states], dim=0
|
||||
)
|
||||
|
||||
# Prepare reference attention control
|
||||
reference_control_writer = ReferenceAttentionControl(
|
||||
self.reference_unet,
|
||||
do_classifier_free_guidance=do_double_pass,
|
||||
mode="write",
|
||||
fusion_blocks="full",
|
||||
)
|
||||
reference_control_reader = ReferenceAttentionControl(
|
||||
self.unet,
|
||||
do_classifier_free_guidance=do_double_pass,
|
||||
mode="read",
|
||||
fusion_blocks="full",
|
||||
)
|
||||
|
||||
self.reference_unet(
|
||||
ref_image_latent.repeat(2 if do_double_pass else 1, 1, 1, 1),
|
||||
torch.zeros(size=(1,), dtype=int, device=device),
|
||||
encoder_hidden_states=encoder_hidden_states,
|
||||
return_dict=False,
|
||||
)
|
||||
reference_control_reader.update(reference_control_writer)
|
||||
|
||||
# Prepare timesteps
|
||||
self.scheduler.set_timesteps(loop_steps, device=device)
|
||||
timesteps = self.scheduler.timesteps
|
||||
|
||||
comfy_pbar = comfy.utils.ProgressBar(loop_steps)
|
||||
|
||||
with self.progress_bar(total=loop_steps) as progress_bar:
|
||||
for i, t in enumerate(timesteps):
|
||||
|
||||
latents = self.solve_one_step(
|
||||
t=t,
|
||||
latents=latents,
|
||||
encoder_hidden_states=encoder_hidden_states,
|
||||
pose_latent=pose_latent,
|
||||
global_context=global_context,
|
||||
cfg=cfg,
|
||||
delta=delta,
|
||||
do_double_pass=do_double_pass,
|
||||
device=device,
|
||||
extra_step_kwargs=extra_step_kwargs,
|
||||
)
|
||||
|
||||
progress_bar.update()
|
||||
comfy_pbar.update_absolute(i + 1)
|
||||
|
||||
if interpolation_factor > 0:
|
||||
latents = self.interpolate_latents(latents, interpolation_factor, device)
|
||||
|
||||
reference_control_reader.clear()
|
||||
reference_control_writer.clear()
|
||||
|
||||
return latents
|
||||
|
||||
@torch.no_grad()
|
||||
def __call__(
|
||||
self,
|
||||
steps,
|
||||
cfg,
|
||||
pose_fea,
|
||||
delta,
|
||||
ref_image_latent,
|
||||
pose_latent,
|
||||
encoder_hidden_states,
|
||||
seed = 999999999,
|
||||
eta: float = 0.0,
|
||||
@@ -180,8 +370,9 @@ class AADiffusion(DiffusionPipeline, LoraLoaderMixin):
|
||||
callback_steps: Optional[int] = 1,
|
||||
):
|
||||
|
||||
device = pose_fea.device
|
||||
|
||||
do_double_pass = cfg > 0
|
||||
|
||||
device = pose_latent.device
|
||||
generator=torch.manual_seed(seed)
|
||||
latents = self.prepare_latents(
|
||||
batch_size=pose_fea.shape[0],
|
||||
@@ -239,74 +430,33 @@ class AADiffusion(DiffusionPipeline, LoraLoaderMixin):
|
||||
[[60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]]
|
||||
]
|
||||
"""
|
||||
|
||||
do_classifier_free_guidance = cfg > 0
|
||||
|
||||
# denoising loop
|
||||
num_warmup_steps = len(timesteps) - steps * self.scheduler.order
|
||||
with self.progress_bar(total=steps) as progress_bar:
|
||||
for i, t in enumerate(timesteps):
|
||||
noise_pred = torch.zeros(
|
||||
(
|
||||
latents.shape[0] * (2 if do_classifier_free_guidance else 1),
|
||||
*latents.shape[1:],
|
||||
),
|
||||
device=device,
|
||||
dtype=latents.dtype,
|
||||
)
|
||||
counter = torch.zeros(
|
||||
(1, 1, latents.shape[2], 1, 1),
|
||||
device=device,
|
||||
dtype=latents.dtype,
|
||||
)
|
||||
|
||||
for context in global_context:
|
||||
# 3.1 expand the latents if we are doing classifier free guidance
|
||||
latent_model_input = (
|
||||
torch.cat([latents[:, :, c] for c in context]) # Concatenates the context in the same batch
|
||||
.to(device)
|
||||
.repeat(2 if do_classifier_free_guidance else 1, 1, 1, 1, 1)
|
||||
)
|
||||
latent_model_input = self.scheduler.scale_model_input(
|
||||
latent_model_input, t
|
||||
)
|
||||
b, c, f, h, w = latent_model_input.shape
|
||||
latent_pose_input = torch.cat(
|
||||
[pose_fea[:, :, c] for c in context]
|
||||
).repeat(2 if do_classifier_free_guidance else 1, 1, 1, 1, 1)
|
||||
pred = self.unet(
|
||||
latent_model_input, # torch.Size([2, 4, 24, 96, 64])
|
||||
t,
|
||||
encoder_hidden_states=encoder_hidden_states[:b],
|
||||
pose_cond_fea=latent_pose_input, # torch.Size([2, 320, 24, 96, 64])
|
||||
return_dict=False,
|
||||
)[0]
|
||||
|
||||
for j, c in enumerate(context):
|
||||
noise_pred[:, :, c] = noise_pred[:, :, c] + pred
|
||||
counter[:, :, c] = counter[:, :, c] + 1
|
||||
|
||||
# perform guidance
|
||||
if do_classifier_free_guidance:
|
||||
noise_pred_uncond, noise_pred_text = (noise_pred / counter).chunk(2)
|
||||
noise_pred = noise_pred_uncond + cfg * (
|
||||
noise_pred_text - noise_pred_uncond
|
||||
)
|
||||
|
||||
latents = self.scheduler.step(
|
||||
noise_pred, t, latents, **extra_step_kwargs
|
||||
).prev_sample
|
||||
|
||||
# update progress bar and callback
|
||||
if i == len(timesteps) - 1 or (
|
||||
(i + 1) > num_warmup_steps and (i + 1) % self.scheduler.order == 0
|
||||
):
|
||||
progress_bar.update()
|
||||
if callback is not None and i % callback_steps == 0:
|
||||
step_idx = i // getattr(self.scheduler, "order", 1)
|
||||
callback(step_idx, t, latents)
|
||||
|
||||
if interpolation_factor > 0:
|
||||
latents = self.interpolate_latents(latents, interpolation_factor, device)
|
||||
# Prepare initial latents
|
||||
latents = self.prepare_latents(
|
||||
batch_size=pose_latent.shape[0],
|
||||
num_channels_latents=self.unet.config.in_channels,
|
||||
video_length=video_length,
|
||||
height=pose_latent.shape[-2],
|
||||
width=pose_latent.shape[-1],
|
||||
dtype=encoder_hidden_states.dtype,
|
||||
device=device,
|
||||
generator=generator,
|
||||
)
|
||||
|
||||
# sequential double pass
|
||||
latents = self.denoise_loop(
|
||||
ref_image_latent=ref_image_latent,
|
||||
loop_steps=steps,
|
||||
latents=latents,
|
||||
encoder_hidden_states=encoder_hidden_states,
|
||||
pose_latent=pose_latent,
|
||||
global_context=global_context,
|
||||
cfg=cfg,
|
||||
delta=delta,
|
||||
do_double_pass=do_double_pass,
|
||||
interpolation_factor=interpolation_factor,
|
||||
device=device,
|
||||
extra_step_kwargs=extra_step_kwargs,
|
||||
)
|
||||
|
||||
return latents
|
||||
@@ -1,13 +0,0 @@
|
||||
import torch
|
||||
|
||||
from comfy.model_patcher import ModelPatcher
|
||||
|
||||
from .unet_3d import UNet3DConditionModel
|
||||
|
||||
class AnimateAnyoneModelPatcher(ModelPatcher):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.model: UNet3DConditionModel = self.model
|
||||
|
||||
|
||||
Reference in New Issue
Block a user