見出し画像

DiffusersPipelineManagerにIP-Adapter機能を追加


DiffuserPipelineManager設定できるpipeline

t2i
i2i
inpaint
ここらはVRAM消費大きい
t2i_Multi-IP-Adapter
t2i_IP-Adapter
i2i_Multi-IP-Adapter
i2i_IP-Adapter
inpaint_IP-Adapter
Control-NET Canny
Control-NET Openpose
Control-NET T2i-adapter
Control-NET Depth

DiffusersPipelineManaghe V1.1の主なクラス

クラスの定義

呼び出すプログラムで
Df=DiffusersPipelineManager
とすることで初期化される

class DiffusersPipelineManager:

pipeline_init pipelineの定義

modeを指定してpipelineを作成する

mode:str="t2i" #指定できるpipe名  
  t2i/i2i
  i2i_pipe/inpaint_pipe
  canny/openpose/canny_openpose/depth/t2i_adapter_canny pipeline=None #pipeloneの再利用の時に参照する生成済みpipeline名指定  
model:str=None #ロードするSDXLモデル名
vae_en:bool=True #VAE有効無効設定
vae_path:str=None #VAE有効時のVAEへのパス lcm_lora_en:bool=True #LCM -LoRA有効無効設定
無効にするとLCM-LoRAとLCMスケジュ-ラがロードされない
lcm_lora_path=None #LCM -LoRA有効のLCM-LoRAへのパス
lora_en:bool=False   #Style -LoRAの有効無効設定 lola_models:list=None #Style -LoRAの有効時のStyle-LoRAへのパスリスト             複数のStyle-LoRAをロード出来る
ddism_en:bool=False # ddism¥スケジューラ有効化 single_ip:bool=False # IP-Adapter 有効化
mul_ip:bool=False # Multi IP-Adapter 有効化 ip_scal1:float=None # IP-AdapterのScale/Multi IP-Adapter のScale1 ip_scal2:float=None # Multi IP-Adapter のScale2 set_unet:bool=False #UNETの有効無効設定

generate 画像の生成

3種類の生成モード共通のパラメータ
pipe
 利用するpipeを指定。必ず指定しなければならない。
