Diffusers documentation
ChronoEdit
ChronoEdit
ChronoEdit: Towards Temporal Reasoning for Image Editing and World Simulation dari NVIDIA dan University of Toronto, oleh 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.
TL;DR: ChronoEdit membingkai ulang pengeditan gambar sebagai tugas generasi video, menggunakan gambar input dan gambar yang telah diedit sebagai bingkai awal/akhir untuk memanfaatkan model video pralatih dengan konsistensi temporal. Tahap penalaran temporal memperkenalkan token penalaran untuk memastikan edit yang secara fisika masuk akal dan memvisualisasikan lintasan pengeditan.
Perkembangan terbaru dalam model generatif besar telah sangat meningkatkan kemampuan pengeditan gambar dan pembuatan gambar dalam konteks, namun masih terdapat kesenjangan kritis dalam memastikan konsistensi fisik, di mana objek yang diedit harus tetap koheren. Kemampuan ini sangat penting untuk tugas-tugas yang berkaitan dengan simulasi dunia. Dalam makalah ini, kami memperkenalkan ChronoEdit, sebuah kerangka kerja yang membingkai ulang pengeditan gambar sebagai masalah pembuatan video. Pertama, ChronoEdit memperlakukan gambar input dan gambar yang diedit sebagai bingkai pertama dan terakhir dari sebuah video, sehingga memungkinkan pemanfaatan model generatif video pralatih besar yang menangkap tidak hanya penampilan objek tetapi juga fisika implisit dari gerakan dan interaksi melalui konsistensi temporal yang dipelajari. Kedua, ChronoEdit memperkenalkan tahap penalaran temporal yang secara eksplisit melakukan pengeditan pada saat inferensi. Dalam pengaturan ini, bingkai target didenorkan secara bersama-sama dengan token penalaran untuk membayangkan lintasan pengeditan yang masuk akal, yang membatasi ruang solusi pada transformasi yang layak secara fisik. Token penalaran kemudian dibuang setelah beberapa langkah untuk menghindari biaya komputasi tinggi dari merender video penuh. Untuk memvalidasi ChronoEdit, kami memperkenalkan PBench-Edit, sebuah benchmark baru berupa pasangan gambar-prompt untuk konteks yang memerlukan konsistensi fisik, dan menunjukkan bahwa ChronoEdit melampaui baseline state-of-the-art dalam hal kesetiaan visual dan kelayakan fisik. Halaman proyek untuk kode dan model: this https URL.
Pipeline ChronoEdit dikembangkan oleh Tim ChronoEdit. Kode aslinya tersedia di GitHub, dan model pretrained dapat ditemukan di koleksi nvidia/ChronoEdit di Hugging Face.
Model/LoRA yang Tersedia:
- nvidia/ChronoEdit-14B-Diffusers
- nvidia/ChronoEdit-14B-Diffusers-Upscaler-Lora
- nvidia/ChronoEdit-14B-Diffusers-Paint-Brush-Lora
Pengeditan Gambar
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")Secara opsional, aktifkan penalaran temporal untuk konsistensi fisik yang lebih baik:
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")Inferensi dengan Lora Distilasi 8-Langkah
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")Inferensi dengan Beberapa LoRA
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
kelas diffusers.ChronoEditPipeline
< source >( tokenizer: AutoTokenizertext_encoder: UMT5EncoderModelimage_encoder: CLIPVisionModelimage_processor: CLIPImageProcessorPiltransformer: ChronoEditTransformer3DModelvae: AutoencoderKLWanscheduler: FlowMatchEulerDiscreteScheduler )
Parameter
- tokenizer (
T5Tokenizer) — Tokenizer dari T5, khususnya varian google/umt5-xxl. - text_encoder (
T5EncoderModel) — T5, khususnya varian google/umt5-xxl. - image_encoder (
CLIPVisionModel) — CLIP, khususnya varian clip-vit-huge-patch14. - transformer (WanTransformer3DModel) — Transformer bersyarat untuk menghilangkan noise pada latens input.
- scheduler (UniPCMultistepScheduler) —
Scheduler yang digunakan bersama
transformeruntuk menghilangkan noise pada latens gambar yang telah dikodekan. - vae (AutoencoderKLWan) — Model Variational Auto-Encoder (VAE) untuk mengodekan dan mendekodekan video ke dan dari representasi laten.
Pipeline untuk generasi gambar-ke-video menggunakan Wan.
Model ini mewarisi dari DiffusionPipeline. Periksa dokumentasi kelas induk untuk metode generik yang diimplementasikan untuk semua pipeline (mengunduh, menyimpan, menjalankan pada perangkat tertentu, dll.).
__call__
< source >( 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 = ['latents']max_sequence_length: int = 512enable_temporal_reasoning: bool = Falsenum_temporal_reasoning_steps: int = 0 ) → ~ChronoEditPipelineOutput or tuple
Parameter
- image (
PipelineImageInput) — Gambar input untuk mengondisikan generasi. Harus berupa gambar, daftar gambar, atautorch.Tensor. - prompt (
strataulist[str], opsional) — Prompt atau prompt-prompt untuk mengarahkan generasi gambar. Jika tidak didefinisikan, Anda harus meneruskanprompt_embedssebagai gantinya. - negative_prompt (
strataulist[str], opsional) — Prompt atau prompt-prompt yang tidak digunakan untuk mengarahkan generasi gambar. Jika tidak didefinisikan, Anda harus meneruskannegative_prompt_embedssebagai gantinya. Diabaikan jika tidak menggunakan guidance (yaitu, diabaikan jikaguidance_scalekurang dari1). - height (
int, defaultnya480) — Tinggi video yang dihasilkan. - width (
int, defaultnya832) — Lebar video yang dihasilkan. - num_frames (
int, defaultnya81) — Jumlah frame dalam video yang dihasilkan. - num_inference_steps (
int, defaultnya50) — Jumlah langkah denoising. Semakin banyak langkah denoising, biasanya menghasilkan gambar dengan kualitas lebih tinggi, namun dengan biaya inferensi yang lebih lambat. - guidance_scale (
float, defaultnya5.0) — Skala panduan seperti yang didefinisikan dalam Classifier-Free Diffusion Guidance.guidance_scaledidefinisikan sebagaiwdari persamaan 2. pada Imagen Paper. Skala panduan diaktifkan dengan mengaturguidance_scale > 1. Skala panduan yang lebih tinggi mendorong generasi gambar yang sangat terkait denganpromptteks, biasanya dengan mengorbankan kualitas gambar yang lebih rendah. - num_videos_per_prompt (
int, opsional, default 1) — Jumlah gambar yang akan dihasilkan per prompt. - generator (
torch.Generatorataulist[torch.Generator], opsional) —torch.Generatoruntuk membuat generasi menjadi deterministik. - latents (
torch.Tensor, opsional) — Latents berisik yang telah dibuat sebelumnya dan diambil dari distribusi Gaussian, untuk digunakan sebagai input untuk generasi gambar. Dapat digunakan untuk menyesuaikan generasi yang sama dengan prompt yang berbeda. Jika tidak disediakan, tensor latents akan dibuat dengan pengambilan sampel menggunakangeneratoracak yang diberikan. - prompt_embeds (
torch.Tensor, opsional) — Embedding teks yang sudah dibuat sebelumnya. Dapat digunakan untuk dengan mudah menyesuaikan input teks (penimbangan prompt). Jika tidak disediakan, embedding teks akan dihasilkan dari argumen inputprompt. - negative_prompt_embeds (
torch.Tensor, opsional) — Embedding teks yang sudah dibuat sebelumnya. Dapat digunakan untuk dengan mudah menyesuaikan input teks (penimbangan prompt). Jika tidak disediakan, embedding teks akan dihasilkan dari argumen inputnegative_prompt. - image_embeds (
torch.Tensor, opsional) — Embedding gambar yang sudah dibuat sebelumnya. Dapat digunakan untuk dengan mudah menyesuaikan input gambar (penimbangan). Jika tidak disediakan, embedding gambar akan dihasilkan dari argumen inputimage. - output_type (
str, opsional, defaultnya"np") — Format output dari gambar yang dihasilkan. Pilih antaraPIL.Imageataunp.array. - return_dict (
bool, opsional, defaultTrue) — Apakah akan mengembalikanChronoEditPipelineOutputalih-alih tuple biasa. - attention_kwargs (
dict, opsional) — Kamus kwargs yang jika ditentukan akan diteruskan keAttentionProcessorseperti yang didefinisikan di bawahself.processordalam diffusers.models.attention_processor. - callback_on_step_end (
Callable,PipelineCallback,MultiPipelineCallbacks, opsional) — Fungsi atau subkelas dariPipelineCallbackatauMultiPipelineCallbacksyang dipanggil di akhir setiap langkah denoising selama inferensi, dengan argumen berikut:callback_on_step_end(self: DiffusionPipeline, step: int, timestep: int, callback_kwargs: Dict).callback_kwargsakan berisi daftar semua tensor sesuai yang ditentukan olehcallback_on_step_end_tensor_inputs. - callback_on_step_end_tensor_inputs (
List, opsional) — Daftar input tensor untuk fungsicallback_on_step_end. Tensor yang ditentukan dalam daftar akan diteruskan sebagai argumencallback_kwargs. Anda hanya dapat menyertakan variabel yang tercantum dalam atribut._callback_tensor_inputsdari kelas pipeline Anda. - max_sequence_length (
int, defaultnya512) — Panjang maksimum sekuens dari text encoder. Jika prompt lebih panjang dari ini, prompt akan dipotong. Jika prompt lebih pendek, prompt akan di-pad hingga panjang ini. - enable_temporal_reasoning (
bool, opsional, defaultFalse) — Apakah akan mengaktifkan penalaran temporal. - num_temporal_reasoning_steps (
int, opsional, defaultnya0) — Jumlah langkah untuk mengaktifkan penalaran temporal.
Mengembalikan
~ChronoEditPipelineOutput atau tuple
Jika return_dict adalah True, ChronoEditPipelineOutput dikembalikan, selain itu sebuah tuple dikembalikan
di mana elemen pertama adalah daftar dengan gambar yang dihasilkan dan elemen kedua adalah daftar bool
yang menunjukkan apakah gambar yang dihasilkan yang sesuai mengandung konten “not-safe-for-work” (nsfw).
Fungsi panggilan untuk pipeline pada generasi.
Contoh:
>>> 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
< source >( 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 )
Parameter
- prompt (
strataulist[str], opsional) — prompt yang akan dienkod - negative_prompt (
strataulist[str], opsional) — Prompt atau prompt-prompt yang tidak digunakan untuk mengarahkan generasi gambar. Jika tidak didefinisikan, Anda harus meneruskannegative_prompt_embedssebagai gantinya. Diabaikan jika tidak menggunakan guidance (yaitu, diabaikan jikaguidance_scalekurang dari1). - do_classifier_free_guidance (
bool, opsional, defaultTrue) — Apakah akan menggunakan classifier free guidance atau tidak. - num_videos_per_prompt (
int, opsional, default 1) — Jumlah video yang harus dihasilkan per prompt. perangkat torch untuk menempatkan embedding yang dihasilkan - prompt_embeds (
torch.Tensor, opsional) — Embedding teks yang sudah dibuat sebelumnya. Dapat digunakan untuk dengan mudah menyesuaikan input teks, misalnya pembobotan prompt. Jika tidak disediakan, embedding teks akan dihasilkan dari argumen inputprompt. - negative_prompt_embeds (
torch.Tensor, opsional) — Embedding teks negatif yang telah dibuat sebelumnya. Dapat digunakan untuk dengan mudah menyesuaikan input teks, misalnya penimbangan prompt. Jika tidak disediakan, negative_prompt_embeds akan dibuat dari argumen inputnegative_prompt. - device — (
torch.device, opsional): perangkat torch - dtype — (
torch.dtype, opsional): torch dtype
Mengkodekan prompt menjadi hidden states dari text encoder.
ChronoEditPipelineOutput
kelas diffusers.pipelines.chronoedit.pipeline_output.ChronoEditPipelineOutput
< source >( frames: Tensor )
Parameter
- frames (
torch.Tensor,np.ndarray, atau list[list[PIL.Image.Image]]) — Daftar output video - Dapat berupa daftar bersarang dengan panjangbatch_size,di mana setiap sub-daftar berisi urutan gambar PIL yang telah didenois dengan panjangnum_frames.Dapat juga berupa array NumPy atau tensor Torch dengan bentuk(batch_size, num_frames, channels, height, width).
Kelas output untuk pipeline ChronoEdit.