Diffusers documentation

ChronoEdit

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

LoRA

ChronoEdit

ChronoEdit: Towards Temporal Reasoning for Image Editing and World Simulation da NVIDIA e da University of Toronto, por Jay Zhangjie Wu, Xuanchi Ren, Tianchang Shen, Tianshi Cao, Kai He, Yifan Lu, Ruiyuan Gao, Enze Xie, Shiyi Lan, Jose M. Alvarez, Jun Gao, Sanja Fidler, Zian Wang, Huan Ling.

Resumo: O ChronoEdit reformula a edição de imagens como uma tarefa de geração de vídeo, utilizando as imagens de entrada e editadas como quadros inicial e final para aproveitar modelos de vídeo pré-treinados com consistência temporal. Um estágio de raciocínio temporal introduz tokens de raciocínio para garantir edições fisicamente plausíveis e visualizar a trajetória da edição.

Avanços recentes em grandes modelos generativos aprimoraram significativamente tanto a edição de imagens quanto a geração de imagens em contexto, porém uma lacuna crítica permanece em garantir a consistência física, na qual os objetos editados devem permanecer coerentes. Essa capacidade é especialmente vital para tarefas relacionadas à simulação de mundo. Neste artigo, apresentamos o ChronoEdit, um framework que reformula a edição de imagens como um problema de geração de vídeo. Primeiro, o ChronoEdit trata as imagens de entrada e editadas como o primeiro e o último quadro de um vídeo, permitindo aproveitar grandes modelos generativos de vídeo pré-treinados que capturam não apenas a aparência dos objetos, mas também a física implícita do movimento e da interação por meio da consistência temporal aprendida. Segundo, o ChronoEdit introduz um estágio de raciocínio temporal que executa explicitamente a edição no momento da inferência. Sob essa configuração, o quadro-alvo é desruidado conjuntamente com tokens de raciocínio para imaginar uma trajetória de edição plausível que restringe o espaço de soluções a transformações fisicamente viáveis. Os tokens de raciocínio são então descartados após algumas etapas para evitar o alto custo computacional de renderizar um vídeo completo. Para validar o ChronoEdit, introduzimos o PBench-Edit, um novo benchmark de pares de imagem-prompt para contextos que exigem consistência física, e demonstramos que o ChronoEdit supera as baselines state-of-the-art tanto em fidelidade visual quanto em plausibilidade física. Página do projeto para código e modelos: this https URL.

O pipeline ChronoEdit é desenvolvido pela equipe ChronoEdit. O código original está disponível no GitHub, e os modelos pré-treinados podem ser encontrados na coleção nvidia/ChronoEdit no Hugging Face.

Modelos/LoRAs disponíveis:

Edição de Imagens

import torch
import numpy as np
from diffusers import AutoencoderKLWan, ChronoEditTransformer3DModel, ChronoEditPipeline
from diffusers.utils import export_to_video, load_image
from transformers import CLIPVisionModel
from PIL import Image

model_id = "nvidia/ChronoEdit-14B-Diffusers"
image_encoder = CLIPVisionModel.from_pretrained(model_id, subfolder="image_encoder", dtype=torch.float32)
vae = AutoencoderKLWan.from_pretrained(model_id, subfolder="vae", dtype=torch.float32)
transformer = ChronoEditTransformer3DModel.from_pretrained(model_id, subfolder="transformer", dtype=torch.bfloat16)
pipe = ChronoEditPipeline.from_pretrained(model_id, image_encoder=image_encoder, transformer=transformer, vae=vae, dtype=torch.bfloat16)
pipe.to("cuda")  # or "mps", "xpu", "cpu"

image = load_image(
    "https://huggingface.co/spaces/nvidia/ChronoEdit/resolve/main/examples/3.png"
)
max_area = 720 * 1280
aspect_ratio = image.height / image.width
mod_value = pipe.vae_scale_factor_spatial * pipe.transformer.config.patch_size[1]
height = round(np.sqrt(max_area * aspect_ratio)) // mod_value * mod_value
width = round(np.sqrt(max_area / aspect_ratio)) // mod_value * mod_value
print("width", width, "height", height)
image = image.resize((width, height))
prompt = (
    "The user wants to transform the image by adding a small, cute mouse sitting inside the floral teacup, enjoying a spa bath. The mouse should appear relaxed and cheerful, with a tiny white bath towel draped over its head like a turban. It should be positioned comfortably in the cup’s liquid, with gentle steam rising around it to blend with the cozy atmosphere. "
    "The mouse’s pose should be natural—perhaps sitting upright with paws resting lightly on the rim or submerged in the tea. The teacup’s floral design, gold trim, and warm lighting must remain unchanged to preserve the original aesthetic. The steam should softly swirl around the mouse, enhancing the spa-like, whimsical mood."
)

output = pipe(
    image=image,
    prompt=prompt,
    height=height,
    width=width,
    num_frames=5,
    num_inference_steps=50,
    guidance_scale=5.0,
    enable_temporal_reasoning=False,
    num_temporal_reasoning_steps=0,
).frames[0]
Image.fromarray((output[-1] * 255).clip(0, 255).astype("uint8")).save("output.png")

Opcionalmente, ative o raciocínio temporal para melhorar a consistência física:

output = pipe(
    image=image,
    prompt=prompt,
    height=height,
    width=width,
    num_frames=29,
    num_inference_steps=50,
    guidance_scale=5.0,
    enable_temporal_reasoning=True,
    num_temporal_reasoning_steps=50,
).frames[0]
export_to_video(output, "output.mp4", fps=16)
Image.fromarray((output[-1] * 255).clip(0, 255).astype("uint8")).save("output.png")

Inferência com Lora de Destilação de 8 Etapas

import torch
import numpy as np
from diffusers import AutoencoderKLWan, ChronoEditTransformer3DModel, ChronoEditPipeline
from diffusers.schedulers import UniPCMultistepScheduler
from diffusers.utils import export_to_video, load_image
from transformers import CLIPVisionModel
from PIL import Image

model_id = "nvidia/ChronoEdit-14B-Diffusers"
image_encoder = CLIPVisionModel.from_pretrained(model_id, subfolder="image_encoder", dtype=torch.float32)
vae = AutoencoderKLWan.from_pretrained(model_id, subfolder="vae", dtype=torch.float32)
transformer = ChronoEditTransformer3DModel.from_pretrained(model_id, subfolder="transformer", dtype=torch.bfloat16)
pipe = ChronoEditPipeline.from_pretrained(model_id, image_encoder=image_encoder, transformer=transformer, vae=vae, dtype=torch.bfloat16)
pipe.load_lora_weights("nvidia/ChronoEdit-14B-Diffusers", weight_name="lora/chronoedit_distill_lora.safetensors", adapter_name="distill")
pipe.fuse_lora(adapter_names=["distill"], lora_scale=1.0)
pipe.scheduler = UniPCMultistepScheduler.from_config(pipe.scheduler.config, flow_shift=2.0)
pipe.to("cuda")  # or "mps", "xpu", "cpu"

image = load_image(
    "https://huggingface.co/spaces/nvidia/ChronoEdit/resolve/main/examples/3.png"
)
max_area = 720 * 1280
aspect_ratio = image.height / image.width
mod_value = pipe.vae_scale_factor_spatial * pipe.transformer.config.patch_size[1]
height = round(np.sqrt(max_area * aspect_ratio)) // mod_value * mod_value
width = round(np.sqrt(max_area / aspect_ratio)) // mod_value * mod_value
print("width", width, "height", height)
image = image.resize((width, height))
prompt = (
    "The user wants to transform the image by adding a small, cute mouse sitting inside the floral teacup, enjoying a spa bath. The mouse should appear relaxed and cheerful, with a tiny white bath towel draped over its head like a turban. It should be positioned comfortably in the cup’s liquid, with gentle steam rising around it to blend with the cozy atmosphere. "
    "The mouse’s pose should be natural—perhaps sitting upright with paws resting lightly on the rim or submerged in the tea. The teacup’s floral design, gold trim, and warm lighting must remain unchanged to preserve the original aesthetic. The steam should softly swirl around the mouse, enhancing the spa-like, whimsical mood."
)

