enhance outcropping with ability to direct contents of new regions

This commit does several things that improve the customizability of the CLI `outcrop` command:

1. When outcropping an image you can now add a `--new_prompt` option, to specify a new prompt to be applied to the outpainted region instead of the prompt used to generate the image.
2. Similarly you can provide a new seed using `--seed` (or `-S`). A seed less than zero will pick one randomly.
3. The metadata written into the outcropped file is now more informative about what was previously stored.
4. This PR also fixes the crash that happened when trying to outcrop an image  that does not contain InvokeAI metadata.

Other changes:

- add error checking suggested by @Kyle0654
- add special case in invoke.py to allow -1 to be passed as seed.
  This now only occurs for postprocessing commands. Previously, -1
  caused previous seed to be used, and this still applies to generate
  operations.
This commit is contained in:
Lincoln Stein
2022-11-08 17:27:42 +00:00
parent 5606af5083
commit 9141132a5c
7 changed files with 60 additions and 19 deletions

View File

@ -208,7 +208,10 @@ def main_loop(gen, opt):
setattr(opt,attr,path)
# retrieve previous value of seed if requested
if opt.seed is not None and opt.seed < 0:
# Exception: for postprocess operations negative seed values
# mean "discard the original seed and generate a new one"
# (this is a non-obvious hack and needs to be reworked)
if opt.seed is not None and opt.seed < 0 and operation != 'postprocess':
try:
opt.seed = last_results[opt.seed][1]
print(f'>> Reusing previous seed {opt.seed}')
@ -277,7 +280,7 @@ def main_loop(gen, opt):
filename = f'{prefix}.{use_prefix}.{seed}.png'
tm = opt.text_mask[0]
th = opt.text_mask[1] if len(opt.text_mask)>1 else 0.5
formatted_dream_prompt = f'!mask {opt.prompt} -tm {tm} {th}'
formatted_dream_prompt = f'!mask {opt.input_file_path} -tm {tm} {th}'
path = file_writer.save_image_and_prompt_to_png(
image = image,
dream_prompt = formatted_dream_prompt,
@ -317,7 +320,7 @@ def main_loop(gen, opt):
tool = re.match('postprocess:(\w+)',opt.last_operation).groups()[0]
add_postprocessing_to_metadata(
opt,
opt.prompt,
opt.input_file_path,
filename,
tool,
formatted_dream_prompt,
@ -614,10 +617,16 @@ def do_textmask(gen, opt, callback):
)
def do_postprocess (gen, opt, callback):
file_path = opt.prompt # treat the prompt as the file pathname
file_path = opt.prompt # treat the prompt as the file pathname
if opt.new_prompt is not None:
opt.prompt = opt.new_prompt
else:
opt.prompt = None
if os.path.dirname(file_path) == '': #basename given
file_path = os.path.join(opt.outdir,file_path)
opt.input_file_path = file_path
tool=None
if opt.facetool_strength > 0:
tool = opt.facetool
@ -659,7 +668,11 @@ def add_postprocessing_to_metadata(opt,original_file,new_file,tool,command):
try:
meta = retrieve_metadata(original_file)['sd-metadata']
except AttributeError:
meta = retrieve_metadata(new_file)['sd-metadata']
try:
meta = retrieve_metadata(new_file)['sd-metadata']
except AttributeError:
meta = {}
if 'image' not in meta:
meta = metadata_dumps(opt,seeds=[opt.seed])['image']
meta['image'] = {}
@ -707,7 +720,7 @@ def prepare_image_metadata(
elif len(prior_variations) > 0:
formatted_dream_prompt = opt.dream_prompt_str(seed=first_seed)
elif operation == 'postprocess':
formatted_dream_prompt = '!fix '+opt.dream_prompt_str(seed=seed)
formatted_dream_prompt = '!fix '+opt.dream_prompt_str(seed=seed,prompt=opt.input_file_path)
else:
formatted_dream_prompt = opt.dream_prompt_str(seed=seed)
return filename,formatted_dream_prompt