From aa785c3ef1853743358b8a087ca4926e73ff5de3 Mon Sep 17 00:00:00 2001 From: Lincoln Stein Date: Thu, 27 Oct 2022 11:55:00 -0400 Subject: [PATCH] ready for merge after documentation added --- ldm/generate.py | 11 ++-- ldm/invoke/args.py | 105 ++++++++++++++++++++++---------- ldm/invoke/generator/omnibus.py | 2 + scripts/invoke.py | 5 +- 4 files changed, 84 insertions(+), 39 deletions(-) diff --git a/ldm/generate.py b/ldm/generate.py index 76d4068cf8..b075b72b6e 100644 --- a/ldm/generate.py +++ b/ldm/generate.py @@ -428,10 +428,11 @@ class Generate: fit=fit, text_mask=text_mask, invert_mask=invert_mask, + force_outpaint=force_outpaint, ) # TODO: Hacky selection of operation to perform. Needs to be refactored. - generator = self.select_generator(init_image, mask_image, embiggen, hires_fix) + generator = self.select_generator(init_image, mask_image, embiggen, hires_fix, force_outpaint) generator.set_variation( self.seed, variation_amount, with_variations @@ -649,6 +650,7 @@ class Generate: mask_image:Image.Image=None, embiggen:bool=False, hires_fix:bool=False, + force_outpaint:bool=False, ): inpainting_model_in_use = self.sampler.uses_inpainting_model() @@ -678,6 +680,7 @@ class Generate: fit=False, text_mask=None, invert_mask=False, + force_outpaint=False, ): init_image = None init_mask = None @@ -691,7 +694,7 @@ class Generate: # if image has a transparent area and no mask was provided, then try to generate mask if self._has_transparency(image): - self._transparency_check_and_warning(image, mask) + self._transparency_check_and_warning(image, mask, force_outpaint) init_mask = self._create_init_mask(image, width, height, fit=fit) if (image.width * image.height) > (self.width * self.height) and self.size_matters: @@ -1005,11 +1008,11 @@ class Generate: colored += 1 return colored == 0 - def _transparency_check_and_warning(self,image, mask): + def _transparency_check_and_warning(self,image, mask, force_outpaint=False): if not mask: print( '>> Initial image has transparent areas. Will inpaint in these regions.') - if self._check_for_erasure(image): + if (not force_outpaint) and self._check_for_erasure(image): print( '>> WARNING: Colors underneath the transparent region seem to have been erased.\n', '>> Inpainting will be suboptimal. Please preserve the colors when making\n', diff --git a/ldm/invoke/args.py b/ldm/invoke/args.py index 3c1bf2eae4..deb4196644 100644 --- a/ldm/invoke/args.py +++ b/ldm/invoke/args.py @@ -177,13 +177,16 @@ class Args(object): else: # no initial quote, so get everything up to the first thing # that looks like a switch - match = re.match('^(.+?)\s(--?[a-zA-Z].+)',cmd_string) - if match: - prompt,switches = match.groups() + if cmd_string.startswith('-'): + prompt = '' + switches = cmd_string else: - prompt = cmd_string - switches = '' - + match = re.match('^(.+?)\s(--?[a-zA-Z].+)',cmd_string) + if match: + prompt,switches = match.groups() + else: + prompt = cmd_string + switches = '' try: self._cmd_switches = self._cmd_parser.parse_args(shlex.split(switches)) setattr(self._cmd_switches,'prompt',prompt) @@ -566,9 +569,12 @@ class Args(object): ) render_group = parser.add_argument_group('General rendering') img2img_group = parser.add_argument_group('Image-to-image and inpainting') + inpainting_group = parser.add_argument_group('Inpainting') + outpainting_group = parser.add_argument_group('Outpainting and outcropping') variation_group = parser.add_argument_group('Creating and combining variations') postprocessing_group = parser.add_argument_group('Post-processing') special_effects_group = parser.add_argument_group('Special effects') + deprecated_group = parser.add_argument_group('Deprecated options') render_group.add_argument( '--prompt', default='', @@ -699,17 +705,6 @@ class Args(object): type=str, help='Path to input image for img2img mode (supersedes width and height)', ) - img2img_group.add_argument( - '-M', - '--init_mask', - type=str, - help='Path to input mask for inpainting mode (supersedes width and height)', - ) - img2img_group.add_argument( - '--invert_mask', - action='store_true', - help='Invert the mask', - ) img2img_group.add_argument( '-tm', '--text_mask', @@ -737,29 +732,68 @@ class Args(object): help='Strength for noising/unnoising. 0.0 preserves image exactly, 1.0 replaces it completely', default=0.75, ) - img2img_group.add_argument( - '-D', - '--out_direction', - nargs='+', + inpainting_group.add_argument( + '-M', + '--init_mask', type=str, - metavar=('direction', 'pixels'), - help='Direction to extend the given image (left|right|top|bottom). If a distance pixel value is not specified it defaults to half the image size' + help='Path to input mask for inpainting mode (supersedes width and height)', ) - img2img_group.add_argument( - '-c', - '--outcrop', - nargs='+', - type=str, - metavar=('direction','pixels'), - help='Outcrop the image with one or more direction/pixel pairs: -c top 64 bottom 128 left 64 right 64', + inpainting_group.add_argument( + '--invert_mask', + action='store_true', + help='Invert the mask', ) - img2img_group.add_argument( + inpainting_group.add_argument( '-r', '--inpaint_replace', type=float, default=0.0, help='when inpainting, adjust how aggressively to replace the part of the picture under the mask, from 0.0 (a gentle merge) to 1.0 (replace entirely)', ) + outpainting_group.add_argument( + '-c', + '--outcrop', + nargs='+', + type=str, + metavar=('direction','pixels'), + help='Outcrop the image with one or more direction/pixel pairs: e.g. -c top 64 bottom 128 left 64 right 64', + ) + outpainting_group.add_argument( + '--force_outpaint', + action='store_true', + default=False, + help='Force outpainting if you have no inpainting mask to pass', + ) + outpainting_group.add_argument( + '--seam_size', + type=int, + default=0, + help='When outpainting, size of the mask around the seam between original and outpainted image', + ) + outpainting_group.add_argument( + '--seam_blur', + type=int, + default=0, + help='When outpainting, the amount to blur the seam inwards', + ) + outpainting_group.add_argument( + '--seam_strength', + type=float, + default=0.7, + help='When outpainting, the img2img strength to use when filling the seam. Values around 0.7 work well', + ) + outpainting_group.add_argument( + '--seam_steps', + type=int, + default=10, + help='When outpainting, the number of steps to use to fill the seam. Low values (~10) work well', + ) + outpainting_group.add_argument( + '--tile_size', + type=int, + default=32, + help='When outpainting, the tile size to use for filling outpaint areas', + ) postprocessing_group.add_argument( '-ft', '--facetool', @@ -843,7 +877,14 @@ class Args(object): dest='use_mps_noise', help='Simulate noise on M1 systems to get the same results' ) - + deprecated_group.add_argument( + '-D', + '--out_direction', + nargs='+', + type=str, + metavar=('direction', 'pixels'), + help='Older outcropping system. Direction to extend the given image (left|right|top|bottom). If a distance pixel value is not specified it defaults to half the image size' + ) return parser def format_metadata(**kwargs): diff --git a/ldm/invoke/generator/omnibus.py b/ldm/invoke/generator/omnibus.py index e0705ec397..e8426a9205 100644 --- a/ldm/invoke/generator/omnibus.py +++ b/ldm/invoke/generator/omnibus.py @@ -42,6 +42,8 @@ class Omnibus(Img2Img,Txt2Img): ) if isinstance(init_image, Image.Image): + if init_image.mode != 'RGB': + init_image = init_image.convert('RGB') init_image = self._image_to_tensor(init_image) if isinstance(mask_image, Image.Image): diff --git a/scripts/invoke.py b/scripts/invoke.py index 1937d47ab5..671a8ad227 100644 --- a/scripts/invoke.py +++ b/scripts/invoke.py @@ -172,9 +172,8 @@ def main_loop(gen, opt): except (OSError, AttributeError, KeyError): pass -# if len(opt.prompt) == 0: -# print('\nTry again with a prompt!') -# continue + if len(opt.prompt) == 0: + opt.prompt = '' # width and height are set by model if not specified if not opt.width: