Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
S
Stable Diffusion Webui
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
novelai-storage
Stable Diffusion Webui
Commits
127bfb6c
Commit
127bfb6c
authored
Feb 04, 2023
by
AUTOMATIC1111
Committed by
GitHub
Feb 04, 2023
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #7481 from Klace/master
img2img instruct-pix2pix support
parents
226d840e
ba6a4e7e
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
107 additions
and
8 deletions
+107
-8
modules/img2img.py
modules/img2img.py
+2
-1
modules/processing.py
modules/processing.py
+5
-2
modules/sd_samplers_kdiffusion.py
modules/sd_samplers_kdiffusion.py
+97
-5
modules/ui.py
modules/ui.py
+3
-0
No files found.
modules/img2img.py
View file @
127bfb6c
...
...
@@ -76,7 +76,7 @@ def process_batch(p, input_dir, output_dir, inpaint_mask_dir, args):
processed_image
.
save
(
os
.
path
.
join
(
output_dir
,
filename
))
def
img2img
(
id_task
:
str
,
mode
:
int
,
prompt
:
str
,
negative_prompt
:
str
,
prompt_styles
,
init_img
,
sketch
,
init_img_with_mask
,
inpaint_color_sketch
,
inpaint_color_sketch_orig
,
init_img_inpaint
,
init_mask_inpaint
,
steps
:
int
,
sampler_index
:
int
,
mask_blur
:
int
,
mask_alpha
:
float
,
inpainting_fill
:
int
,
restore_faces
:
bool
,
tiling
:
bool
,
n_iter
:
int
,
batch_size
:
int
,
cfg_scale
:
float
,
denoising_strength
:
float
,
seed
:
int
,
subseed
:
int
,
subseed_strength
:
float
,
seed_resize_from_h
:
int
,
seed_resize_from_w
:
int
,
seed_enable_extras
:
bool
,
height
:
int
,
width
:
int
,
resize_mode
:
int
,
inpaint_full_res
:
bool
,
inpaint_full_res_padding
:
int
,
inpainting_mask_invert
:
int
,
img2img_batch_input_dir
:
str
,
img2img_batch_output_dir
:
str
,
img2img_batch_inpaint_mask_dir
:
str
,
override_settings_texts
,
*
args
):
def
img2img
(
id_task
:
str
,
mode
:
int
,
prompt
:
str
,
negative_prompt
:
str
,
prompt_styles
,
init_img
,
sketch
,
init_img_with_mask
,
inpaint_color_sketch
,
inpaint_color_sketch_orig
,
init_img_inpaint
,
init_mask_inpaint
,
steps
:
int
,
sampler_index
:
int
,
mask_blur
:
int
,
mask_alpha
:
float
,
inpainting_fill
:
int
,
restore_faces
:
bool
,
tiling
:
bool
,
n_iter
:
int
,
batch_size
:
int
,
cfg_scale
:
float
,
image_cfg_scale
:
float
,
denoising_strength
:
float
,
seed
:
int
,
subseed
:
int
,
subseed_strength
:
float
,
seed_resize_from_h
:
int
,
seed_resize_from_w
:
int
,
seed_enable_extras
:
bool
,
height
:
int
,
width
:
int
,
resize_mode
:
int
,
inpaint_full_res
:
bool
,
inpaint_full_res_padding
:
int
,
inpainting_mask_invert
:
int
,
img2img_batch_input_dir
:
str
,
img2img_batch_output_dir
:
str
,
img2img_batch_inpaint_mask_dir
:
str
,
override_settings_texts
,
*
args
):
override_settings
=
create_override_settings_dict
(
override_settings_texts
)
is_batch
=
mode
==
5
...
...
@@ -142,6 +142,7 @@ def img2img(id_task: str, mode: int, prompt: str, negative_prompt: str, prompt_s
inpainting_fill
=
inpainting_fill
,
resize_mode
=
resize_mode
,
denoising_strength
=
denoising_strength
,
image_cfg_scale
=
image_cfg_scale
,
inpaint_full_res
=
inpaint_full_res
,
inpaint_full_res_padding
=
inpaint_full_res_padding
,
inpainting_mask_invert
=
inpainting_mask_invert
,
...
...
modules/processing.py
View file @
127bfb6c
...
...
@@ -186,7 +186,7 @@ class StableDiffusionProcessing:
return
conditioning
def
edit_image_conditioning
(
self
,
source_image
):
conditioning_image
=
self
.
sd_model
.
get_first_stage_encoding
(
self
.
sd_model
.
encode_first_stage
(
source_image
)
)
conditioning_image
=
self
.
sd_model
.
encode_first_stage
(
source_image
)
.
mode
(
)
return
conditioning_image
...
...
@@ -268,6 +268,7 @@ class Processed:
self
.
height
=
p
.
height
self
.
sampler_name
=
p
.
sampler_name
self
.
cfg_scale
=
p
.
cfg_scale
self
.
image_cfg_scale
=
getattr
(
p
,
'image_cfg_scale'
,
None
)
self
.
steps
=
p
.
steps
self
.
batch_size
=
p
.
batch_size
self
.
restore_faces
=
p
.
restore_faces
...
...
@@ -445,6 +446,7 @@ def create_infotext(p, all_prompts, all_seeds, all_subseeds, comments=None, iter
"Steps"
:
p
.
steps
,
"Sampler"
:
p
.
sampler_name
,
"CFG scale"
:
p
.
cfg_scale
,
"Image CFG scale"
:
getattr
(
p
,
'image_cfg_scale'
,
None
),
"Seed"
:
all_seeds
[
index
],
"Face restoration"
:
(
opts
.
face_restoration_model
if
p
.
restore_faces
else
None
),
"Size"
:
f
"{p.width}x{p.height}"
,
...
...
@@ -901,12 +903,13 @@ class StableDiffusionProcessingTxt2Img(StableDiffusionProcessing):
class
StableDiffusionProcessingImg2Img
(
StableDiffusionProcessing
):
sampler
=
None
def
__init__
(
self
,
init_images
:
list
=
None
,
resize_mode
:
int
=
0
,
denoising_strength
:
float
=
0.75
,
mask
:
Any
=
None
,
mask_blur
:
int
=
4
,
inpainting_fill
:
int
=
0
,
inpaint_full_res
:
bool
=
True
,
inpaint_full_res_padding
:
int
=
0
,
inpainting_mask_invert
:
int
=
0
,
initial_noise_multiplier
:
float
=
None
,
**
kwargs
):
def
__init__
(
self
,
init_images
:
list
=
None
,
resize_mode
:
int
=
0
,
denoising_strength
:
float
=
0.75
,
image_cfg_scale
:
float
=
None
,
mask
:
Any
=
None
,
mask_blur
:
int
=
4
,
inpainting_fill
:
int
=
0
,
inpaint_full_res
:
bool
=
True
,
inpaint_full_res_padding
:
int
=
0
,
inpainting_mask_invert
:
int
=
0
,
initial_noise_multiplier
:
float
=
None
,
**
kwargs
):
super
()
.
__init__
(
**
kwargs
)
self
.
init_images
=
init_images
self
.
resize_mode
:
int
=
resize_mode
self
.
denoising_strength
:
float
=
denoising_strength
self
.
image_cfg_scale
:
float
=
image_cfg_scale
if
shared
.
sd_model
.
cond_stage_key
==
"edit"
else
None
self
.
init_latent
=
None
self
.
image_mask
=
mask
self
.
latent_mask
=
None
...
...
modules/sd_samplers_kdiffusion.py
View file @
127bfb6c
from
collections
import
deque
import
torch
import
inspect
import
einops
import
k_diffusion.sampling
from
modules
import
prompt_parser
,
devices
,
sd_samplers_common
...
...
@@ -40,6 +41,90 @@ sampler_extra_params = {
'sample_dpm_2'
:
[
's_churn'
,
's_tmin'
,
's_tmax'
,
's_noise'
],
}
class
CFGDenoiserEdit
(
torch
.
nn
.
Module
):
"""
Classifier free guidance denoiser. A wrapper for stable diffusion model (specifically for unet)
that can take a noisy picture and produce a noise-free picture using two guidances (prompts)
instead of one. Originally, the second prompt is just an empty string, but we use non-empty
negative prompt.
"""
def
__init__
(
self
,
model
):
super
()
.
__init__
()
self
.
inner_model
=
model
self
.
mask
=
None
self
.
nmask
=
None
self
.
init_latent
=
None
self
.
step
=
0
def
combine_denoised
(
self
,
x_out
,
conds_list
,
uncond
,
cond_scale
,
image_cfg_scale
):
denoised_uncond
=
x_out
[
-
uncond
.
shape
[
0
]:]
denoised
=
torch
.
clone
(
denoised_uncond
)
for
i
,
conds
in
enumerate
(
conds_list
):
for
cond_index
,
weight
in
conds
:
out_cond
,
out_img_cond
,
out_uncond
=
x_out
.
chunk
(
3
)
denoised
[
i
]
=
out_uncond
[
cond_index
]
+
cond_scale
*
(
out_cond
[
cond_index
]
-
out_img_cond
[
cond_index
])
+
image_cfg_scale
*
(
out_img_cond
[
cond_index
]
-
out_uncond
[
cond_index
])
return
denoised
def
forward
(
self
,
x
,
sigma
,
uncond
,
cond
,
cond_scale
,
image_cond
,
image_cfg_scale
):
if
state
.
interrupted
or
state
.
skipped
:
raise
sd_samplers_common
.
InterruptedException
conds_list
,
tensor
=
prompt_parser
.
reconstruct_multicond_batch
(
cond
,
self
.
step
)
uncond
=
prompt_parser
.
reconstruct_cond_batch
(
uncond
,
self
.
step
)
batch_size
=
len
(
conds_list
)
repeats
=
[
len
(
conds_list
[
i
])
for
i
in
range
(
batch_size
)]
x_in
=
torch
.
cat
([
torch
.
stack
([
x
[
i
]
for
_
in
range
(
n
)])
for
i
,
n
in
enumerate
(
repeats
)]
+
[
x
]
+
[
x
])
sigma_in
=
torch
.
cat
([
torch
.
stack
([
sigma
[
i
]
for
_
in
range
(
n
)])
for
i
,
n
in
enumerate
(
repeats
)]
+
[
sigma
]
+
[
sigma
])
image_cond_in
=
torch
.
cat
([
torch
.
stack
([
image_cond
[
i
]
for
_
in
range
(
n
)])
for
i
,
n
in
enumerate
(
repeats
)]
+
[
image_cond
]
+
[
torch
.
zeros_like
(
self
.
init_latent
)])
denoiser_params
=
CFGDenoiserParams
(
x_in
,
image_cond_in
,
sigma_in
,
state
.
sampling_step
,
state
.
sampling_steps
)
cfg_denoiser_callback
(
denoiser_params
)
x_in
=
denoiser_params
.
x
image_cond_in
=
denoiser_params
.
image_cond
sigma_in
=
denoiser_params
.
sigma
if
tensor
.
shape
[
1
]
==
uncond
.
shape
[
1
]:
cond_in
=
torch
.
cat
([
tensor
,
uncond
,
uncond
])
if
shared
.
batch_cond_uncond
:
x_out
=
self
.
inner_model
(
x_in
,
sigma_in
,
cond
=
{
"c_crossattn"
:
[
cond_in
],
"c_concat"
:
[
image_cond_in
]})
else
:
x_out
=
torch
.
zeros_like
(
x_in
)
for
batch_offset
in
range
(
0
,
x_out
.
shape
[
0
],
batch_size
):
a
=
batch_offset
b
=
a
+
batch_size
x_out
[
a
:
b
]
=
self
.
inner_model
(
x_in
[
a
:
b
],
sigma_in
[
a
:
b
],
cond
=
{
"c_crossattn"
:
[
cond_in
[
a
:
b
]],
"c_concat"
:
[
image_cond_in
[
a
:
b
]]})
else
:
x_out
=
torch
.
zeros_like
(
x_in
)
batch_size
=
batch_size
*
2
if
shared
.
batch_cond_uncond
else
batch_size
for
batch_offset
in
range
(
0
,
tensor
.
shape
[
0
],
batch_size
):
a
=
batch_offset
b
=
min
(
a
+
batch_size
,
tensor
.
shape
[
0
])
x_out
[
a
:
b
]
=
self
.
inner_model
(
x_in
[
a
:
b
],
sigma_in
[
a
:
b
],
cond
=
{
"c_crossattn"
:
torch
.
cat
([
tensor
[
a
:
b
]],
uncond
)
,
"c_concat"
:
[
image_cond_in
[
a
:
b
]]})
x_out
[
-
uncond
.
shape
[
0
]:]
=
self
.
inner_model
(
x_in
[
-
uncond
.
shape
[
0
]:],
sigma_in
[
-
uncond
.
shape
[
0
]:],
cond
=
{
"c_crossattn"
:
[
uncond
],
"c_concat"
:
[
image_cond_in
[
-
uncond
.
shape
[
0
]:]]})
devices
.
test_for_nans
(
x_out
,
"unet"
)
if
opts
.
live_preview_content
==
"Prompt"
:
sd_samplers_common
.
store_latent
(
x_out
[
0
:
uncond
.
shape
[
0
]])
elif
opts
.
live_preview_content
==
"Negative prompt"
:
sd_samplers_common
.
store_latent
(
x_out
[
-
uncond
.
shape
[
0
]:])
denoised
=
self
.
combine_denoised
(
x_out
,
conds_list
,
uncond
,
cond_scale
,
image_cfg_scale
)
if
self
.
mask
is
not
None
:
denoised
=
self
.
init_latent
*
self
.
mask
+
self
.
nmask
*
denoised
self
.
step
+=
1
return
denoised
class
CFGDenoiser
(
torch
.
nn
.
Module
):
"""
...
...
@@ -78,8 +163,8 @@ class CFGDenoiser(torch.nn.Module):
repeats
=
[
len
(
conds_list
[
i
])
for
i
in
range
(
batch_size
)]
x_in
=
torch
.
cat
([
torch
.
stack
([
x
[
i
]
for
_
in
range
(
n
)])
for
i
,
n
in
enumerate
(
repeats
)]
+
[
x
])
image_cond_in
=
torch
.
cat
([
torch
.
stack
([
image_cond
[
i
]
for
_
in
range
(
n
)])
for
i
,
n
in
enumerate
(
repeats
)]
+
[
image_cond
])
sigma_in
=
torch
.
cat
([
torch
.
stack
([
sigma
[
i
]
for
_
in
range
(
n
)])
for
i
,
n
in
enumerate
(
repeats
)]
+
[
sigma
])
image_cond_in
=
torch
.
cat
([
torch
.
stack
([
image_cond
[
i
]
for
_
in
range
(
n
)])
for
i
,
n
in
enumerate
(
repeats
)]
+
[
image_cond
])
denoiser_params
=
CFGDenoiserParams
(
x_in
,
image_cond_in
,
sigma_in
,
state
.
sampling_step
,
state
.
sampling_steps
)
cfg_denoiser_callback
(
denoiser_params
)
...
...
@@ -195,6 +280,9 @@ class KDiffusionSampler:
return
p
.
steps
def
initialize
(
self
,
p
):
if
shared
.
sd_model
.
cond_stage_key
==
"edit"
and
getattr
(
p
,
'image_cfg_scale'
,
None
)
!=
1
:
self
.
model_wrap_cfg
=
CFGDenoiserEdit
(
self
.
model_wrap
)
self
.
model_wrap_cfg
.
mask
=
p
.
mask
if
hasattr
(
p
,
'mask'
)
else
None
self
.
model_wrap_cfg
.
nmask
=
p
.
nmask
if
hasattr
(
p
,
'nmask'
)
else
None
self
.
model_wrap_cfg
.
step
=
0
...
...
@@ -260,13 +348,17 @@ class KDiffusionSampler:
self
.
model_wrap_cfg
.
init_latent
=
x
self
.
last_latent
=
x
samples
=
self
.
launch_sampling
(
t_enc
+
1
,
lambda
:
self
.
func
(
self
.
model_wrap_cfg
,
xi
,
extra_args
=
{
extra_args
=
{
'cond'
:
conditioning
,
'image_cond'
:
image_conditioning
,
'uncond'
:
unconditional_conditioning
,
'cond_scale'
:
p
.
cfg_scale
},
disable
=
False
,
callback
=
self
.
callback_state
,
**
extra_params_kwargs
))
'cond_scale'
:
p
.
cfg_scale
,
}
if
hasattr
(
p
,
'image_cfg_scale'
)
and
p
.
image_cfg_scale
!=
1
and
p
.
image_cfg_scale
!=
None
:
extra_args
[
'image_cfg_scale'
]
=
p
.
image_cfg_scale
samples
=
self
.
launch_sampling
(
t_enc
+
1
,
lambda
:
self
.
func
(
self
.
model_wrap_cfg
,
xi
,
extra_args
=
extra_args
,
disable
=
False
,
callback
=
self
.
callback_state
,
**
extra_params_kwargs
))
return
samples
...
...
modules/ui.py
View file @
127bfb6c
...
...
@@ -766,6 +766,7 @@ def create_ui():
elif
category
==
"cfg"
:
with
FormGroup
():
cfg_scale
=
gr
.
Slider
(
minimum
=
1.0
,
maximum
=
30.0
,
step
=
0.5
,
label
=
'CFG Scale'
,
value
=
7.0
,
elem_id
=
"img2img_cfg_scale"
)
image_cfg_scale
=
gr
.
Slider
(
minimum
=
0
,
maximum
=
3.0
,
step
=
0.05
,
label
=
'Image CFG Scale (for instruct-pix2pix models only)'
,
value
=
1.5
,
elem_id
=
"img2img_image_cfg_scale"
)
denoising_strength
=
gr
.
Slider
(
minimum
=
0.0
,
maximum
=
1.0
,
step
=
0.01
,
label
=
'Denoising strength'
,
value
=
0.75
,
elem_id
=
"img2img_denoising_strength"
)
elif
category
==
"seed"
:
...
...
@@ -861,6 +862,7 @@ def create_ui():
batch_count
,
batch_size
,
cfg_scale
,
image_cfg_scale
,
denoising_strength
,
seed
,
subseed
,
subseed_strength
,
seed_resize_from_h
,
seed_resize_from_w
,
seed_checkbox
,
...
...
@@ -947,6 +949,7 @@ def create_ui():
(
sampler_index
,
"Sampler"
),
(
restore_faces
,
"Face restoration"
),
(
cfg_scale
,
"CFG scale"
),
(
image_cfg_scale
,
"Image CFG scale"
),
(
seed
,
"Seed"
),
(
width
,
"Size-1"
),
(
height
,
"Size-2"
),
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment