FLUX.1-devã§ControlNetãå©çšãããç»åã®è³ªãäžãã£ãã®ã§Img2Imgã䜿ã£ãŠæ¹åããŠã¿ããDiffusersã
ã¯ããã«
FLUX.1ãšã¯ãç»åçæAIã§ãããã®æåãªãStable Diffusionãã®éçºã«æºãã£ãAIç ç©¶è ãç«ã¡ãããæ°ããAIéçºäŒæ¥ã§ãããBlack Forest Labsãã«ããçã¿åºããã髿§èœãªç»åçæAIã¢ãã«ã§ãã
å æ¥ãGoogle Colabã«ãŠãFLUX.1-dev + ControlNet + LoRAããDiffusersã©ã€ãã©ãªã§åäœãããèšäºãèšèŒããŸãããïŒç§ã¯å®æäžã®çç±ããWebUIã¯äœ¿ããªãã®ã§ãdiffusersã©ã€ãã©ãªã«ãã ãã£ãŠããŸãïŒ
ããããªãããäžèšã®èšäºã®çæç»åäŸãããããããã«ãControlNetãå©çšããªã圢ã§çæããç»åãšControlNetãå©çšããŠçæããç»åãæ¯èŒãããšãçæãããç»åã®ã€ã¡ãŒãžãããªãç°ãªãããšãããããšæããŸãã
ä»åã¯ãControlNetãå©çšããŠçæãããç»åããåã³FLUX.1-devã®Img2Imgãã€ãã©ã€ã³ã«å ¥åããŠãæ§å³ãç¶æããªãããã質ã®é«ãç»åã«ããå®éšãããŠã¿ãŸãã
çæç»åäŸ
ControlNetã®ã¿ã®ç»å

ããèŠããšããããå€ãªç»åãšããããã§ã¯ãªãã§ãããäŸãã°ãçãäžã®ç»åãšãã¯ããªãã³ã®éšåãªã©ãããããã«ãªã£ãŠããããæã®æã®æ¬æ°ã6æ¬ã«ãªã£ãŠãããããŸãã
3æç®ã®ç»åãImg2Img Pipelineã«å ¥åãé«å質åããç»å

äžèšã®ç»åã¯ãControlNetã®ã¿ã®ç»åã®ãã¡ã3æç®ïŒçãäžïŒã®ç»åãåç
§ç»åãšããŠãImg2Img Pipelineã«ãŠç»åãçæããŠããŸãã
ç»åãèŠãéããå
¥åç»åã®æ§å³ãç¶æããªãããããé«å質ãªç»åã«åæ§æã§ããŠããããšãããããŸãã
ïŒåèïŒControlNetã䜿ããªãã§çæããç»å

ããèŠããšãControlNetãå©çšãããšãç»åã®è³ªãäžãããšããæå³ãããããšæããŸãã
ãã ããæ§å³ãªã©ã¯ãã©ãã©ã«çæãããã®ã§ãææã®ç»åãçæããã«ã¯ã倧éã®ç»åãçæããŠãæãè¯ããã®ãæ¢ããããããã³ããã工倫ããå¿
èŠããããŸãã
ControlNetãå©çšããããšã§ãç°¡åã«æ§å³ãåºå®ã§ããããšã¯ã倧ããªã¡ãªããã«ãªããããControlNetã§æ§å³ãæå®ããäžã§ã質ã®é«ãç»åãçæããããšãç®æšã«ããŸãã
ææç©
äžèšã®ãªããžããªãã芧ãã ãã
ïŒååã®èšäºã®ãªããžããªã«Image to Imageã®æ©èœã远å ãããã®ã«ãªããŸãïŒ
äºåæºå
Hugging Faceã®login tokenã®ååŸãšç»é²
ååã®èšäºã«èšèŒããã®ã§é ããŸã
Hugging Faceã®login tokenã®ååŸãšç»é²
SD3ã®ã¢ãã«ãããŒã«ã«ã§å©çšå¯èœã«ããããã«ãHuggingfaceãããã°ã€ã³çšã®tokenãååŸããå¿
èŠããããŸãã
ãã°ã€ã³tokenã®ååŸæ¹æ³ã¯äžèšã®èšäºãåèã«ããŠãã ããã
ãŸããååŸãããã°ã€ã³tokenãGoogle Colabã«ç»é²ããå¿
èŠããããŸãã
äžèšã®èšäºãåèã«ç»é²ããŠãã ããã
HF_LOGINãšããååã§ç»é²ããŠãã ããã
FLUX.1-devéã¿ãžã®ã¢ã¯ã»ã¹æºå
ååã®èšäºã«èšèŒããã®ã§é ããŸã
FLUX.1-devéã¿ãžã®ã¢ã¯ã»ã¹æºå
ç¶ããŠãHuggingfaceã§FLUX.1-devã®éã¿ã«ã¢ã¯ã»ã¹ã§ããããã«ããŸãã
äžèšã®URLã«ã¢ã¯ã»ã¹ããŠãã ããã

åããŠã¢ã¯ã»ã¹ããå Žåãäžèšã®ãããªç»é¢ã«ãªããšæãã®ã§ãäœæããã¢ã«ãŠã³ãã§ãã°ã€ã³ããŠãã ããã
ãã®åŸãå
¥åãã©ãŒã ã衚瀺ãããããšæããŸãã
ãã®ãã©ãŒã ããã¹ãŠåããŠãæåºããããšã§ãã¢ãã«éã¿ã«ã¢ã¯ã»ã¹ã§ããããã«ãªããŸãã
ãªããžããªã®ã¯ããŒã³
ãŸãã¯äžèšã®ãªããžããªãcloneããŠãã ããã
git clone https://github.com/personabb/colab_AI_sample.git
ãã®åŸãcloneãããã©ã«ãã®äžã§ãããcolab_AI_sample/colab_fluxdev_sample2ãããã€ãã©ã€ãã®é©åœãªå Žæã«ãããŠãã ããã
Img2Img Pipelineçšã®åç §ç»åã®æºå
ä»åã¯ãååã®èšäºã§çæããç»åãæµçšããŸããäžèšã®ç»åã«ãªããŸãã

