はじめに
以前「Rerender A Video」の記事を書きました。touch-sp.hatenablog.com
今回、新たにDiffusersから使えるようになったのでさっそく試してみました。
Video2Videoに関しては「AnimateDiff」と同等、またはそれ以上の結果が得られました。
「AnimateDiff」を使ったVideo2Videoの結果はこちら。
support-touchsp.blogspot.com
PC環境
Windows 11 CUDA 11.8 Python 3.11
Python環境構築
pip install torch==2.1.2+cu118 torchvision==0.16.2+cu118 --index-url https://download.pytorch.org/whl/cu118 pip install diffusers[torch] pip install transformers omegaconf opencv-python
gmflowのインストール
「please install gmflow」と書かれていますが、GitHubのリポジトリをクローンするだけで動作しました。git clone https://github.com/haofeixu/gmflow
rerender_a_video.pyの修正
まずは「rerender_a_video.py」をこちらからダウンロードします。37行目から41行目を修正します。
修正前
gmflow_dir = "/path/to/gmflow" sys.path.insert(0, gmflow_dir) from gmflow.gmflow import GMFlow # noqa: E402 from utils.utils import InputPadder # noqa: E402
修正後
#gmflow_dir = "/path/to/gmflow" #sys.path.insert(0, gmflow_dir) from gmflow.gmflow.gmflow import GMFlow # noqa: E402 from gmflow.utils.utils import InputPadder # noqa: E402
フォルダ構造
以下のようなフォルダ構成にしました。「run.py」は後述するスクリプトが書かれたPythonファイルです。
works: ├─controlnet │ └─control_v11p_sd15_canny ├─custom_pipeline │ └─rerender_a_video.py ├─gmflow ├─model │ └─mistoonAnimev20_ema ├─vae │ └─vae-ft-mse-840000-ema-pruned.safetensors ├─dance512.mp4 └─run.py
Pythonスクリプト
from diffusers import DiffusionPipeline, ControlNetModel, AutoencoderKL, DDIMScheduler from diffusers.utils import export_to_gif import numpy as np import torch import cv2 from PIL import Image def video_to_frame(video_path: str, interval: int): vidcap = cv2.VideoCapture(video_path) success = True count = 0 res = [] while success: count += 1 success, image = vidcap.read() if count % interval != 1: continue if image is not None: image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) res.append(image) vidcap.release() return res input_video_path = 'dance512.mp4' input_interval = 2 frames = video_to_frame( input_video_path, input_interval) control_frames = [] for frame in frames: np_image = cv2.Canny(frame, 50, 100) np_image = np_image[:, :, None] np_image = np.concatenate([np_image, np_image, np_image], axis=2) canny_image = Image.fromarray(np_image) control_frames.append(canny_image) controlnet = ControlNetModel.from_pretrained( "controlnet/control_v11p_sd15_canny", torch_dtype=torch.float16 ) pipe = DiffusionPipeline.from_pretrained( "model/mistoonAnimev20_ema", controlnet=controlnet, custom_pipeline='custom_pipeline/rerender_a_video.py', torch_dtype=torch.float16 ) pipe.vae = AutoencoderKL.from_single_file( "vae/vae-ft-mse-840000-ema-pruned.safetensors", torch_dtype=torch.float16 ) pipe.scheduler = DDIMScheduler.from_config(pipe.scheduler.config) pipe.to("cuda") generator = torch.manual_seed(0) frames = [Image.fromarray(frame) for frame in frames] output_frames = pipe( prompt="anime style, high quality, best quality, man with black hair, wearing sunglasses, black sweater, dancing", negative_prompt='longbody, lowres, bad anatomy, bad hands, missing fingers, extra digit, fewer digits, cropped, worst quality, low quality', frames=frames, control_frames=control_frames, num_inference_steps=20, strength=0.6, guidance_scale=7.5, controlnet_conditioning_scale=0.7, generator=generator, warp_start=0.0, warp_end=0.1, mask_start=0.5, mask_end=0.8, mask_strength=0.1 ).frames export_to_gif(output_frames, "result.gif")
実行
python run.py
結果
作成された動画はGoogle Bloggerに載せています。
support-touchsp.blogspot.com