はじめに
「Long Weighted Prompt Pipeline」はプロンプトの重み付けをする時にA1111のスタイルが使え、かつ長いプロンプトが使用できるようになるパイプラインです。Diffusersではそういった用途にcompelというライブラリを使用するのですが、はっきり言って使い勝手は良くありません。compelの代わりになるのが「Long Weighted Prompt Pipeline」です。「Long Weighted Prompt Pipeline」自体は以前からありましたがclip skipやFreeUは使えませんでした。最近使えるようになったとのことでさっそく使ってみました。結果
clip skip
左がノーマル、右がclip skip = 1を設定した時の画像です。FreeU
左がノーマル、右がFreeUを使用した時の画像です。both clip skip and FreeU
感想
clip skipはアニメ画像を扱うモデルで効果が高いとされています。今回は使うべきではなかったのかもしれません。FreeUは画質を良くしますが、手や腕の破綻が増える印象です。たまたまかも知れませんが・・・。Pythonスクリプト
from diffusers import DiffusionPipeline, DPMSolverMultistepScheduler import torch import os model_id = "model/hadukiMix_v16Typek" pipe = DiffusionPipeline.from_pretrained( model_id, torch_dtype=torch.float16, variant="fp16", custom_pipeline= "custom-pipeline/lpw_stable_diffusion_xl.py", ) pipe.scheduler = DPMSolverMultistepScheduler.from_config( pipe.scheduler.config, algorithm_type="sde-dpmsolver++", use_karras_sigmas=True ) pipe.to("cuda") prompt = "beautiful japanese woman with smile, (35yo:1.5), in the cafe, sitting on the sofa, 8k, RAW photo, (best quality), masterpiece, photo-realistic, focus, professional lighting" negative_prompt = "(worst quality:1.3), (low quality:1.3)" seed_list = [x for x in range(10000, 20000, 1000)] # normal os.makedirs("normal", exist_ok=True) for seed in seed_list: generator = torch.manual_seed(seed) image = pipe( prompt=prompt, negative_prompt=negative_prompt, generator=generator, num_inference_steps=30, width=1152, height=896 ).images[0] image.save(os.path.join("normal", f"seed{seed}.png")) # clip skip os.makedirs("with_clipskip", exist_ok=True) for seed in seed_list: generator = torch.manual_seed(seed) image = pipe( prompt=prompt, negative_prompt=negative_prompt, generator=generator, num_inference_steps=30, width=1152, height=896, clip_skip=1, ).images[0] image.save(os.path.join("with_clipskip", f"seed{seed}.png")) # freeu os.makedirs("with_freeu", exist_ok=True) pipe.enable_freeu(s1=0.6, s2=0.4, b1=1.1, b2=1.2) for seed in seed_list: generator = torch.manual_seed(seed) image = pipe( prompt=prompt, negative_prompt=negative_prompt, generator=generator, num_inference_steps=30, width=1152, height=896 ).images[0] image.save(os.path.join("with_freeu", f"seed{seed}.png")) # both clip skip and freeu os.makedirs("both", exist_ok=True) for seed in seed_list: generator = torch.manual_seed(seed) image = pipe( prompt=prompt, negative_prompt=negative_prompt, generator=generator, num_inference_steps=30, width=1152, height=896, clip_skip=1 ).images[0] image.save(os.path.join("both", f"seed{seed}.png")) import glob import cv2 import numpy as np image_list = [os.path.basename(x) for x in glob.glob("normal/*.png")] # clip skip os.makedirs("stackimage-clipskip", exist_ok=True) for image in image_list: im1 = cv2.imread(os.path.join("normal", image)) im2 = cv2.imread(os.path.join("with_clipskip", image)) stack_image = np.hstack([im1, im2]) cv2.imwrite(os.path.join("stackimage-clipskip", image), stack_image) # freeu os.makedirs("stackimage-freeu", exist_ok=True) for image in image_list: im1 = cv2.imread(os.path.join("normal", image)) im2 = cv2.imread(os.path.join("with_freeu", image)) stack_image = np.hstack([im1, im2]) cv2.imwrite(os.path.join("stackimage-freeu", image), stack_image) # both os.makedirs("stackimage-both", exist_ok=True) for image in image_list: im1 = cv2.imread(os.path.join("normal", image)) im2 = cv2.imread(os.path.join("both", image)) stack_image = np.hstack([im1, im2]) cv2.imwrite(os.path.join("stackimage-both", image), stack_image)