äžèšã®ç»åãinputs/imagetoimage/inputs1.pngãšããŠæ ŒçŽããŸã
æ³å®ããããã£ã¬ã¯ããªæ§é
Google Driveã®ãã£ã¬ã¯ããªæ§é ã¯äžèšãæ³å®ããŸãã
MyDrive/
â colab_AI_sample/
â colab_fluxdev_sample2/
â configs/
| â config.ini
â inputs/
| â imagetoimage/
| | â inputs1.png
| â controlnet/
| | â refer/ãïŒText2Imageã®ControlNetã§å©çšãä»åäžèŠïŒ
| | â refer_prepared/ãïŒText2Imageã®ControlNetã§å©çšãä»åäžèŠïŒ
â outputs/
â module/
| â module_flux.py
â FluxDev_sample2.ipynb
äœ¿ãæ¹
å®è¡æ¹æ³
FluxDev_sample2.ipynbãGoogle Colabratoryã¢ããªã§éããŠãäžèšã§èšèŒããããã©ã¡ãŒã¿ã®èšå®ãããããã³ããã®å€æŽããé©åã«å®æœããåŸãäžçªäžã®ã»ã«ããé çªã«äžçªäžãŸã§å®è¡ãããšãç»åã5æãoutputsããã©ã«ãã«çæãããŸãã
ãŸããæåŸãŸã§å®è¡åŸããã©ã¡ãŒã¿ã倿ŽããŠå床å®è¡ããå Žåã¯ããã©ã³ã¿ã€ã ãâãã»ãã·ã§ã³ãåèµ·åããŠå šãŠå®è¡ããããã¯ãªãã¯ããŠãã ããã
ãã©ã¡ãŒã¿ã®å€æŽ
FluxDev_sample2.ipynbã®5ã»ã«ç®ãš8ã»ã«ç®ã該åœããŸãã
ãã©ã¡ãŒã¿ã®èšå®ã5ã»ã«ç®
#ã¢ãã«ã®èšå®ãè¡ãã
config_text = """
[FLUX]
device = auto
n_steps=24
seed=42
;model_mode = t2i
model_mode = i2i
strength = 0.6
;from_single_file = False
;base_model_path = black-forest-labs/FLUX.1-schnell
base_model_path = black-forest-labs/FLUX.1-dev
use_controlnet = False
controlnet_path = Shakker-Labs/FLUX.1-dev-ControlNet-Union-Pro
;control_mode0 = canny
;control_mode1 = tile
control_mode2 = depth
;control_mode3 = blur
;control_mode4 = pose
;control_mode5 = gray
;control_mode6 = lq
;lora_weight_repo0 = alfredplpl/flux.1-dev-modern-anime-lora
;lora_weight_path0 = modern-anime-lora-2.safetensors
;lora_weight_repo1 = aleksa-codes/flux-ghibsky-illustration
;lora_weight_path1 = lora.safetensors
;lora_scale0 = 1.0
;lora_scale1 = 1.0
;trigger_word0 = "modern anime style"
;trigger_word1 = "GHIBSKY style painting"
;lora_weight_repo2 = None
;lora_weight_path2 = ./inputs/QTCanimation_lora_v1-PAseer.safetensors
;lora_scale2 = 1.0
;trigger_word2 = ""
;select_solver = LCM
;select_solver = DPM
;select_solver = Eulera
select_solver = FMEuler
use_karras_sigmas = True
scheduler_algorithm_type = dpmsolver++
solver_order = 2
cfg_scale = 3.5
;cfg_scale = 1.0
width = 832
height = 1216
output_type = pil
aesthetic_score = 6
negative_aesthetic_score = 2.5
save_latent_simple = False
save_latent_overstep = False
"""
with open("configs/config.ini", "w", encoding="utf-8") as f:
f.write(config_text)
-
n_steps- 20step以äžãã綺éºãªç»åãçæããããå ¬åŒã§ã¯50stepãæšå¥šããŠãããæéãããã
- ãæ°èŠè¿œå ã
model_mode-
t2iãi2iãèšå®ããŸã -
t2iã¯ããã³ããããç»åãçæãããã€ãã©ã€ã³ã§ã -
i2iã¯ç»åãšããã³ããããç»åãçæãããã€ãã©ã€ã³ã§ãã
-
- ãæ°èŠè¿œå ã
strength-
model_mode = i2iãéžæããéã«ãã©ã®çšåºŠå ã®ç»åã«ãã€ãºãä»äžããããèšå®ãã - 1ã®å Žåã¯
t2iãšäžèŽããŸã
-
-
base_model_path- å©çšããã¢ãã«ã®æå®ãFLUX.1-schnellãªã©ãæå®ã§ããã
- ä»åŸã髿§èœã¯FineTuningã¢ãã«ãç»å Žãããããã¡ããå©çšããããšãã§ãã
- ãã®ã¢ãã«ãåäžã®safetensorã¢ãã«ã®å Žåã¯
from_single_file = Trueãèšå®ãã
- ãã®ã¢ãã«ãåäžã®safetensorã¢ãã«ã®å Žåã¯
-
use_controlnet- ControlNetãå©çšãããã©ããã®Flag
-
controlnet_path- å©çšããControlNetã®ã¢ãã«ãã¹
-
control_mode0ããcontrol_mode6- å©çšããControlNetã®ã¢ãŒããè€æ°èšèŒããã°å€éã«é©çšå¯èœ
-
lora_weight_repo0ããlora_weight_repo9- å©çšããLoRAã®ãªããžããªæå®ãè€æ°èšèŒããã°å€éã«é©çšå¯èœ
- HuggingFaceã«ããLoRAå©çšããå Žåã¯ãããã«ãªããžããªåãæå®ãã
-
lora_weight_path0ããlora_weight_path9- å©çšããLoRAã®ãã¹ãæå®ãããè€æ°èšèŒããã°å€éã«é©çšå¯èœ
- HuggingFaceã«ããLoRAå©çšããå Žåã¯ãããã«ã¯LoRAã§å©çšãããã¡ã€ã«åã®ã¿ãæå®ãã
- Civitaiãªã©ã®LoRAãã¡ã€ã«ãããŠã³ããŒãããŠå©çšãããã¡ã€ã«ã¯ããã¡ã€ã«ãä¿åããå Žæã®çžå¯Ÿãã¹ãèšè¿°ããïŒ'lora_weight_repo`ã¯Noneã«èšå®ããïŒ
-
lora_scale0ããlora_scale9- å©çšããLoRAã®é©çšåºŠåã
-
trigger_word0ããtrigger_word9- å©çšããLoRAã§æšå¥šãããTrigger Wordã®èšå®
-
select_solver- å©çšãããµã³ãã©ãŒã®æå®ãFLUX.1ã·ãªãŒãºã®å Žåã¯
FMEulerãæå®ãã
- å©çšãããµã³ãã©ãŒã®æå®ãFLUX.1ã·ãªãŒãºã®å Žåã¯
-
widthãšheight- çæããç»åã®ãµã€ãº
-
save_latent_simpleãšsave_latent_overstep- çæéäžãåºåãããã©ãããåºåããå Žåã©ã®ãããªåœ¢åŒã§åºåãããã®ãã©ã°
-
save_latent_simpleã¯ãã€ãºããçæãããéçšãåºå -
save_latent_overstepã¯ããçšåºŠç¶ºéºãªç»åãé·ç§»ãããããªéçšãåºå
8ã»ã«ç®ã¯äžèšã§ãã
controlnet_conditioning_scale = [0.5]
temp_strength = None
for i in range(5):
start = time.time()
image = flux.generate_image(main_prompt,c_image_path = output_refer_image_folder, i_image_path = i2i_image_path, controlnet_conditioning_scale = controlnet_conditioning_scale, temp_strength = temp_strength)
print("generate image time: ", time.time()-start)
image.save("./outputs/FLUX_result_{}.png".format(i))
ãã¡ãã®controlnet_conditioning_scale = [0.5]ãštemp_strength = Noneã®éšåã倿Žå¯èœãªãã©ã¡ãŒã¿ã§ãã
controlnet_conditioning_scaleã¯ãControlNetãå©çšããå Žåã«ãã©ã®çšåºŠåæ ãããããèšå®ãããã©ã¡ãŒã¿ã§ããå
¬åŒçã«ã¯0.3-0.8ããããæšå¥šã«ãªã£ãŠããŸãã
temp_strengthã¯5ã»ã«ç®ã®strengthãšåãã§ãã
temp_strengthãèšå®ãããŠããå Žå(None以å€ã®å®æ°)ã¯ãã¡ããåªå
ãããŸãã
ããã³ããã®å€æŽ
FluxDev_sample2.ipynbã®6ã»ã«ç®ã該åœããŸãã
#èªã¿äžããããã³ãããèšå®ããã
main_prompt = """
modern anime style, a cute Japanese idle singer girl, long Yellowish-white hair with red small ribbon,red eyes,small red hat ,She sings with a smile on her face ,make a peace sign with her left hand, wearing white idle costume, standing on the stage ,This is a flashy concert with 3D holograms and laser effects
"""
#ã³ã³ãããŒã«ãããã«å
¥åããåç
§ç»åã¯0ãã6ãŸã§ã®æ°åãæ³å®ïŒ0.png,6.webpãªã©ãæ°åã¯controlnetã®ã¢ãŒããšäžèŽãããŠãã ããïŒ
#åç
§ïŒã³ã³ãããŒã«ãããã®ã¢ãŒããcanny (0), tile (1), depth (2), blur (3), pose (4), gray (5), low quality (6).
input_refer_image_folder = "./inputs/controlnet/refer"
#ã³ã³ãããŒã«ãããã«å
¥åãã倿åŸã®åç
§ç»åã®æ ŒçŽãã©ã«ããåœåèŠåã¯äžèšãšåæ§
output_refer_image_folder = "./inputs/controlnet/refer_prepared"
#image to imageã¢ãŒããå©çšããéã®ç»åpath
i2i_image_path = "./inputs/imagetoimage/inputs1.png"
6ã»ã«ç®ã®main_promptã倿ŽããŠã8ã»ã«ç®ãå®è¡ããããšã§ã倿Žãããããã³ãããåæ ãããŠå®è¡ãããŸãã
å®è¡çµæ
ããããã¯ãGoogle Colabã§ããŸããŸãã©ã¡ãŒã¿ã倿Žããå®éšçµæãèšèŒããŸãã»
ããã³ãããšåç
§ç»åãåºå®ããŠãstrengthã0.6-0.9ãŸã§å€æŽããçµæã確èªããŸãã
èšå®
ä»åŸãæèšããªãéããäžèšã®èšå®ãå©çšãã
åç §ç»å
i2i_image_path = "./inputs/imagetoimage/inputs1.png"ã§æå®ããŠããç»åã§ãã