output = pipe(
    image=image,
    prompt=prompt,
    height=height,
    width=width,
    num_frames=5,
    num_inference_steps=8,
    guidance_scale=1.0,
    enable_temporal_reasoning=False,
    num_temporal_reasoning_steps=0,
).frames[0]
export_to_video(output, "output.mp4", fps=16)
Image.fromarray((output[-1] * 255).clip(0, 255).astype("uint8")).save("output.png")

Inferência com múltiplos LoRAs

import torch
import numpy as np
from diffusers import AutoencoderKLWan, ChronoEditTransformer3DModel, ChronoEditPipeline
from diffusers.schedulers import UniPCMultistepScheduler
from diffusers.utils import export_to_video, load_image
from transformers import CLIPVisionModel
from PIL import Image

model_id = "nvidia/ChronoEdit-14B-Diffusers"
image_encoder = CLIPVisionModel.from_pretrained(model_id, subfolder="image_encoder", dtype=torch.float32)
vae = AutoencoderKLWan.from_pretrained(model_id, subfolder="vae", dtype=torch.float32)
transformer = ChronoEditTransformer3DModel.from_pretrained(model_id, subfolder="transformer", dtype=torch.bfloat16)
pipe = ChronoEditPipeline.from_pretrained(model_id, image_encoder=image_encoder, transformer=transformer, vae=vae, dtype=torch.bfloat16)
pipe.load_lora_weights("nvidia/ChronoEdit-14B-Diffusers-Paint-Brush-Lora", weight_name="paintbrush_lora_diffusers.safetensors", adapter_name="paintbrush")
pipe.load_lora_weights("nvidia/ChronoEdit-14B-Diffusers", weight_name="lora/chronoedit_distill_lora.safetensors", adapter_name="distill")
pipe.fuse_lora(adapter_names=["paintbrush", "distill"], lora_scale=1.0)
pipe.scheduler = UniPCMultistepScheduler.from_config(pipe.scheduler.config, flow_shift=2.0)
pipe.to("cuda")  # or "mps", "xpu", "cpu"

image = load_image(
    "https://raw.githubusercontent.com/nv-tlabs/ChronoEdit/refs/heads/main/assets/images/input_paintbrush.png"
)
max_area = 720 * 1280
aspect_ratio = image.height / image.width
mod_value = pipe.vae_scale_factor_spatial * pipe.transformer.config.patch_size[1]
height = round(np.sqrt(max_area * aspect_ratio)) // mod_value * mod_value
width = round(np.sqrt(max_area / aspect_ratio)) // mod_value * mod_value
print("width", width, "height", height)
image = image.resize((width, height))
prompt = (
    "Turn the pencil sketch in the image into an actual object that is consistent with the image’s content. The user wants to change the sketch to a crown and a hat."
)

output = pipe(
    image=image,
    prompt=prompt,
    height=height,
    width=width,
    num_frames=5,
    num_inference_steps=8,
    guidance_scale=1.0,
    enable_temporal_reasoning=False,
    num_temporal_reasoning_steps=0,
).frames[0]
export_to_video(output, "output.mp4", fps=16)
Image.fromarray((output[-1] * 255).clip(0, 255).astype("uint8")).save("output_1.png")

ChronoEditPipeline

classe diffusers.ChronoEditPipeline

< >

( tokenizer: AutoTokenizertext_encoder: UMT5EncoderModelimage_encoder: CLIPVisionModelimage_processor: CLIPImageProcessorPiltransformer: ChronoEditTransformer3DModelvae: AutoencoderKLWanscheduler: FlowMatchEulerDiscreteScheduler )