image=None,
 入力イメージを指定する。パスではなくイメージオブジェクト
 (PILが標準、CV2も使えるはず(ためしていない)
mask_image=None,
 インペイントなどのマスクイメージを指定。
 パスではなくイメージオブジェクト(
 PILが標準、CV2も使えるはず(ためしていない)
embe:bool=True,
 プロンプトエンべデッディング有効・無効。有効時はCONPLEによる
 エンべディングを行う。プロンプトのウエイト指定も可能
 ウエイト指定の例  prompt = "a red cat++ playing with a ball----" +はprompt Enhace /-は Reduce
prompt:str=None,
 プロンプト 文章も使えます。ただし英語のみ
conditioning=None,
pooled=None,
 conditioningとpooledはプロンプトエンべデッディングでCONPLEから
 得られる変数を記述
negative_prompt=None,
 ネガティブプロンプト
num_inference_steps:int=4,
 生成時のSTEP、大きいほうがきれいになる。
 lmcは4が標準だが適時上げる
strength:float=0.1,
 プロンプトの効きを調整する0〜1.0
guidance_scale:float=1.0,
 ガイダンススケール 1.0で無効、大きいと生成時間が伸びる。
 上げれば画像がきれいになるわけででない
generator=None,
 SEEDを指定する。
 例 generator = torch.manual_seed(0 )でマニュアルで SEED指定
height:int = None,
 画像の高さを指定する
width:int = None,
 画像の幅を指定する
num_images_per_prompt:int = 1,
 プロンプトあたりの生成画像数を指定して複数生成させることが出来る
guess_mode:bool=None,
 ガウシアン効果の有効無効指定
freeu:bool=False,
 freeu効果の有効無効指定。有効にすると生成画像が鮮やかな色になる。
freeu_list:list=[0.9, 0.2,1.2,1.4],
 freeu効果のパラメータ指定
output_type:str="pil",
 画像出力形式を指定する。ndarreyが指定可能("nd")
crops_coords_top_left=(0, 0),
 生成する主画像の位置を指定する
controlnet_conditioning_scale=1.0,
 コントロールネットの効き具合を指定する
ip_adapter:bool=False,
 IP-Adaperを使う
style_images:list=None,
 Multi-IP-Adaper用のStyle画像リスト
face_image=None,
 IP-Adaper用の入力画像 / Multi-IP-Adaper用のface画像リスト

T2I-Adaper特有のパラメータ
adapter_conditioning_scale:float=None,
adapter_conditioning_factor:int=None,
 アダプタの効き具合の設定をする

シンプルなt2iテストコード

import torch
from PIL import Image
from  DiffusersPipelineManager_v1_1 import DiffusersPipelineManager

t2i=True
 #DiffusersPipelineManagerの定義と初期化 
Df=DiffusersPipelineManager() #デフォルトpipeのロード 
model="./models/animagine-xl-2.0/animagine-xl-2.0.safetensors"
pipe_t2i=Df.pipeline_init("t2i",model=model)
pipe_i2i=Df.pipeline_init("i2i_pipe",pipeline=pipe_t2i)#pipelineの使い回し
pipe_inpaint=Df.pipeline_init("inpaint_pipe",pipeline=pipe_t2i)#pipelineの使い回し 

if t2i:
    #-----LCM "t2i" アニメテスト
    #modelとpipeはデフォルトを使う 
    #--SDXL embeddingなし
    prompt = "masterpiece, best quality, 1girl, solo, long hair,  white shirt, serafuku,  brown hair,looking at viewer,blush,smile, bangs,blue eyes, simple background,t-shirt,white background,closed mouth,standing,white t-shirt,shorts, short shorts,headphones,black shorts,light brown hair,blue shorts ,running"
    image_count=2
    generator = torch.manual_seed(0 )
    x_image_list=Df.generate( pipe_t2i ,
              prompt=prompt ,
              embe=False,  generator=generator , freeu=True ,
              num_images_per_prompt=image_count,
              height=512,width=512)
    x_image_list[0].show()
    x_image_list[1].show()

DiffusersPipelineManager V1.1 全コード

from diffusers import StableDiffusionXLImg2ImgPipeline  ,  StableDiffusionXLPipeline  ,  AutoPipelineForText2Image, AutoPipelineForImage2Image ,StableDiffusionDepth2ImgPipeline, StableDiffusionXLInpaintPipeline
from diffusers import DiffusionPipeline, LCMScheduler, UNet2DConditionModel , AutoencoderKL ,  AutoPipelineForInpainting,StableDiffusionXLAdapterPipeline
from diffusers import StableDiffusionXLControlNetPipeline, ControlNetModel, AutoencoderKL, UniPCMultistepScheduler, T2IAdapter, LCMScheduler,DDIMScheduler
from diffusers.utils import load_image,make_image_grid
from compel import Compel,ReturnedEmbeddingsType
from controlnet_aux import OpenposeDetector #Depthで使用 
from transformers import DPTFeatureExtractor, DPTForDepthEstimation,CLIPVisionModelWithProjection
import torch
from datetime import datetime
import time
import numpy as np
import cv2
from PIL import Image

class DiffusersPipelineManager:
     def __init__(self):
        #----- デフォルト用定義
        #VAE 
        self.org_vae = "madebyollin/sdxl-vae-fp16-fix"
        #model 
        self.org_model="./models/animagine-xl-2.0/animagine-xl-2.0.safetensors"
        #self .org_model="./models/sd_xl_1.0/sd_xl_base_1.0.safetensors",
        #self .org_model="./models/blue_pencil-XL-LCM/bluePencilXLLCM_v200.safetensors"
        
        #LoRA 
        self.org_lora_model_list=[
            ["./models/animagine-xl-2.0/megu_sports_sdxl_v02.safetensors","style",0.8],
            ["./models/animagine-xl-2.0/anime-detailer-xl.safetensors","detaile",1.0],
            ["./models/animagine-xl-2.0/style-enhancer-xl.safetensors","enhancer",0.5]]

        #embe  TEST プロンプトの準備
        self.prompt_embe=["masterpiece, best quality, 1girl, solo, flower, long hair, outdoors, letterboxed, school uniform, day, sky, looking up, short sleeves, parted lips, shirt, cloud,black hair, sunlight, white shirt, serafuku, upper body, from side, pink flower, blurry, brown hair, blue sky, depth of field",
          "at shcool park"]

        #lcm_lora ="latent-consistency/lcm-lora-sdxl"
        self.lcm_lora="./models/SSD-1B-anime/lcm-ssd1b-anime.safetensors"

     def  pipeline_init(self,
                mode:str="t2i",              #指定できるpipe名  t2i/i2i/canny/i2i_pipe/inpaint_pipe/canny/openpose/canny_openpose/depth/t2i_adapter_canny
                pipeline=None,               #pipeloneの再利用の時に参照する生成済みpipeline名指定  デフォルト:無し
                model:str=None,              #ロードするSDXLモデル名  デフォルト:無し
                vae_en:bool=True,            #VAE有効無効設定   デフォルト:有効
                vae_path:str=None,           #VAE有効時のVAEへのパス  デフォルト:無し
                lcm_lora_en:bool=True,       #LCM -LoRA有効無効設定 無効にするとLCM-LoRAとLCMスケジュ-ラがロードされない デフォルト 有効
                lcm_lora_path=None,          #LCM -LoRA有効のLCM-LoRAへのパス デフォルト:無し
                lora_en:bool=False,          #Style -LoRAの有効無効設定 デフォルト 有効
                lola_models:list=None,       #Style -LoRAの有効時のStyle-LoRAへのパスリスト 複数のStyle-LoRAをロード出来る デフォルト:無し
                ddism_en:bool=False,         # ddism¥スケジューラ有効化
                single_ip:bool=False,        # IP-Adapter 有効化
                mul_ip:bool=False,           # Multi IP-Adapter 有効化
                ip_scal1:float=None,         #  IP-AdapterのScale/Multi IP-Adapter のScale1
                ip_scal2:float=None,         #  Multi IP-Adapter のScale2
                set_unet:bool=False,):       #UNETの有効無効設定  デフォルト 有効
          
        # デフォルト引数が None の場合、クラス属性を使用
        if model is None:
            model = self.org_model
        if vae_path is None:
            vae_path = self.org_vae
        if lcm_lora_path is None:
            lcm_lora_path = self.lcm_lora
        if lola_models is None:
            lola_models = self.org_lora_model_list         
        #UNETの準備 
        if lcm_lora_en:
            unet = UNet2DConditionModel.from_pretrained(
                "latent-consistency/lcm-sdxl",
                torch_dtype=torch.float16,
                variant="fp16",)
        else:
             unet =None
        #VAEの準備 
        if vae_en:
            vae = AutoencoderKL.from_pretrained(vae_path, torch_dtype=torch.float16, use_safetensors=True)
        else:
            print("VAE disabled")
            vae = None

       
        #pipelineの準備 
        if mode=="t2i":
            print("+++++t2i loading")
            pipe = StableDiffusionXLPipeline.from_single_file(
                model,
                variant="fp16",
                safety_checker=None,
                feature_extractor=None,
                unet=unet,
                torch_dtype=torch.float16,
                vae=vae,
                ).to("cuda")
        elif mode=="i2i":#t2iを継承しないpipelineのロード
            print("+++++i2i loading")
            pipe = StableDiffusionXLImg2ImgPipeline.from_single_file(
                model,
                variant="fp16",
                use_safetensors=True,
                safety_checker=None,
                feature_extractor=None,
                unet=unet,
                torch_dtype=torch.float16,
                vae=vae,
                ).to("cuda")

        #"i2i_pipe","inpaint_pipe"は"t2i"の設定を引き継ぐので再設定はできない。設定を変える場合は"i2i"を指定すること。。
        elif mode=="i2i_pipe":
            print("+++++i2i pipe  loading")
            pipe = AutoPipelineForImage2Image.from_pipe(pipeline).to("cuda")
            return pipe
        elif mode=="inpaint_pipe":
            print("+++++inpaint_pipe loading")
            pipe = AutoPipelineForInpainting.from_pipe(pipeline).to("cuda")
            return pipe

        #ControlNet名を指定してpipeを設定するとき 。 対象は="canny" , "openpose" , "depth"の3種類
        elif mode=="canny" or mode=="openpose"  or mode=="depth":
             if mode=="canny" :
                 controlnet = ControlNetModel.from_pretrained("diffusers/controlnet-canny-sdxl-1.0", torch_dtype=torch.float16, use_safetensors=True )
             elif mode=="openpose":
                 controlnet = ControlNetModel.from_pretrained("thibaud/controlnet-openpose-sdxl-1.0", torch_dtype=torch.float16)
             elif mode=="depth":
                  controlnet = ControlNetModel.from_pretrained("diffusers/controlnet-depth-sdxl-1.0", variant="fp16", use_safetensors=True, torch_dtype=torch.float16,).to("cuda")
             else:
                  print("ContorolNET error")
             #pipe  = StableDiffusionXLControlNetPipeline.from_pretrained(  #HuggingFaceからダウンロードする場合 
             pipe = StableDiffusionXLControlNetPipeline.from_single_file(
                   model,
                   controlnet=controlnet,
                   vae=vae,
                   torch_dtype=torch.float16,
                   use_safetensors=True )
             pipe.enable_model_cpu_offload()
        #canny_openpose  指定 マルチControlNeのpipeを設定するとき。
        elif mode=="canny_openpose":
            print("+++++canny_openpose loading")
            controlnets = [
                 ControlNetModel.from_pretrained("diffusers/controlnet-canny-sdxl-1.0", torch_dtype=torch.float16, use_safetensors=True ),
                 ControlNetModel.from_pretrained( "thibaud/controlnet-openpose-sdxl-1.0", torch_dtype=torch.float16 ),
                  ]
            #pipe  = StableDiffusionXLControlNetPipeline.from_pretrained(   #HuggingFaceからダウンロードする場合 
            pipe = StableDiffusionXLControlNetPipeline.from_single_file(
                   model,
                   controlnet=controlnets,
                   vae=vae,
                   torch_dtype=torch.float16,
                   use_safetensors=True)
            pipe.scheduler = UniPCMultistepScheduler.from_config(pipe.scheduler.config)
            pipe.enable_model_cpu_offload()
        #T2I -Adapterのpipeを作成する時
        elif mode=="t2i_adapter_canny":
             print("+++++t2i_adapter_canny  loading")
             adapter = T2IAdapter.from_pretrained("TencentARC/t2i-adapter-canny-sdxl-1.0", torch_dtype=torch.float16, varient="fp16").to("cuda")
             unet = UNet2DConditionModel.from_pretrained("latent-consistency/lcm-sdxl", torch_dtype=torch.float16, variant="fp16",)
             pipe = StableDiffusionXLAdapterPipeline.from_pretrained(      #HuggingFaceからダウンロードする場合 
                    model,
                    unet=unet,
                    adapter=adapter,
                     vae=vae,
                     torch_dtype=torch.float16,
                     variant="fp16", 
                      ).to("cuda")
        # IP-Adapterのpipeを設定
        elif mul_ip:
                  print("-----mul_ip",mode)
                  image_encoder = CLIPVisionModelWithProjection.from_pretrained(
                        "h94/IP-Adapter",
                        subfolder="models/image_encoder",
                        torch_dtype=torch.float16,
                         )
                  if  mode=="t2i_ip":
                       pipe = StableDiffusionXLPipeline.from_single_file(model, torch_dtype=torch.float16, image_encoder=image_encoder).to("cuda")
                  if mode=="i2i_ip":
                      pipe = StableDiffusionXLImg2ImgPipeline.from_single_file(model, torch_dtype=torch.float16, image_encoder=image_encoder).to("cuda")
                  """
                  #当面  IP-Adapter inpaintは使えません
                  if mode=="inpaint_ip":
                       pipe = StableDiffusionXLInpaintPipeline.from_single_file(model, torch_dtype=torch.float16, image_encoder=image_encoder).to("cuda")
                  """   
                  print("+++++ multi Ip-Adapter loading")
                  pipe.load_ip_adapter("h94/IP-Adapter", subfolder="sdxl_models", weight_name=["ip-adapter-plus_sdxl_vit-h.safetensors", "ip-adapter-plus-face_sdxl_vit-h.safetensors"])
                  pipe.set_ip_adapter_scale([ip_scal1, ip_scal2])
        elif single_ip:
                  print("-----single_ip",mode)
                  if  mode=="t2i_ip":
                       print("+++++t2i_ip  loading")
                       pipe = StableDiffusionXLPipeline.from_single_file(model, torch_dtype=torch.float16 ).to("cuda")
                  if mode=="i2i_ip":
                      print("+++++ i2i_ip  loading")
                      pipe = StableDiffusionXLImg2ImgPipeline.from_single_file(model, torch_dtype=torch.float16).to("cuda")

                  #IP -Adapter inpaintはVRAMが16G必要
                  if mode=="inpaint_ip":
                       print("+++++ inpaint_ip")
                       pipe = StableDiffusionXLInpaintPipeline.from_single_file(model, torch_dtype=torch.float16).to("cuda")

                  print("+++++ single-Ip-Adapter loading")
                  pipe.load_ip_adapter("h94/IP-Adapter", subfolder="sdxl_models", weight_name="ip-adapter_sdxl.bin")
                  #pipe .load_ip_adapter("h94/IP-Adapter", subfolder="sdxl_models", weight_name="ip-adapter-plus-face_sdxl_vit-h.safetensors")#Need  DDIMScheduler and EulerDiscreteScheduler
                  pipe.set_ip_adapter_scale(ip_scal1)

        else:
            print("error=100")   #pipe名指定のエラー 
            return "100"

        # Set scheduler LCMスケージューラーのセット
        if lcm_lora_en:   # Reload the scheduler with custom config
            pipe.scheduler = LCMScheduler.from_config(pipe.scheduler.config)# Reload the scheduler with custom config
        if ddism_en:   # Reload the scheduler with custom config
            pipe.scheduler = DDIMScheduler.from_config(pipe.scheduler.config)
            
        #LCM -LoRAのロード
        if lcm_lora_en:
            #pipe .load_lora_weights("latent-consistency/lcm-lora-sdxl", adapter_name="lcm") #HuggingFaceからダウンロードする場合 
            pipe.load_lora_weights(lcm_lora_path, adapter_name="lcm")
            adapters_list=["lcm"]
        else:
            adapters_list=[]
        #Style -LoRAのロード     
        if lora_en :
            n_of_lora=len( lola_models)
            if lcm_lora_en:
                adapter_weights_list=[1.0]
            else:
                adapter_weights_list=[]
            #loRAのモデルとアダプタ名及びウエイトリスト作成 
            for n in range(n_of_lora):
                lora_name=lola_models[n][0]
                adapter_name=lola_models[n][1]
                adapters_list.append(adapter_name)
                weight=lola_models[n][2]
                adapter_weights_list.append(weight)
                pipe.load_lora_weights(lora_name, adapter_name=adapter_name)
            # Combine LoRAs
            pipe.set_adapters(adapters_list, adapter_weights=adapter_weights_list)
            print("adapters_list",adapters_list,"adapter_weights",adapter_weights_list)
        # Set the unet to channels last, which accelerates inference a little bit
        if set_unet:
            pipe.unet = pipe.unet.to(memory_format=torch.channels_last)
        # Disable the progress bar
        pipe.set_progress_bar_config(disable=True)

        return pipe

     #-----prompt_embeddings プロンプトをロードするクラス
     #prompt  = "a red cat++ playing with a ball----"   prompt  Enhace / Reduce
     def prompt_embedding(self, pipe, prompt):
        #compel_proc  = Compel(tokenizer=pipe.tokenizer, text_encoder=pipe.text_encoder)
        compel = Compel(
              tokenizer=[pipe.tokenizer, pipe.tokenizer_2] ,
              text_encoder=[pipe.text_encoder, pipe.text_encoder_2],
              returned_embeddings_type=ReturnedEmbeddingsType.PENULTIMATE_HIDDEN_STATES_NON_NORMALIZED,
              requires_pooled=[False, True]
                )
        conditioning, pooled = compel(prompt)
        return conditioning, pooled

    #-----load_image for i2i 指定イメージをロードするクラス
     def load_image_img(self,image_path):
        image =load_image(image_path)
        #image  = pipe.image_processor.preprocess(
        #        Image.open(image_path) .convert("RGB").resize((512,) * 2, Image.Resampling.LANCZOS))
        #image  = Image.open(image_path)#同じ
        return image
     
     #cannyイメージ作成クラス 
     def get_canny(self , original_image , low_threshold = 100 , high_threshold = 200):
          image = np.array(original_image)
          image = cv2.Canny(image, low_threshold, high_threshold)
          image = image[:, :, None]
          image = np.concatenate([image, image, image], axis=2)
          canny_image = Image.fromarray(image)
          return canny_image
     
     #openposeイメージ作成クラス 
     def get_openpose(self , image ):
          openpose = OpenposeDetector.from_pretrained("lllyasviel/ControlNet")
          openpose_image = openpose(image)
          return openpose_image
               
     #Depthイメージ作成クラス 
     def get_depth_map(self, image):
          feature_extractor = DPTFeatureExtractor.from_pretrained("Intel/dpt-hybrid-midas")
          depth_estimator = DPTForDepthEstimation.from_pretrained("Intel/dpt-hybrid-midas").to("cuda")
          image = feature_extractor(images=image, return_tensors="pt").pixel_values.to("cuda")
          with torch.no_grad(), torch.autocast("cuda"):
               depth_map = depth_estimator(image).predicted_depth
          depth_map = torch.nn.functional.interpolate(depth_map.unsqueeze(1), size=(1024, 1024), mode="bicubic", align_corners=False, )
          depth_min = torch.amin(depth_map, dim=[1, 2, 3], keepdim=True)
          depth_max = torch.amax(depth_map, dim=[1, 2, 3], keepdim=True)
          depth_map = (depth_map - depth_min) / (depth_max - depth_min)
          image = torch.cat([depth_map] * 3, dim=1)
          image = image.permute(0, 2, 3, 1).cpu().numpy()[0]
          image = Image.fromarray((image * 255.0).clip(0, 255).astype(np.uint8))
          return image

    #画像の生成  
    #generate  t2i/i2i/inpaint/cannyで使用
    #generate_controlnet   openpose/depth/Multi-ContorolNETで使用
    #generate_t2a_adapter   T2I- Adapterで使用
     
     """3種類の生成モード共通のパラメータ
        pipe
        利用するpipeを指定。必ず指定しなければならない。
        image=None,
   入力イメージを指定する。パスではなくイメージオブジェクト(PILが標準、CV2も使えるはず(ためしていない)
        mask_image=None,
   インペイントなどのマスクイメージを指定。パスではなくイメージオブジェクト(PILが標準、CV2も使えるはず(ためしていない)
        embe:bool=True,
         プロンプトエンべデッディング有効・無効。有効時はCONPLEによるエンべディングを行う。プロンプトのウエイト指定も可能
             ウエイト指定の例  prompt = "a red cat++ playing with a ball----"   +はprompt  Enhace /-は Reduce
        prompt:str=None,
             プロンプト 文章も使えます。ただし英語のみ
        conditioning=None,
        pooled=None,
             conditioningとpooledはプロンプトエンべデッディングでCONPLEから得られる変数を記述
        negative_prompt=None,
             ネガティブプロンプト
        num_inference_steps:int=4,
             生成時のSTEP、大きいほうがきれいになる。lmcは4が標準だが適時上げる
        strength:float=0.1,
             プロンプトの効きを調整する0〜1.0
        guidance_scale:float=1.0,
             ガイダンススケール 1.0で無効、大きいと生成時間が伸びる。上げれば画像がきれいになるわけででない
        generator=None,
             SEEDを指定する。例 generator = torch.manual_seed(0 )でマニュアルでSEED指定
        height:int = None,
             画像の高さを指定する
        width:int = None,
             画像の幅を指定する
        num_images_per_prompt:int = 1,
             プロンプトあたりの生成画像数を指定して複数生成させることが出来る
        guess_mode:bool=None,
             ガウシアン効果の有効無効指定
        freeu:bool=False,
             freeu効果の有効無効指定。有効にすると生成画像が鮮やかな色になる。
        output_type:str="pil",
             画像出力形式を指定する。ndarreyが指定可能("nd")
        crops_coords_top_left=(0, 0),
         生成する主画像の位置を指定する
        controlnet_conditioning_scale=1.0,
             コントロールネットの効き具合を指定する
        ip_adapter:bool=False,
             IP-Adaperを使う
        style_images:list=None,
             Multi-IP-Adaper用のStyle画像リスト
        face_image=None,
         IP-Adaper用の入力画像 / Multi-IP-Adaper用のface画像リスト
     T2I-Adaper特有のパラメータ
        adapter_conditioning_scale:float=None,   
        adapter_conditioning_factor:int=None,
         アダプタの効き具合の設定をする
     """
    
    #-----image generation  t2i/i2i /inpaint and Multi-IP-Adapter  t2i
     def generate(self,
        pipe,
        image=None,
        mask_image=None,
        negative_prompt_embeds=  None,
        embe:bool=True,
        prompt:str=None,
        conditioning=None,
        pooled=None,
        negative_prompt=None,
        num_inference_steps:int=4,
        strength:float=0.1,
        guidance_scale:float=1.0,
        generator=None,
        height:int = None,
        width:int = None,
        num_images_per_prompt:int = 1,
        guess_mode:bool=None,
        freeu:bool=False,
        freeu_list:list=[0.9, 0.2,1.2,1.4],
        output_type:str="pil",
        crops_coords_top_left=(0, 0),
        controlnet_conditioning_scale=1.0,
        ip_adapter:bool=False,
        style_images:list=None,
        ip_image =None,          
        ):
        print("++++++++++++++++ @@@@@@@@@@@@ +++++++++generate")
        if freeu:        # Freeu enable
            #pipe .enable_freeu(s1=0.9, s2=0.2, b1=1.2, b2=1.4)
            pipe.enable_freeu(s1=freeu_list[0],s2=freeu_list[1],b1=freeu_list[2],b2=freeu_list[3])
        if ip_adapter:
                if style_images==None:
                       print("Single_IP-Adapter")
                       ip_adapter_image=ip_image 
                else:
                       print("Multi_IP-Adapter")
                       ip_adapter_image=[style_images, ip_image ]
                       
                image = pipe(
                    image=image,
                    prompt=prompt,
                    mask_image=mask_image,
                    prompt_embeds=None,
                    pooled_prompt_embeds=None,
                    negative_prompt=negative_prompt, 
                    num_inference_steps=num_inference_steps,
                    generator=generator,
                    height=height,
                    width= width,
                    guidance_scale=guidance_scale,
                    #strength =strength,     #  ip_adapterではエラーになります。ip_adapter==False:のときとの違いはここだけ
                    num_images_per_prompt=num_images_per_prompt,
                    guess_mode=guess_mode,
                    crops_coords_top_left=crops_coords_top_left,
                    controlnet_conditioning_scale=controlnet_conditioning_scale,
                    ip_adapter_image= ip_adapter_image,
                    style_images=style_images,
                    ).images
        elif ip_adapter==False:
                print("++++++++++++++@@@@@@@@@@@@@@ embe=", embe)
                image = pipe(
                    image=image,
                    prompt=prompt,
                    mask_image=mask_image,
                    prompt_embeds=conditioning,
                    pooled_prompt_embeds=pooled,
                    negative_prompt=negative_prompt,
                    num_inference_steps=num_inference_steps,
                    strength=strength,
                    generator=generator,
                    height =height,
                    width = width,
                    num_images_per_prompt=num_images_per_prompt,
                    guess_mode=guess_mode,
                    output_type=output_type,
                    guidance_scale=guidance_scale,
                    crops_coords_top_left=crops_coords_top_left,
                    controlnet_conditioning_scale=controlnet_conditioning_scale,
                    ).images
        return  image
     #-----image generation  controlnet
     def generate_controlnet(self,
        pipe,
        image=None,
        prompt:str=None,
        negative_prompt=None,
        num_inference_steps:int=4,
        guidance_scale:float=1.0,
        generator=None,
        height:int = None,
        width:int = None,
        num_images_per_prompt:int = 1,
        guess_mode:bool=None,
        freeu:bool=False,
        output_type:str="pil",
        crops_coords_top_left=(0, 0),
        controlnet_conditioning_scale=1.0,
             ):
        if freeu:        # Freeu enable
            pipe.enable_freeu(s1=0.9, s2=0.2, b1=1.2, b2=1.4)
        image = pipe( 
                    prompt=prompt,
                    image=image,
                    negative_prompt=negative_prompt,
                    num_inference_steps=num_inference_steps,
                    generator=generator,
                    height =height,
                    width = width,
                    num_images_per_prompt=num_images_per_prompt,
                    guess_mode=guess_mode,
                    guidance_scale=guidance_scale,
                    crops_coords_top_left=crops_coords_top_left,
                    controlnet_conditioning_scale=controlnet_conditioning_scale,
                    ).images
        return  image
     #-----image generation  t2a_adapter
     def generate_t2a_adapter(self,
        pipe,
        image=None,
        prompt:str=None,
        negative_prompt=None,
        num_inference_steps:int=4,
        guidance_scale:float=1.0,
        generator=None,
        height:int = None,
        width:int = None,
        num_images_per_prompt:int = 1,
        freeu:bool=False,
        output_type:str="pil",
        crops_coords_top_left=(0, 0),
        adapter_conditioning_scale:float=None,   
        adapter_conditioning_factor:int=None,
             ):
        if freeu:        # Freeu enable
            pipe.enable_freeu(s1=0.9, s2=0.2, b1=1.2, b2=1.4)
        image = pipe( 
                    prompt=prompt,
                    image=image,
                    negative_prompt=negative_prompt,
                    num_inference_steps=num_inference_steps,
                    generator=generator,
                    height =height,
                    width = width,
                    num_images_per_prompt=num_images_per_prompt,
                    guidance_scale=guidance_scale,
                    crops_coords_top_left=crops_coords_top_left,
                    adapter_conditioning_scale=adapter_conditioning_scale,
                    adapter_conditioning_factor=adapter_conditioning_factor,
                    ).images
        return  image