ããèŠããšããªãã³ã®éšåãšããããããã«ãªã£ãŠããããšãããããŸãã
ããã«ãæã®æã®æ¬æ°ã6æ¬ã«ãªã£ãŠããŸãã
ãã®èŸºããã©ãå€åããããèŠãã®ã§ãã
ããã³ãã
modern anime style, a cute Japanese idle singer girl, long Yellowish-white hair with red small ribbon,red eyes,small red hat ,She sings with a smile on her face ,make a peace sign with her left hand, wearing white idle costume, standing on the stage ,This is a flashy concert with 3D holograms and laser effects
åæ ããããæ§å³ãããã³ããã«çã蟌ãã§ããŸãã
ïŒmake a peace sign with her left handã®éšåïŒ
ããããããšã§ãçæãããç»åãããåç
§ç»åã®æ§å³ã«è¿ããªããŸãã
èšå®
6ã»ã«ç®ã¯äžèšã®ããã«æå®ããŸãã
#ã¢ãã«ã®èšå®ãè¡ãã
config_text = """
[FLUX]
device = auto
n_steps=24
seed=42
;model_mode = t2i
model_mode = i2i
strength = 0.6
base_model_path = black-forest-labs/FLUX.1-dev
use_controlnet = False
select_solver = FMEuler
use_karras_sigmas = True
scheduler_algorithm_type = dpmsolver++
solver_order = 2
cfg_scale = 3.5
width = 832
height = 1216
output_type = pil
aesthetic_score = 6
negative_aesthetic_score = 2.5
save_latent_simple = False
save_latent_overstep = False
"""
with open("configs/config.ini", "w", encoding="utf-8") as f:
f.write(config_text)
å®éš1ãstrength:0.6
8ã»ã«ç®ã§
temp_strength=0.6ãšããŠå®è¡ããŸã
çæçµæ
çæãããç»åã¯äžèšã§ããïŒäžæã«ãŸãšããŠããŸãïŒ

0.6æç¹ã§ããªãå
ã®ç»åã«å¿ å®ãªããããç»åã®è³ªãåäžããŠããããšãããããŸãã
äŸãã°ã厩å£ããŠãããªãã³ã¯ç¶ºéºã«ãªã£ãŠããŸãã
äžæ¹ã§ãæã®æã®æ¬æ°ã¯å€§å€æ°ã®ç»åã§ãæ®å¿µãªãã6æ¬ã®ãŸãŸã§ã
ä»åŸãstrengthãäžããŠããããšã§ãå ã®ç»åã®å¿ å®åºŠãäžããŠãããªãããæ§å³ã®å¿ 宿§ãšç»åã®è³ªã®ãã©ã³ã¹ãèŠãŠãããŸãã
å®éš1ãstrength:0.7
8ã»ã«ç®ã§
temp_strength=0.7ãšããŠå®è¡ããŸã
çæçµæ
çæãããç»åã¯äžèšã§ããïŒäžæã«ãŸãšããŠããŸãïŒ

0.7ã§ãæ§å³ã«å¿ å®ã«ç»åãçæãããŠããŸãã
ããããªãããå®éš1ãšæ¯èŒããŠç»åã®è³ªãäžãã£ãŠããŸãã
äŸãã°ã
厩å£ããŠãããªãã³ã¯ç¶ºéºã«çæãããŠããããŸããååãããã®ç»åã¯æã®æã®æ¬æ°ã5æ¬ã«ä¿®æ£ãããŠããŸãã
å®éš1ãstrength:0.8
8ã»ã«ç®ã§
temp_strength=0.8ãšããŠå®è¡ããŸã
çæçµæ
çæãããç»åã¯äžèšã§ããïŒäžæã«ãŸãšããŠããŸãïŒ

å€å°æ§å³ã厩ããŠããŸããïŒããŒã¹ã®äœçœ®ããã©ãã©ïŒãããŸã 倧ãŸããªæ§å³ã¯äžèŽããŠããŸãã
ç»åã®è³ªã¯ã©ãã©ãäžãã£ãŠãããŸãã
4æã®ç»åã§æã®æ¬æ°ã5æ¬ã«ä¿®æ£ãããŠããŸãã
å®éš1ãstrength:0.9
8ã»ã«ç®ã§
temp_strength=0.9ãšããŠå®è¡ããŸã
çæçµæ
çæãããç»åã¯äžèšã§ããïŒäžæã«ãŸãšããŠããŸãïŒ