Parâmetros

  • tokenizer (T5Tokenizer) — Tokenizer do T5, especificamente a variante google/umt5-xxl.
  • text_encoder (T5EncoderModel) — T5, especificamente a variante google/umt5-xxl.
  • image_encoder (CLIPVisionModel) — CLIP, especificamente a variante clip-vit-huge-patch14.
  • transformer (WanTransformer3DModel) — Transformer condicional para desruidar os latentes de entrada.
  • scheduler (UniPCMultistepScheduler) — Um scheduler a ser usado em combinação com transformer para desruidar os latentes da imagem codificada.
  • vae (AutoencoderKLWan) — Modelo de Autoencoder Variacional (VAE) para codificar e decodificar vídeos para e a partir de representações latentes.

Pipeline para geração de vídeo a partir de imagem usando Wan.

Este modelo herda de DiffusionPipeline. Consulte a documentação da superclasse para os métodos genéricos implementados para todos os pipelines (download, salvamento, execução em um dispositivo específico, etc.).

__call__

< >

( image: typing.Union[PIL.Image.Image, numpy.ndarray, torch.Tensor, list[PIL.Image.Image], list[numpy.ndarray], list[torch.Tensor]]prompt: str | list[str] = Nonenegative_prompt: str | list[str] = Noneheight: int = 480width: int = 832num_frames: int = 81num_inference_steps: int = 50guidance_scale: float = 5.0num_videos_per_prompt: int | None = 1generator: typing.Union[torch.Generator, list[torch.Generator], NoneType] = Nonelatents: typing.Optional[torch.Tensor] = Noneprompt_embeds: typing.Optional[torch.Tensor] = Nonenegative_prompt_embeds: typing.Optional[torch.Tensor] = Noneimage_embeds: typing.Optional[torch.Tensor] = Noneoutput_type: str | None = 'np'return_dict: bool = Trueattention_kwargs: dict[str, typing.Any] | None = Nonecallback_on_step_end: typing.Optional[typing.Callable[[int, int, NoneType], diffusers.callbacks.PipelineCallback | diffusers.callbacks.MultiPipelineCallbacks]] = Nonecallback_on_step_end_tensor_inputs: list[str] = ['latents']max_sequence_length: int = 512enable_temporal_reasoning: bool = Falsenum_temporal_reasoning_steps: int = 0 ) → ~ChronoEditPipelineOutput or tuple

