enhance outcropping with ability to direct contents of new regions

- When outcropping an image you can now add a `--new_prompt` option, to specify
  a new prompt to be used instead of the original one used to generate the image.

- Similarly you can provide a new seed using `--seed` (or `-S`). A seed of zero
  will pick one randomly.

- This PR also fixes the crash that happened when trying to outcrop an image
  that does not contain InvokeAI metadata.
This commit is contained in:
Lincoln Stein 2022-11-08 17:27:42 +00:00
parent 48aa6416dc
commit 8aa94d5774
5 changed files with 48 additions and 14 deletions

View File

@ -92,6 +92,21 @@ The new image is larger than the original (576x704) because 64 pixels were added
to the top and right sides. You will need enough VRAM to process an image of
this size.
#### Outcropping non-InvokeAI images
You can outcrop an arbitrary image that was not generated by InvokeAI,
but your results will vary. The `inpainting-1.5` model is highly
recommended, but if not feasible, then you may be able to improve the
output by conditioning the outcropping with a text prompt that
describes the scene using the `--new_prompt` argument:
```bash
invoke> !fix images/vacation.png --outcrop top 128 --new_prompt "family vacation"
```
You may also provide a different seed for outcropping to use by passing
`-S<seed>`. A seed of "0" will generate a new random seed.
A number of caveats:
1. Although you can specify any pixel values, they will be rounded up to the

View File

@ -561,18 +561,22 @@ class Generate:
):
# retrieve the seed from the image;
seed = None
image_metadata = None
prompt = None
args = metadata_from_png(image_path)
seed = args.seed
prompt = args.prompt or ''
if seed == 0:
seed = random.randrange(0, np.iinfo(np.uint32).max)
opt.seed = seed
print(f'>> generated new seed {seed} and prompt "{prompt}" for {image_path}')
if opt.seed is not None:
seed = opt.seed
elif args.seed >= 0:
seed = args.seed
else:
print(f'>> retrieved seed {seed} and prompt "{prompt}" from {image_path}')
seed = random.randrange(0, np.iinfo(np.uint32).max)
if opt.prompt is not None:
prompt = opt.prompt
else:
prompt = args.prompt
print(f'>> using seed {seed} and prompt "{prompt}" for {image_path}')
# try to reuse the same filename prefix as the original file.
# we take everything up to the first period
@ -619,6 +623,10 @@ class Generate:
extend_instructions[direction]=int(pixels)
except ValueError:
print(f'** invalid extension instruction. Use <directions> <pixels>..., as in "top 64 left 128 right 64 bottom 64"')
opt.seed = seed
opt.prompt = prompt
if len(extend_instructions)>0:
restorer = Outcrop(image,self,)
return restorer.process (

View File

@ -864,6 +864,11 @@ class Args(object):
default=32,
help='When outpainting, the tile size to use for filling outpaint areas',
)
postprocessing_group.add_argument(
'--new_prompt',
type=str,
help='Change the text prompt applied during postprocessing (default, use original generation prompt)',
)
postprocessing_group.add_argument(
'-ft',
'--facetool',

View File

@ -32,8 +32,8 @@ class Outcrop(object):
image_callback(img,preferred_seed,use_prefix=prefix,**kwargs)
result= self.generate.prompt2image(
orig_opt.prompt,
seed = orig_opt.seed if orig_opt.seed>0 else opt.seed,
opt.prompt,
seed = opt.seed if opt.seed else orig_opt.seed,
sampler = self.generate.sampler,
steps = opt.steps,
cfg_scale = opt.cfg_scale,

View File

@ -277,7 +277,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 +317,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 +614,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
@ -707,7 +713,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