ãããŸã§ãããšãå
ã®åç
§ç»åã®æ§å³ã¯ã»ãŒãªããããã³ããã«åŸã£ãŠç»åãçæãããŠããããšãããããŸãã
ç»è³ªãéåžžã®FLUX.1-devãšåæ§ãéåžžã«é«ã質ã«ãªã£ãŠããŸãã
ãŸãšã
ä»åã¯ãcontrolNetãå©çšããŠã質ãäžãã£ãŠããŸã£ãç»åã«å¯ŸããŠãImg2Img Pipelineãé©çšããŠç»åã®è³ªãæ¹åãããŠã¿ãŸããã
ç»åã®æ§å³ãå®å
šã«äžèŽããããå Žåã¯strength=0.7çšåºŠã®ãã©ã¡ãŒã¿ãæå®ããããšã§ãæ§å³ãäžèŽãããªãããç»åã®è³ªãåäžã§ããããšãããããŸããã
ä»åã®èšäºã¯ååã®èšäºãèŠãŠããã ããŠããããšãåæãªã®ã§ãååã®èšäºã䜵ããŠã芧ãã ããã
ãã®ããã«å·¥å€«ãããšãäœãããæ§å³ã®è³ªã®é«ãç»åãçæã§ããããšãããããŸããã
å
ã®åç
§ç»åã®æ§å³ãç¶æããªãããããã³ããã®å
容ãåæ ãããŠããããšããControlNetãšäŒŒãŠããŸãã䜿ãåããã§ããŠããŠããã§ããã
ã§ã¯ãããŸã§èªãã§ãã ãã£ãŠããããšãããããŸããïŒ
ã³ãŒã解説
FluxDev_sample2.ipynb
FluxDev_sample2.ipynbã«ã€ããŠè§£èª¬ããŸãã
ã³ãŒãã¯äžèšããã芧ãã ãã
1ã»ã«ç®
#Google Driveã®ãã©ã«ããããŠã³ãïŒèªèšŒå
¥ãïŒ
from google.colab import drive
drive.mount('/content/drive')
ãã€ãã©ã€ãã®ããŠã³ããè¡ã£ãŠããŸãã
èªèšŒãå
¥ããäžå®æéèªèšŒããªããšãšã©ãŒã«ãªã£ãŠããŸãã®ã§ãæåã«æã£ãŠããŠå®è¡ãšèªèšŒããŸãšããŠå®æœããŸãã
2ã»ã«ç®
#FLUX ã§å¿
èŠãªã¢ãžã¥ãŒã«ã®ã€ã³ã¹ããŒã«
%rm -r /content/diffusers
%cd /content/
!git clone https://github.com/huggingface/diffusers.git
!pip install -U optimum-quanto peft tensorflow-metadata transformers scikit-learn ftfy accelerate invisible_watermark safetensors controlnet-aux mediapipe timm
å¿
èŠãªã¢ãžã¥ãŒã«ãã€ã³ã¹ããŒã«ããŠããŸãã
å®é𿥿ç¹ã§ãpipããã€ã³ã¹ããŒã«å¯èœãªDiffusersã¢ãžã¥ãŒã«ã®äžã«FLUX.1ãå®è¡ã§ããã³ãŒããå
¥ã£ãŠããªãã£ããããçŽæ¥GithubããDiffusersãªããžããªãã¯ããŒã³ããŠå©çšããŠããŸãã
æ¥ãçµã€ã«ã€ããŠãéåžžã®pipã§ã€ã³ã¹ããŒã«ãå¯èœã«ãªããšæããŸãã
3ã»ã«ç®
from huggingface_hub import login
from google.colab import userdata
HF_LOGIN = userdata.get('HF_LOGIN')
login(HF_LOGIN)
# ã«ã¬ã³ããã£ã¬ã¯ããªãæ¬ãã¡ã€ã«ãååšãããã£ã¬ã¯ããªã«å€æŽããã
import glob
import os
pwd = os.path.dirname(glob.glob('/content/drive/MyDrive/colabzenn/colab_fluxdev_sample2/FluxDev_sample2.ipynb', recursive=True)[0])
print(pwd)
%cd $pwd
!pwd
import sys
sys.path.append("/content/diffusers/src")
HuggingFaceã®ãã°ã€ã³çšã®ç§å¯éµã®ååŸãšãã«ã¬ã³ããã£ã¬ã¯ããªã®èšå®ãšãDiffusersã¢ãžã¥ãŒã«ã®PATHã®è¿œå ã宿œããŠããŸãã
Diffusersã¢ãžã¥ãŒã«ãéåžžã®pipã§ã€ã³ã¹ããŒã«ã§ããããã«ãªããŸããããäžèšéšåã¯äžèŠã«ãªããŸã
import sys
sys.path.append("/content/diffusers/src")
4ã»ã«ç®
#ã¢ãžã¥ãŒã«ãimportãã
from module.module_flux import FLUX
import time
ã¢ãžã¥ãŒã«ãinportããŠããŸãã
FLUX.1ã®å®è£
ã³ãŒãã¯module/module_flux.pyã§èšè¿°ããŠãããŸãã
ãã¡ããåŸè¿°ããŸã
5ã»ã«ç®
#ã¢ãã«ã®èšå®ãè¡ãã
config_text = """
[FLUX]
device = auto
n_steps=24
seed=42
;model_mode = t2i
model_mode = i2i
strength = 0.6
;from_single_file = False
;base_model_path = black-forest-labs/FLUX.1-schnell
base_model_path = black-forest-labs/FLUX.1-dev
use_controlnet = False
controlnet_path = Shakker-Labs/FLUX.1-dev-ControlNet-Union-Pro
;control_mode0 = canny
;control_mode1 = tile
control_mode2 = depth
;control_mode3 = blur
;control_mode4 = pose
;control_mode5 = gray
;control_mode6 = lq
;lora_weight_repo0 = alfredplpl/flux.1-dev-modern-anime-lora
;lora_weight_path0 = modern-anime-lora-2.safetensors
;lora_weight_repo1 = aleksa-codes/flux-ghibsky-illustration
;lora_weight_path1 = lora.safetensors
;lora_scale0 = 1.0
;lora_scale1 = 1.0
;trigger_word0 = "modern anime style"
;trigger_word1 = "GHIBSKY style painting"
;lora_weight_repo2 = None
;lora_weight_path2 = ./inputs/QTCanimation_lora_v1-PAseer.safetensors
;lora_scale2 = 1.0
;trigger_word2 = ""
;select_solver = LCM
;select_solver = DPM
;select_solver = Eulera
select_solver = FMEuler
use_karras_sigmas = True
scheduler_algorithm_type = dpmsolver++
solver_order = 2
cfg_scale = 3.5
;cfg_scale = 1.0
width = 832
height = 1216
output_type = pil
aesthetic_score = 6
negative_aesthetic_score = 2.5
save_latent_simple = False
save_latent_overstep = False
"""
with open("configs/config.ini", "w", encoding="utf-8") as f:
f.write(config_text)
å®éšã®èšå®ãªã©ãèšè¿°ããéšåã§ãã
çŽæ¥configs/config.iniãæžãæããŠãããã®ã»ã«ãå®è¡ãããäžæžããããŠããŸãã®ã§æ³šæããŠãã ããã
;ãã€ãããšã³ã¡ã³ãã¢ãŠãã§ããã®ã§ãä»åã®å®éšã§ã¯äžèŠã ããæ®ããŠããããå®éšèšå®ãªã©ã¯ã³ã¡ã³ãã¢ãŠãããŠæ®ããŠããããšããå§ãããŸãã
6ã»ã«ç®
#èªã¿äžããããã³ãããèšå®ããã
main_prompt = """
modern anime style, a cute Japanese idle singer girl, long Yellowish-white hair with red small ribbon,red eyes,small red hat ,She sings with a smile on her face ,make a peace sign with her left hand, wearing white idle costume, standing on the stage ,This is a flashy concert with 3D holograms and laser effects
"""
#ã³ã³ãããŒã«ãããã«å
¥åããåç
§ç»åã¯0ãã6ãŸã§ã®æ°åãæ³å®ïŒ0.png,6.webpãªã©ãæ°åã¯controlnetã®ã¢ãŒããšäžèŽãããŠãã ããïŒ
#åç
§ïŒã³ã³ãããŒã«ãããã®ã¢ãŒããcanny (0), tile (1), depth (2), blur (3), pose (4), gray (5), low quality (6).
input_refer_image_folder = "./inputs/controlnet/refer"
#ã³ã³ãããŒã«ãããã«å
¥åãã倿åŸã®åç
§ç»åã®æ ŒçŽãã©ã«ããåœåèŠåã¯äžèšãšåæ§
output_refer_image_folder = "./inputs/controlnet/refer_prepared"
#image to imageã¢ãŒããå©çšããéã®ç»åpath
i2i_image_path = "./inputs/imagetoimage/inputs1.png"
çæããããã³ãããšãControlNetãImg2Img Pilelineã§å©çšããåç §ç»åã®æ ŒçŽå Žæãèšè¿°ããŠãŸãã
7ã»ã«ç®
flux = FLUX()
#æå®ããŠããControlNetã§å©çšã§ãã"./inputs/refer_prepared/0.png"ãªã©ããã§ã«ããå Žåã¯ãäžèšã¯ã³ã¡ã³ãã¢ãŠãããŠãè¯ã
#flux.prepare_multi_referimage(input_refer_image_folder = input_refer_image_folder,output_refer_image_folder = output_refer_image_folder, low_threshold = 100, high_threshold = 200, noise_level=25, blur_radius=5)
ç»åçæAIã®FLUX.1ã®ã¯ã©ã¹ã€ã³ã¹ã¿ã³ã¹ãç«ã¡äžããŠããŸãã
ç«ã¡äžãæã«ãã¢ãã«ã®ããŠã³ããŒããšèªã¿èŸŒã¿éååãŸã§å®æœãããŸãã
ä»åã¯ControlNetãå©çšããªãã®ã§ãäžã®ã³ãŒãã¯ã³ã¡ã³ãã¢ãŠãããŠããŸãã
ControlNetãå©çšããå Žåã¯ãäžã®ã³ãŒããå®è¡ããŠãã ããã
äœ¿ãæ¹ã¯ååã®èšäºãåèã«ããŠãã ããã
8ã»ã«ç®
controlnet_conditioning_scale = [0.5]
temp_strength = 0.6
#temp_strength = None
for i in range(5):
start = time.time()
image = flux.generate_image(main_prompt,c_image_path = output_refer_image_folder, i_image_path = i2i_image_path, controlnet_conditioning_scale = controlnet_conditioning_scale, temp_strength = temp_strength)
print("generate image time: ", time.time()-start)
image.save("./outputs/FLUX_result_{}.png".format(i))
ããã§æå®ããseedå€ããé£ç¶ã§5æåã®ç»åãçæããçæã«ããã£ãæéãèšæž¬ããŸãã
çæãããç»åã¯outputsãã©ã«ãã«æ ŒçŽãããŸãã
module/module_flux.py
module/module_flux.pyã«ã€ããŠè§£èª¬ããŸãã
ã³ãŒãã¯äžèšããã芧ãã ãã
èšå®ãã¡ã€ã«ã®äžèº«ãååŸ
class FLUXconfig:
def __init__(self, config_ini_path = './configs/config.ini'):
# iniãã¡ã€ã«ã®èªã¿èŸŒã¿
self.config_ini = configparser.ConfigParser()
# æå®ããiniãã¡ã€ã«ãååšããªãå Žåããšã©ãŒçºç
if not os.path.exists(config_ini_path):
raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), config_ini_path)
self.config_ini.read(config_ini_path, encoding='utf-8')
FLUX_items = self.config_ini.items('FLUX')
self.FLUX_config_dict = dict(FLUX_items)
äžèšã³ãŒãã§ã¯èšå®ãã¡ã€ã«ïŒ./configs/config.iniïŒã®äžèº«ãèŸæžåãšããŠååŸããŠããŸãã
èšå®ãã¡ã€ã«ã¯ããŒãããã¯ããæžãæããããšãã§ããŸãã®ã§ãæ®æ®µã¯æ°ã«ããå¿
èŠã¯ãããŸããã
FLUXã¯ã©ã¹ã®ã³ã³ã¹ãã©ã¯ã¿
initã¡ãœãã
class FLUX:
def __init__(self,device = None, config_ini_path = './configs/config.ini'):
FLUX_config = FLUXconfig(config_ini_path = config_ini_path)
config_dict = FLUX_config.FLUX_config_dict
if device is not None:
self.device = device
else:
device = config_dict["device"]
self.device = "cuda" if torch.cuda.is_available() else "cpu"
if device != "auto":
self.device = device
self.last_latents = None
self.last_step = -1
self.last_timestep = 1000
self.n_steps = int(config_dict["n_steps"])
self.seed = int(config_dict["seed"])
self.generator = torch.Generator(device=self.device).manual_seed(self.seed)
self.use_controlnet = config_dict.get("use_controlnet", "False")
if self.use_controlnet == "False":
self.use_controlnet = False
else:
self.use_controlnet = True
self.model_mode = config_dict.get("model_mode", "None")
if self.model_mode == "t2i":
self.model_mode = "t2i"
print("t2i mode")
elif self.model_mode == "i2i":
self.model_mode = "i2i"
print("i2i mode")
else:
raise ValueError("model_mode is only 't2i' or 'i2i'.")
self.strength = config_dict.get("strength", "None")
if self.strength == "None":
self.strength = None
if self.model_mode == "i2i":
raise ValueError("strength is not set")
else:
self.strength = float(self.strength)
self.controlnet_path = config_dict.get("controlnet_path", "None")
if not self.use_controlnet and self.controlnet_path == "None":
raise ValueError("controlnet_path is not set")
self.control_modes_number_list = []
control_mode_dict = {
"canny":0,
"tile":1,
"depth":2,
"blur":3,
"pose":4,
"gray":5,
"lq":6
}
for i in range(7):
if config_dict.get(f"control_mode{i}", "None") != "None":
self.control_modes_number_list.append(control_mode_dict[config_dict[f"control_mode{i}"]])
self.from_single_file = config_dict.get("from_single_file", "None")
self.SINGLE_FILE_FLAG = True
if self.from_single_file != "True":
self.from_single_file = None
self.SINGLE_FILE_FLAG = False
self.base_model_path = config_dict["base_model_path"]
self.lora_repo_list = []
self.lora_path_list = []
self.lora_scale_list = []
self.lora_trigger_word_list = []
self.lora_nums = 0
self.LORA_FLAG = False
for i in range(10):
if config_dict.get(f"lora_weight_path{i}", "None") != "None":
self.LORA_FLAG = True
#Huggingfaceã®repoããååŸããå Žåã¯ãrepoãšpathïŒãã¡ã€ã«åïŒã®äž¡æ¹ãæå®ãã
if config_dict.get(f"lora_weight_repo{i}", "None") != "None":
self.lora_repo_list.append(config_dict[f"lora_weight_repo{i}"])
#Civitaiãªã©ããããŠã³ããŒãããŠå©çšããå Žåã¯ããã£ã¬ã¯ããªåå«ãpathã®ã¿ã§æå®ãã
else:
self.lora_repo_list.append(None)
self.lora_path_list.append(config_dict[f"lora_weight_path{i}"])
self.lora_nums += 1
self.lora_scale_list.append(float(config_dict.get(f"lora_scale{i}", "1.0")))
self.lora_trigger_word_list.append(config_dict.get(f"trigger_word{i}", "None"))
self.select_solver = config_dict.get("select_solver", "FMEuler")
self.use_karras_sigmas = config_dict.get("use_karras_sigmas", "True")
if self.use_karras_sigmas == "True":
self.use_karras_sigmas = True
else:
self.use_karras_sigmas = False
self.scheduler_algorithm_type = config_dict.get("scheduler_algorithm_type", "dpmsolver++")
self.solver_order = config_dict.get("solver_order", "None")
if self.solver_order != "None":
self.solver_order = int(self.solver_order)
else:
self.solver_order = None
self.cfg_scale = float(config_dict["cfg_scale"])
self.width = int(config_dict["width"])
self.height = int(config_dict["height"])
self.output_type = config_dict["output_type"]
self.aesthetic_score = float(config_dict["aesthetic_score"])
self.negative_aesthetic_score = float(config_dict["negative_aesthetic_score"])
self.save_latent_simple = config_dict["save_latent_simple"]
if self.save_latent_simple == "True":
self.save_latent_simple = True
print("use callback save_latent_simple")
else:
self.save_latent_simple = False
self.save_latent_overstep = config_dict["save_latent_overstep"]
if self.save_latent_overstep == "True":
self.save_latent_overstep = True
print("use callback save_latent_overstep")
else:
self.save_latent_overstep = False
self.use_callback = False
if self.save_latent_simple or self.save_latent_overstep:
self.use_callback = True
if (self.save_latent_simple and self.save_latent_overstep):
raise ValueError("save_latent_simple and save_latent_overstep cannot be set at the same time")
if self.model_mode == "t2i":
if self.LORA_FLAG:
self.base = self.preprepare_model_withLoRAandQuantize()
else:
self.base = self.preprepare_model()
elif self.model_mode == "i2i":
if self.LORA_FLAG:
self.base = self.preprepare_img2img_model_withLoRAandQuantize()
else:
self.base = self.preprepare_img2img_model()
else:
raise ValueError("model_mode is only 't2i' or 'i2i'.")
èšå®ãã¡ã€ã«ãèªã¿èŸŒãã§ãã¯ã©ã¹ã¢ããªãã¥ãŒãã«èšå®ããŠããŸãããŸãLoRAãControlNetãªã©ãå Žåã«ãã£ãŠã¯è€æ°èªã¿èŸŒãŸããå¯èœæ§ã®ããèšå®ãªã©ãã幟ã€èªã¿èŸŒãå¿ èŠãããããªã©ãååŸããŠãå¥ã¡ãœããã§å¿ èŠã¯ãã©ã°ãªã©ãç«ãŠãŠããŸãã
æåŸã«ãpreprepare_modelã«ãŠãã¢ãã«ã®ããŠã³ããŒããèªã¿èŸŒã¿ãéååãªã©ã宿œããŠããŸãã
ååã®èšäºã§èšèŒããŸãããã2024幎9æ11æ¥çŸåšãQuantoã«ããéååãšLoRAã䜵çšãããšãšã©ãŒãåºãŠããŸãåé¡ãããããã§ãã
åŸã£ãŠãLoRAãå©çšãããã©ããã§ãéååããããããªããã®ã¢ãã«ããŒããå€ããŠããŸãã
ãŸããText to ImageãšImage to Imageã§ã¯å©çšããPipelineãéããããããæ¬¡ç¬¬ã§ãã¢ãã«ããŒããéããŸãã
FLUX.1ã¢ãã«ã®èªã¿èŸŒã¿ïŒImage to Image without LoRAïŒ
Text to Imageã«é¢ããŠã¯ååã®èšäºãã芧ãã ããã
preprepare_modelã¡ãœãã
class FLUX:
ã»ã»ã»
def preprepare_img2img_model(self):
if not self.SINGLE_FILE_FLAG:
transformer = FluxTransformer2DModel.from_pretrained(
self.base_model_path,
subfolder="transformer",
torch_dtype=torch.float16
)
print("transformer quantizing")
quantize(transformer, weights=qfloat8)
freeze(transformer)
print("loaded transformer")
text_encoder_2 = T5EncoderModel.from_pretrained(
self.base_model_path,
subfolder="text_encoder_2",
torch_dtype=torch.float16
)
print("text_encoder_2 quantizing")
quantize(text_encoder_2, weights=qfloat8)
freeze(text_encoder_2)
print("loaded text_encoder_2")
base = FluxImg2ImgPipeline.from_pretrained(
self.base_model_path,
transformer=transformer,
text_encoder_2=text_encoder_2,
torch_dtype=torch.float16
)
print("loaded base model")
else:
base = FluxImg2ImgPipeline.from_pretrained(self.base_model_path, torch_dtype=torch.float16)
print("transformer quantizing")
quantize(base.transformer, weights=qfloat8)
freeze(base.transformer)
print("text_encoder_2 quantizing")
quantize(base.text_encoder_2, weights=qfloat8)
freeze(base.text_encoder_2)
print("loaded base model")
print("cpu offloading")
base.enable_model_cpu_offload()
lora_adapter_name_list = []
lora_adapter_weights_list = []
if self.LORA_FLAG:
for i in range(self.lora_nums):
if self.lora_repo_list[i] is not None:
base.load_lora_weights(
pretrained_model_name_or_path_or_dict = self.lora_repo_list[i],
weight_name=self.lora_path_list[i],
adapter_name=f"lora{i}")
else:
base.load_lora_weights(self.lora_path_list[i], adapter_name=f"lora{i}")
lora_adapter_name_list.append(f"lora{i}")
lora_adapter_weights_list.append(self.lora_scale_list[i])
if self.lora_nums > 1:
base.set_adapters(lora_adapter_name_list, adapter_weights=lora_adapter_weights_list)
print("finish lora settings")
if self.select_solver == "DPM":
if self.solver_order is not None:
base.scheduler = DPMSolverMultistepScheduler.from_config(
base.scheduler.config,
use_karras_sigmas=self.use_karras_sigmas,
Algorithm_type =self.scheduler_algorithm_type,
solver_order=self.solver_order,
)
else:
base.scheduler = DPMSolverMultistepScheduler.from_config(
base.scheduler.config,
use_karras_sigmas=self.use_karras_sigmas,
Algorithm_type =self.scheduler_algorithm_type,
)
elif self.select_solver == "LCM":
base.scheduler = LCMScheduler.from_config(base.scheduler.config)
elif self.select_solver == "Eulera":
base.scheduler = EulerAncestralDiscreteScheduler.from_config(base.scheduler.config)
elif self.select_solver == "FMEuler":
base.scheduler = FlowMatchEulerDiscreteScheduler.from_config(base.scheduler.config)
else:
raise ValueError("select_solver is only 'DPM' or 'LCM' or 'Eulera' or 'FMEuler'.")
return base
åºæ¬çã«ã¯ååã®èšäºã®å 容ãšåãã§ãã
ãã ãå©çšããPipeLineãFluxPipelineã§ã¯ãªããFluxImg2ImgPipelineã«ãªããŸãã
LoRAãå©çšãããããããã¯åäžã®safetensorãã¡ã€ã«ããã¢ãã«ãèªã¿èŸŒãã®ããã©ã®ã¹ã±ãžã¥ãŒã©ãå©çšããã®ããªã©ãèšå®ãã¡ã€ã«ã«åã£ãŠäžããé çªã«ã¢ãã«ãæ§ç¯ããŠãããŸãã
FLUX.1ã«ããç»åçæ
generate_imageã¡ãœãã
class FLUX:
ã»ã»ã»
def generate_image(self, prompt, neg_prompt = None, c_image_path = None, i_image_path = None, seed = None, controlnet_conditioning_scale = [1.0], temp_strength = None):
def decode_tensors(pipe, step, timestep, callback_kwargs):
if self.save_latent_simple:
callback_kwargs = decode_tensors_simple(pipe, step, timestep, callback_kwargs)
elif self.save_latent_overstep:
callback_kwargs = decode_tensors_residual(pipe, step, timestep, callback_kwargs)
else:
raise ValueError("save_latent_simple or save_latent_overstep must be set")
return callback_kwargs
def decode_tensors_simple(pipe, step, timestep, callback_kwargs):
latents = callback_kwargs["latents"]
imege = None
if self.save_latent_simple:
image = latents_to_rgb_vae(latents,pipe)
else:
raise ValueError("save_latent_simple is not set")
gettime = time.time()
formatted_time_human_readable = time.strftime("%Y%m%d_%H%M%S", time.localtime(gettime))
image.save(f"./outputs/latent_{formatted_time_human_readable}_{step}_{timestep}.png")
return callback_kwargs
def decode_tensors_residual(pipe, step, timestep, callback_kwargs):
latents = callback_kwargs["latents"]
if step > 0:
residual = latents - self.last_latents
goal = self.last_latents + residual * ((self.last_timestep) / (self.last_timestep - timestep))
#print( ((self.last_timestep) / (self.last_timestep - timestep)))
else:
goal = latents
if self.save_latent_overstep:
image = latents_to_rgb_vae(goal,pipe)
else:
raise ValueError("save_latent_overstep is not set")
gettime = time.time()
formatted_time_human_readable = time.strftime("%Y%m%d_%H%M%S", time.localtime(gettime))
image.save(f"./outputs/latent_{formatted_time_human_readable}_{step}_{timestep}.png")
self.last_latents = latents
self.last_step = step
self.last_timestep = timestep
if timestep == 0:
self.last_latents = None
self.last_step = -1
self.last_timestep = 100
return callback_kwargs
def latents_to_rgb_vae(latents,pipe):
latents = pipe._unpack_latents(latents, self.height, self.width, pipe.vae_scale_factor)
latents = (latents / pipe.vae.config.scaling_factor) + pipe.vae.config.shift_factor
image = pipe.vae.decode(latents, return_dict=False)[0]
image = pipe.image_processor.postprocess(image, output_type=self.output_type)
return FluxPipelineOutput(images=image).images[0]
def load_image_path(image_path):
# ãã image_path ã str ãªããã¡ã€ã«ãã¹ãšããŠç»åãèªã¿èŸŒã
if isinstance(image_path, str):
image = load_image(image_path)
print("Image loaded from file path.")
# ãã image_path ã PIL ã€ã¡ãŒãžãªããã®ãŸãŸäœ¿çš
elif isinstance(image_path, Image.Image):
image = image_path
print("PIL Image object provided.")
# ãã image_path ã Torch ãã³ãœã«ãªããã®ãŸãŸäœ¿çš
elif isinstance(image_path, torch.Tensor):
image = image_path.unsqueeze(0)
image = image.permute(0, 3, 1, 2)
image = image/255.0
print("Torch Tensor object provided.")
else:
raise TypeError("Unsupported type. Provide a file path, PIL Image, or Torch Tensor.")
return image
def find_file_with_extension(image_path, i):
# ãã¿ãŒã³ã«äžèŽãããã¡ã€ã«ãæ€çŽ¢
file_pattern = f"{image_path}/{i}.*"
matching_files = glob.glob(file_pattern)
# ããããããã¡ã€ã«ãååšããå Žåããã®ãã¡ã€ã«ã®ãã¹ãè¿ã
if matching_files:
# äŸ: ./image_path/0.png ã®ãããªå®å
šãªãã¡ã€ã«ãã¹ãååŸããã
return matching_files[0]
else:
# ããããããã¡ã€ã«ããªãå Žå
raise FileNotFoundError(f"No file found matching pattern: {file_pattern}")
return None
if seed is not None:
self.generator = torch.Generator(device=self.device).manual_seed(seed)
if temp_strength is not None:
self.strength = temp_strength
control_image_list = []
if self.use_controlnet and self.model_mode == "t2i":
print("use controlnet mode: ",self.control_modes_number_list)
for i in self.control_modes_number_list:
if c_image_path is None:
raise ValueError("when use controlnet ,control_image_path must be set")
control_image_name = load_image_path(find_file_with_extension(c_image_path, i))
control_image = load_image_path(control_image_name)
control_image_list.append(control_image)
init_image = None
if self.model_mode == "i2i":
print("use i2i mode")
if i_image_path is None:
raise ValueError("when use i2i mode, init_image_path must be set")
init_image = load_image_path(i_image_path)
lora_weight_average = 0
if self.LORA_FLAG:
print("use LoRA")
lora_weight_average = sum(self.lora_scale_list) / len(self.lora_scale_list)
for word in self.lora_trigger_word_list:
if (word is not None) and (word != "None"):
prompt = prompt + ", " + word
image = None
if self.model_mode == "i2i":
if self.use_callback:
if self.LORA_FLAG:
image = self.base(
prompt=prompt,
image=init_image,
strength= self.strength,
guidance_scale=self.cfg_scale,
num_inference_steps=self.n_steps,
output_type=self.output_type,
width = self.width,
height = self.height,
generator=self.generator,
callback_on_step_end=decode_tensors,
callback_on_step_end_tensor_inputs=["latents"],
joint_attention_kwargs={"scale": lora_weight_average},
).images[0]
#LORAãå©çšããªãå Žå
else:
image = self.base(
prompt=prompt,
image=init_image,
strength= self.strength,
guidance_scale=self.cfg_scale,
num_inference_steps=self.n_steps,
output_type=self.output_type,
width = self.width,
height = self.height,
generator=self.generator,
callback_on_step_end=decode_tensors,
callback_on_step_end_tensor_inputs=["latents"],
).images[0]
#latentãä¿åããªãå Žå
else:
if self.LORA_FLAG:
image = self.base(
prompt=prompt,
image=init_image,
strength= self.strength,
guidance_scale=self.cfg_scale,
num_inference_steps=self.n_steps,
output_type=self.output_type,
width = self.width,
height = self.height,
generator=self.generator,
joint_attention_kwargs={"scale": lora_weight_average},
).images[0]
# LORAãå©çšããªãå Žå
else:
image = self.base(
prompt=prompt,
image=init_image,
strength= self.strength,
guidance_scale=self.cfg_scale,
num_inference_steps=self.n_steps,
output_type=self.output_type,
width = self.width,
height = self.height,
generator=self.generator
).images[0]
#t2iã¢ãŒãã®å Žå
elif self.model_mode == "t2i":
if self.use_callback:
if self.LORA_FLAG:
if self.use_controlnet:
image = self.base(
prompt=prompt,
control_image=control_image_list,
control_mode=self.control_modes_number_list,
guidance_scale=self.cfg_scale,
controlnet_conditioning_scale=controlnet_conditioning_scale,
num_inference_steps=self.n_steps,
output_type=self.output_type,
width = self.width,
height = self.height,
generator=self.generator,
callback_on_step_end=decode_tensors,
callback_on_step_end_tensor_inputs=["latents"],
joint_attention_kwargs={"scale": lora_weight_average},
).images[0]
else:
image = self.base(
prompt=prompt,
guidance_scale=self.cfg_scale,
num_inference_steps=self.n_steps,
output_type=self.output_type,
width = self.width,
height = self.height,
generator=self.generator,
callback_on_step_end=decode_tensors,
callback_on_step_end_tensor_inputs=["latents"],
joint_attention_kwargs={"scale": lora_weight_average},
).images[0]
#LORAãå©çšããªãå Žå
else:
if self.use_controlnet:
image = self.base(
prompt=prompt,
control_image=control_image_list,
control_mode=self.control_modes_number_list,
guidance_scale=self.cfg_scale,
controlnet_conditioning_scale=controlnet_conditioning_scale,
num_inference_steps=self.n_steps,
output_type=self.output_type,
width = self.width,
height = self.height,
callback_on_step_end=decode_tensors,
callback_on_step_end_tensor_inputs=["latents"],
generator=self.generator
).images[0]
else:
image = self.base(
prompt=prompt,
guidance_scale=self.cfg_scale,
num_inference_steps=self.n_steps,
output_type=self.output_type,
width = self.width,
height = self.height,
callback_on_step_end=decode_tensors,
callback_on_step_end_tensor_inputs=["latents"],
generator=self.generator
).images[0]
#latentãä¿åããªãå Žå
else:
if self.LORA_FLAG:
if self.use_controlnet:
image = self.base(
prompt=prompt,
control_image=control_image_list,
control_mode=self.control_modes_number_list,
guidance_scale=self.cfg_scale,
controlnet_conditioning_scale=controlnet_conditioning_scale,
num_inference_steps=self.n_steps,
output_type=self.output_type,
width = self.width,
height = self.height,
generator=self.generator,
joint_attention_kwargs={"scale": lora_weight_average},
).images[0]
else:
image = self.base(
prompt=prompt,
guidance_scale=self.cfg_scale,
num_inference_steps=self.n_steps,
output_type=self.output_type,
width = self.width,
height = self.height,
generator=self.generator,
joint_attention_kwargs={"scale": lora_weight_average},
).images[0]
# LORAãå©çšããªãå Žå
else:
if self.use_controlnet:
image = self.base(
prompt=prompt,
control_image=control_image_list,
control_mode=self.control_modes_number_list,
guidance_scale=self.cfg_scale,
controlnet_conditioning_scale=controlnet_conditioning_scale,
num_inference_steps=self.n_steps,
output_type=self.output_type,
width = self.width,
height = self.height,
generator=self.generator
).images[0]
else:
image = self.base(
prompt=prompt,
guidance_scale=self.cfg_scale,
num_inference_steps=self.n_steps,
output_type=self.output_type,
width = self.width,
height = self.height,
generator=self.generator
).images[0]
else:
raise ValueError("model_mode is only 't2i' or 'i2i'.")
return image
ããã§ã¯ãFLUXã«ããç»åçæãè¡ã£ãŠããŸãã
ãã¡ããåºæ¬çã«ååã®èšäºãšåãã§ãããImage to Imageã®å Žåã¯ãè¥å¹²__call__ã¡ãœããã®åŒæ°ãå€ãããŸãã
LoRAãå°å
¥ããããã«çæéäžã®ç»åãåºåããå Žåã¯ãäžèšãå®è¡ãããŸãã
äžèšã§ã¯ãèšå®ãã¡ã€ã«ã«ãŠèšèŒãããŠããèšå®ãšããã³ããããããŠLoRAã®èšå®ãšãåç
§ç»åã®ç»åããŒã¿ããã€ãºã®ä»äžçããããŠãçæéäžã®ç»åãåºåããããã®ã³ãŒã«ããã¯é¢æ°ãèšå®ããŠããŸãã
if self.model_mode == "i2i":
if self.use_callback:
if self.LORA_FLAG:
image = self.base(
prompt=prompt,
image=init_image,
strength= self.strength,
guidance_scale=self.cfg_scale,
num_inference_steps=self.n_steps,
output_type=self.output_type,
width = self.width,
height = self.height,
generator=self.generator,
callback_on_step_end=decode_tensors,
callback_on_step_end_tensor_inputs=["latents"],
joint_attention_kwargs={"scale": lora_weight_average},
).images[0]
ãŸãšãïŒ2åç®ïŒ
ãããŸã§ãå®è£
ã³ãŒãã®è§£èª¬ãããŠãããŸããã
åºæ¬çã«ã¯FLUXã¯ååã®èšäºã§èª¬æããéãã§ãããä»åã¯ããã«Image to Imageã®Pipelineãå°å
¥ããŸããã
ãããŸã§èªãã§ãã ãã£ãŠãæ¬åœã«ããããšãããããŸããïŒ
Discussion