Parâmetros

  • image (PipelineImageInput) — A imagem de entrada para condicionar a geração. Deve ser uma imagem, uma lista de imagens ou um torch.Tensor.
  • prompt (str ou list[str], opcional) — O prompt ou os prompts para orientar a geração da imagem. Se não for definido, é necessário passar prompt_embeds em vez disso.
  • negative_prompt (str ou list[str], opcional) — O prompt ou os prompts que não devem orientar a geração da imagem. Se não for definido, é necessário passar negative_prompt_embeds em vez disso. Ignorado quando não se usa orientação (ou seja, ignorado se guidance_scale for menor que 1).
  • height (int, padrão 480) — A altura do vídeo gerado.
  • width (int, padrão 832) — A largura do vídeo gerado.
  • num_frames (int, padrão 81) — O número de quadros no vídeo gerado.
  • num_inference_steps (int, padrão 50) — O número de etapas de desruido. Mais etapas de desruido geralmente resultam em uma imagem de maior qualidade, em detrimento de uma inferência mais lenta.
  • guidance_scale (float, padrão 5.0) — Escala de orientação definida em Classifier-Free Diffusion Guidance. guidance_scale é definido como w da equação 2. de Imagen Paper. A escala de orientação é ativada ao definir guidance_scale > 1. Uma escala de orientação maior incentiva a geração de imagens que estão intimamente ligadas ao prompt de texto, geralmente em detrimento de uma menor qualidade de imagem.
  • num_videos_per_prompt (int, opcional, padrão 1) — O número de imagens a serem geradas por prompt.
  • generator (torch.Generator ou list[torch.Generator], opcional) — Um torch.Generator para tornar a geração determinística.
  • latents (torch.Tensor, opcional) — Latentes ruidosos pré-gerados, amostrados de uma distribuição gaussiana, a serem usados como entradas para a geração de imagens. Pode ser usado para ajustar a mesma geração com diferentes prompts. Se não for fornecido, um tensor de latentes é gerado por amostragem usando o generator aleatório fornecido.
  • prompt_embeds (torch.Tensor, opcional) — Incorporações de texto pré-geradas. Podem ser usadas para ajustar facilmente as entradas de texto (ponderação do prompt). Se não forem fornecidas, as incorporações de texto são geradas a partir do argumento de entrada prompt.
  • negative_prompt_embeds (torch.Tensor, opcional) — Incorporações de texto pré-geradas. Podem ser usadas para ajustar facilmente as entradas de texto (ponderação do prompt). Se não forem fornecidas, as incorporações de texto são geradas a partir do argumento de entrada negative_prompt.
  • image_embeds (torch.Tensor, opcional) — Incorporações de imagem pré-geradas. Podem ser usadas para ajustar facilmente as entradas de imagem (ponderação). Se não forem fornecidas, as incorporações de imagem são geradas a partir do argumento de entrada image.
  • output_type (str, opcional, padrão "np") — O formato de saída da imagem gerada. Escolha entre PIL.Image ou np.array.
  • return_dict (bool, opcional, padrão True) — Se deve ou não retornar um ChronoEditPipelineOutput em vez de uma tupla simples.
  • attention_kwargs (dict, opcional) — Um dicionário de kwargs que, se especificado, é passado ao AttentionProcessor conforme definido em self.processor em diffusers.models.attention_processor.
  • callback_on_step_end (Callable, PipelineCallback, MultiPipelineCallbacks, opcional) — Uma função ou uma subclasse de PipelineCallback ou MultiPipelineCallbacks que é chamada no final de cada etapa de remoção de ruído durante a inferência, com os seguintes argumentos: callback_on_step_end(self: DiffusionPipeline, step: int, timestep: int, callback_kwargs: Dict). callback_kwargs incluirá uma lista de todos os tensores, conforme especificado por callback_on_step_end_tensor_inputs.
  • callback_on_step_end_tensor_inputs (List, opcional) — A lista de entradas de tensor para a função callback_on_step_end. Os tensores especificados na lista serão passados como argumento callback_kwargs. Você só poderá incluir variáveis listadas no atributo ._callback_tensor_inputs da sua classe de pipeline.
  • max_sequence_length (int, padrão 512) — O comprimento máximo da sequência do codificador de texto. Se o prompt for mais longo que isso, ele será truncado. Se o prompt for mais curto, ele será preenchido até esse comprimento.
  • enable_temporal_reasoning (bool, opcional, padrão False) — Se deve habilitar o raciocínio temporal.
  • num_temporal_reasoning_steps (int, opcional, padrão 0) — O número de etapas para habilitar o raciocínio temporal.

Retorna

~ChronoEditPipelineOutput ou tuple

Se return_dict for True, ChronoEditPipelineOutput é retornado; caso contrário, uma tuple é retornada, em que o primeiro elemento é uma lista com as imagens geradas e o segundo elemento é uma lista de bools indicando se a imagem gerada correspondente contém conteúdo “not-safe-for-work” (nsfw).

A função de chamada do pipeline para geração.

Exemplos:

>>> import torch
>>> import numpy as np
>>> from diffusers import AutoencoderKLWan, ChronoEditTransformer3DModel, ChronoEditPipeline
>>> from diffusers.utils import export_to_video, load_image
>>> from transformers import CLIPVisionModel

>>> # Available models: nvidia/ChronoEdit-14B-Diffusers
>>> model_id = "nvidia/ChronoEdit-14B-Diffusers"
>>> image_encoder = CLIPVisionModel.from_pretrained(
...     model_id, subfolder="image_encoder", torch_dtype=torch.float32
... )
>>> vae = AutoencoderKLWan.from_pretrained(model_id, subfolder="vae", torch_dtype=torch.float32)
>>> transformer = ChronoEditTransformer3DModel.from_pretrained(
...     model_id, subfolder="transformer", torch_dtype=torch.bfloat16
... )
>>> pipe = ChronoEditPipeline.from_pretrained(
...     model_id, vae=vae, image_encoder=image_encoder, transformer=transformer, torch_dtype=torch.bfloat16
... )
>>> pipe.to("cuda")

