Views
No views yet


Flexible NFEs: For TCD, the NFEs can be varied at will (compared with Turbo), without adversely affecting the quality of the results (compared with LCMs), where LCM experiences a notable decline in quality at high NFEs.Better than Teacher: TCD maintains superior generative quality at high NFEs, even exceeding the performance of DPM-Solver++(2S) with origin SDXL. It is worth noting that there is no additional discriminator or LPIPS supervision included during training.Freely Change the Detailing: During inference, the level of detail in the image can be simply modified by adjusing one hyper-parameter gamma. This option does not require the introduction of any additional parameters.Versatility: Integrated with LoRA technology, TCD can be directly applied to various models (including the custom Community Models, styled LoRA, ControlNet, IP-Adapter) that share the same backbone, as demonstrated in the Usage.

Avoiding Mode Collapse: TCD achieves few-step generation without the need for adversarial training, thus circumventing mode collapse caused by the GAN objective.
In contrast to the concurrent work SDXL-Lightning, which relies on Adversarial Diffusion Distillation, TCD can synthesize results that are more realistic and slightly more diverse, without the presence of "Janus" artifacts.

pip install diffusers transformers accelerate peft1git clone https://github.com/jabir-zheng/TCD.git
2cd TCD1import torch
2from diffusers import StableDiffusionXLPipeline
3from scheduling_tcd import TCDScheduler
4
5device = "cuda"
6base_model_id = "stabilityai/stable-diffusion-xl-base-1.0"
7tcd_lora_id = "h1t/TCD-SDXL-LoRA"
8
9pipe = StableDiffusionXLPipeline.from_pretrained(base_model_id, torch_dtype=torch.float16, variant="fp16").to(device)
10pipe.scheduler = TCDScheduler.from_config(pipe.scheduler.config)
11
12pipe.load_lora_weights(tcd_lora_id)
13pipe.fuse_lora()
14
15prompt = "Beautiful woman, bubblegum pink, lemon yellow, minty blue, futuristic, high-detail, epic composition, watercolor."
16
17image = pipe(
18 prompt=prompt,
19 num_inference_steps=4,
20 guidance_scale=0,
21 # Eta (referred to as `gamma` in the paper) is used to control the stochasticity in every step.
22 # A value of 0.3 often yields good results.
23 # We recommend using a higher eta when increasing the number of inference steps.
24 eta=0.3,
25 generator=torch.Generator(device=device).manual_seed(0),
26).images[0]
1import torch
2from diffusers import AutoPipelineForInpainting
3from diffusers.utils import load_image, make_image_grid
4from scheduling_tcd import TCDScheduler
5
6device = "cuda"
7base_model_id = "diffusers/stable-diffusion-xl-1.0-inpainting-0.1"
8tcd_lora_id = "h1t/TCD-SDXL-LoRA"
9
10pipe = AutoPipelineForInpainting.from_pretrained(base_model_id, torch_dtype=torch.float16, variant="fp16").to(device)
11pipe.scheduler = TCDScheduler.from_config(pipe.scheduler.config)
12
13pipe.load_lora_weights(tcd_lora_id)
14pipe.fuse_lora()
15
16img_url = "https://raw.githubusercontent.com/CompVis/latent-diffusion/main/data/inpainting_examples/overture-creations-5sI6fQgYIuo.png"
17mask_url = "https://raw.githubusercontent.com/CompVis/latent-diffusion/main/data/inpainting_examples/overture-creations-5sI6fQgYIuo_mask.png"
18
19init_image = load_image(img_url).resize((1024, 1024))
20mask_image = load_image(mask_url).resize((1024, 1024))
21
22prompt = "a tiger sitting on a park bench"
23
24image = pipe(
25 prompt=prompt,
26 image=init_image,
27 mask_image=mask_image,
28 num_inference_steps=8,
29 guidance_scale=0,
30 eta=0.3, # Eta (referred to as `gamma` in the paper) is used to control the stochasticity in every step. A value of 0.3 often yields good results.
31 strength=0.99, # make sure to use `strength` below 1.0
32 generator=torch.Generator(device=device).manual_seed(0),
33).images[0]
34
35grid_image = make_image_grid([init_image, mask_image, image], rows=1, cols=3)
1import torch
2from diffusers import StableDiffusionXLPipeline
3from scheduling_tcd import TCDScheduler
4
5device = "cuda"
6base_model_id = "cagliostrolab/animagine-xl-3.0"
7tcd_lora_id = "h1t/TCD-SDXL-LoRA"
8
9pipe = StableDiffusionXLPipeline.from_pretrained(base_model_id, torch_dtype=torch.float16, variant="fp16").to(device)
10pipe.scheduler = TCDScheduler.from_config(pipe.scheduler.config)
11
12pipe.load_lora_weights(tcd_lora_id)
13pipe.fuse_lora()
14
15prompt = "A man, clad in a meticulously tailored military uniform, stands with unwavering resolve. The uniform boasts intricate details, and his eyes gleam with determination. Strands of vibrant, windswept hair peek out from beneath the brim of his cap."
16
17image = pipe(
18 prompt=prompt,
19 num_inference_steps=8,
20 guidance_scale=0,
21 # Eta (referred to as `gamma` in the paper) is used to control the stochasticity in every step.
22 # A value of 0.3 often yields good results.
23 # We recommend using a higher eta when increasing the number of inference steps.
24 eta=0.3,
25 generator=torch.Generator(device=device).manual_seed(0),
26).images[0]
1import torch
2from diffusers import StableDiffusionXLPipeline
3from scheduling_tcd import TCDScheduler
4
5device = "cuda"
6base_model_id = "stabilityai/stable-diffusion-xl-base-1.0"
7tcd_lora_id = "h1t/TCD-SDXL-LoRA"
8styled_lora_id = "TheLastBen/Papercut_SDXL"
9
10pipe = StableDiffusionXLPipeline.from_pretrained(base_model_id, torch_dtype=torch.float16, variant="fp16").to(device)
11pipe.scheduler = TCDScheduler.from_config(pipe.scheduler.config)
12
13pipe.load_lora_weights(tcd_lora_id, adapter_name="tcd")
14pipe.load_lora_weights(styled_lora_id, adapter_name="style")
15pipe.set_adapters(["tcd", "style"], adapter_weights=[1.0, 1.0])
16
17prompt = "papercut of a winter mountain, snow"
18
19image = pipe(
20 prompt=prompt,
21 num_inference_steps=4,
22 guidance_scale=0,
23 # Eta (referred to as `gamma` in the paper) is used to control the stochasticity in every step.
24 # A value of 0.3 often yields good results.
25 # We recommend using a higher eta when increasing the number of inference steps.
26 eta=0.3,
27 generator=torch.Generator(device=device).manual_seed(0),
28).images[0]
1import torch
2import numpy as np
3from PIL import Image
4from transformers import DPTFeatureExtractor, DPTForDepthEstimation
5from diffusers import ControlNetModel, StableDiffusionXLControlNetPipeline
6from diffusers.utils import load_image, make_image_grid
7from scheduling_tcd import TCDScheduler
8
9device = "cuda"
10depth_estimator = DPTForDepthEstimation.from_pretrained("Intel/dpt-hybrid-midas").to(device)
11feature_extractor = DPTFeatureExtractor.from_pretrained("Intel/dpt-hybrid-midas")
12
13def get_depth_map(image):
14 image = feature_extractor(images=image, return_tensors="pt").pixel_values.to(device)
15 with torch.no_grad(), torch.autocast(device):
16 depth_map = depth_estimator(image).predicted_depth
17
18 depth_map = torch.nn.functional.interpolate(
19 depth_map.unsqueeze(1),
20 size=(1024, 1024),
21 mode="bicubic",
22 align_corners=False,
23 )
24 depth_min = torch.amin(depth_map, dim=[1, 2, 3], keepdim=True)
25 depth_max = torch.amax(depth_map, dim=[1, 2, 3], keepdim=True)
26 depth_map = (depth_map - depth_min) / (depth_max - depth_min)
27 image = torch.cat([depth_map] * 3, dim=1)
28
29 image = image.permute(0, 2, 3, 1).cpu().numpy()[0]
30 image = Image.fromarray((image * 255.0).clip(0, 255).astype(np.uint8))
31 return image
32
33base_model_id = "stabilityai/stable-diffusion-xl-base-1.0"
34controlnet_id = "diffusers/controlnet-depth-sdxl-1.0"
35tcd_lora_id = "h1t/TCD-SDXL-LoRA"
36
37controlnet = ControlNetModel.from_pretrained(
38 controlnet_id,
39 torch_dtype=torch.float16,
40 variant="fp16",
41).to(device)
42pipe = StableDiffusionXLControlNetPipeline.from_pretrained(
43 base_model_id,
44 controlnet=controlnet,
45 torch_dtype=torch.float16,
46 variant="fp16",
47).to(device)
48pipe.enable_model_cpu_offload()
49
50pipe.scheduler = TCDScheduler.from_config(pipe.scheduler.config)
51
52pipe.load_lora_weights(tcd_lora_id)
53pipe.fuse_lora()
54
55prompt = "stormtrooper lecture, photorealistic"
56
57image = load_image("https://huggingface.co/lllyasviel/sd-controlnet-depth/resolve/main/images/stormtrooper.png")
58depth_image = get_depth_map(image)
59
60controlnet_conditioning_scale = 0.5 # recommended for good generalization
61
62image = pipe(
63 prompt,
64 image=depth_image,
65 num_inference_steps=4,
66 guidance_scale=0,
67 eta=0.3, # A parameter (referred to as `gamma` in the paper) is used to control the stochasticity in every step. A value of 0.3 often yields good results.
68 controlnet_conditioning_scale=controlnet_conditioning_scale,
69 generator=torch.Generator(device=device).manual_seed(0),
70).images[0]
71
72grid_image = make_image_grid([depth_image, image], rows=1, cols=2)
1import torch
2from diffusers import ControlNetModel, StableDiffusionXLControlNetPipeline
3from diffusers.utils import load_image, make_image_grid
4from scheduling_tcd import TCDScheduler
5
6device = "cuda"
7base_model_id = "stabilityai/stable-diffusion-xl-base-1.0"
8controlnet_id = "diffusers/controlnet-canny-sdxl-1.0"
9tcd_lora_id = "h1t/TCD-SDXL-LoRA"
10
11controlnet = ControlNetModel.from_pretrained(
12 controlnet_id,
13 torch_dtype=torch.float16,
14 variant="fp16",
15).to(device)
16pipe = StableDiffusionXLControlNetPipeline.from_pretrained(
17 base_model_id,
18 controlnet=controlnet,
19 torch_dtype=torch.float16,
20 variant="fp16",
21).to(device)
22pipe.enable_model_cpu_offload()
23
24pipe.scheduler = TCDScheduler.from_config(pipe.scheduler.config)
25
26pipe.load_lora_weights(tcd_lora_id)
27pipe.fuse_lora()
28
29prompt = "ultrarealistic shot of a furry blue bird"
30
31canny_image = load_image("https://huggingface.co/datasets/hf-internal-testing/diffusers-images/resolve/main/sd_controlnet/bird_canny.png")
32
33controlnet_conditioning_scale = 0.5 # recommended for good generalization
34
35image = pipe(
36 prompt,
37 image=canny_image,
38 num_inference_steps=4,
39 guidance_scale=0,
40 eta=0.3, # A parameter (referred to as `gamma` in the paper) is used to control the stochasticity in every step. A value of 0.3 often yields good results.
41 controlnet_conditioning_scale=controlnet_conditioning_scale,
42 generator=torch.Generator(device=device).manual_seed(0),
43).images[0]
44
45grid_image = make_image_grid([canny_image, image], rows=1, cols=2)
1import torch
2from diffusers import StableDiffusionXLPipeline
3from diffusers.utils import load_image, make_image_grid
4
5from ip_adapter import IPAdapterXL
6from scheduling_tcd import TCDScheduler
7
8device = "cuda"
9base_model_path = "stabilityai/stable-diffusion-xl-base-1.0"
10image_encoder_path = "sdxl_models/image_encoder"
11ip_ckpt = "sdxl_models/ip-adapter_sdxl.bin"
12tcd_lora_id = "h1t/TCD-SDXL-LoRA"
13
14pipe = StableDiffusionXLPipeline.from_pretrained(
15 base_model_path,
16 torch_dtype=torch.float16,
17 variant="fp16"
18)
19pipe.scheduler = TCDScheduler.from_config(pipe.scheduler.config)
20
21pipe.load_lora_weights(tcd_lora_id)
22pipe.fuse_lora()
23
24ip_model = IPAdapterXL(pipe, image_encoder_path, ip_ckpt, device)
25
26ref_image = load_image("https://raw.githubusercontent.com/tencent-ailab/IP-Adapter/main/assets/images/woman.png").resize((512, 512))
27
28prompt = "best quality, high quality, wearing sunglasses"
29
30image = ip_model.generate(
31 pil_image=ref_image,
32 prompt=prompt,
33 scale=0.5,
34 num_samples=1,
35 num_inference_steps=4,
36 guidance_scale=0,
37 eta=0.3, # A parameter (referred to as `gamma` in the paper) is used to control the stochasticity in every step. A value of 0.3 often yields good results.
38 seed=0,
39)[0]
40
41grid_image = make_image_grid([ref_image, image], rows=1, cols=2)
1@misc{zheng2024trajectory,
2 title={Trajectory Consistency Distillation},
3 author={Jianbin Zheng and Minghui Hu and Zhongyi Fan and Chaoyue Wang and Changxing Ding and Dacheng Tao and Tat-Jen Cham},
4 year={2024},
5 eprint={2402.19159},
6 archivePrefix={arXiv},
7 primaryClass={cs.CV}
8}