>>> image = load_image("https://huggingface.co/spaces/nvidia/ChronoEdit/resolve/main/examples/3.png")
>>> max_area = 720 * 1280
>>> aspect_ratio = image.height / image.width
>>> mod_value = pipe.vae_scale_factor_spatial * pipe.transformer.config.patch_size[1]
>>> height = round(np.sqrt(max_area * aspect_ratio)) // mod_value * mod_value
>>> width = round(np.sqrt(max_area / aspect_ratio)) // mod_value * mod_value
>>> image = image.resize((width, height))
>>> prompt = (
...     "The user wants to transform the image by adding a small, cute mouse sitting inside the floral teacup, enjoying a spa bath. The mouse should appear relaxed and cheerful, with a tiny white bath towel draped over its head like a turban. It should be positioned comfortably in the cup’s liquid, with gentle steam rising around it to blend with the cozy atmosphere. "
...     "The mouse’s pose should be natural—perhaps sitting upright with paws resting lightly on the rim or submerged in the tea. The teacup’s floral design, gold trim, and warm lighting must remain unchanged to preserve the original aesthetic. The steam should softly swirl around the mouse, enhancing the spa-like, whimsical mood."
... )

>>> output = pipe(
...     image=image,
...     prompt=prompt,
...     height=height,
...     width=width,
...     num_frames=5,
...     guidance_scale=5.0,
...     enable_temporal_reasoning=False,
...     num_temporal_reasoning_steps=0,
... ).frames[0]
>>> export_to_video(output, "output.mp4", fps=16)

encode_prompt

< >

( prompt: str | list[str]negative_prompt: str | list[str] | None = Nonedo_classifier_free_guidance: bool = Truenum_videos_per_prompt: int = 1prompt_embeds: typing.Optional[torch.Tensor] = Nonenegative_prompt_embeds: typing.Optional[torch.Tensor] = Nonemax_sequence_length: int = 226device: typing.Optional[torch.device] = Nonedtype: typing.Optional[torch.dtype] = None )

Parâmetros

  • prompt (str ou list[str], opcional) — prompt a ser codificado
  • negative_prompt (str ou list[str], opcional) — O prompt ou os prompts que não devem orientar a geração da imagem. Se não for definido, é necessário passar negative_prompt_embeds em vez disso. Ignorado quando não se usa orientação (ou seja, ignorado se guidance_scale for menor que 1).
  • do_classifier_free_guidance (bool, opcional, padrão True) — Se deve ou não usar classifier free guidance.
  • num_videos_per_prompt (int, opcional, padrão 1) — Número de vídeos que devem ser gerados por prompt. Dispositivo torch para colocar os embeddings resultantes
  • prompt_embeds (torch.Tensor, opcional) — Incorporações de texto pré-geradas. Podem ser usadas para ajustar facilmente as entradas de texto, por exemplo, ponderação de prompts. Se não forem fornecidas, as incorporações de texto serão geradas a partir do argumento de entrada prompt.
  • negative_prompt_embeds (torch.Tensor, opcional) — Incorporações de texto negativas pré-geradas. Pode ser usado para ajustar facilmente as entradas de texto, por exemplo, ponderação de prompts. Se não for fornecido, negative_prompt_embeds será gerado a partir do argumento de entrada negative_prompt.
  • device — (torch.device, opcional): dispositivo torch
  • dtype — (torch.dtype, opcional): dtype do torch

Codifica o prompt em estados ocultos do codificador de texto.

ChronoEditPipelineOutput

classe diffusers.pipelines.chronoedit.pipeline_output.ChronoEditPipelineOutput

< >

( frames: Tensor )

Parâmetros

  • frames (torch.Tensor, np.ndarray ou list[list[PIL.Image.Image]]) — Lista de saídas de vídeo - Pode ser uma lista aninhada de comprimento batch_size, com cada sublista contendo sequências de imagens PIL desruidas de comprimento num_frames. Também pode ser um array NumPy ou tensor Torch de forma (batch_size, num_frames, channels, height, width).

Classe de saída para pipelines do ChronoEdit.

Update on GitHub