diff --git a/README.md b/README.md index 179be569b2..17955d155d 100644 --- a/README.md +++ b/README.md @@ -163,8 +163,6 @@ Then pass this file's name to dream.py when you invoke it: (ldm) ~/stable-diffusion$ python3 scripts/dream.py --from_file="path/to/prompts.txt" ~~~~ ->>>>>>> big-refactoring - ## Weighted Prompts You may weight different sections of the prompt to tell the sampler to attach different levels of @@ -247,6 +245,12 @@ repository and associated paper for details and limitations. ## Changes + * v1.11 (pending) + * Created a feature branch named **yunsaki-morphing-dream** which adds experimental support for + iteratively modifying the prompt and its parameters. Please see[ Pull Request #86](https://github.com/lstein/stable-diffusion/pull/86) + for a synopsis of how this works. Note that when this feature is eventually added to the main branch, it will may be modified + significantly. + * v1.10 (25 August 2022) * A barebones but fully functional interactive web server for online generation of txt2img and img2img. diff --git a/ldm/dream_util.py b/ldm/dream/pngwriter.py similarity index 56% rename from ldm/dream_util.py rename to ldm/dream/pngwriter.py index b69a0c1367..aca7b47c21 100644 --- a/ldm/dream_util.py +++ b/ldm/dream/pngwriter.py @@ -1,6 +1,14 @@ -'''Utilities for dealing with PNG images and their path names''' +''' +Two helper classes for dealing with PNG images and their path names. +PngWriter -- Converts Images generated by T2I into PNGs, finds + appropriate names for them, and writes prompt metadata + into the PNG. Intended to be subclassable in order to + create more complex naming schemes, including using the + prompt for file/directory names. +PromptFormatter -- Utility for converting a Namespace of prompt parameters + back into a formatted prompt string with command-line switches. +''' import os -import atexit import re from math import sqrt,floor,ceil from PIL import Image,PngImagePlugin @@ -105,91 +113,3 @@ class PromptFormatter(): switches.append('-F') return ' '.join(switches) -# ---------------readline utilities--------------------- -try: - import readline - readline_available = True -except: - readline_available = False - -class Completer(): - def __init__(self,options): - self.options = sorted(options) - return - - def complete(self,text,state): - buffer = readline.get_line_buffer() - - if text.startswith(('-I','--init_img')): - return self._path_completions(text,state,('.png')) - - if buffer.strip().endswith('cd') or text.startswith(('.','/')): - return self._path_completions(text,state,()) - - response = None - if state == 0: - # This is the first time for this text, so build a match list. - if text: - self.matches = [s - for s in self.options - if s and s.startswith(text)] - else: - self.matches = self.options[:] - - # Return the state'th item from the match list, - # if we have that many. - try: - response = self.matches[state] - except IndexError: - response = None - return response - - def _path_completions(self,text,state,extensions): - # get the path so far - if text.startswith('-I'): - path = text.replace('-I','',1).lstrip() - elif text.startswith('--init_img='): - path = text.replace('--init_img=','',1).lstrip() - else: - path = text - - matches = list() - - path = os.path.expanduser(path) - if len(path)==0: - matches.append(text+'./') - else: - dir = os.path.dirname(path) - dir_list = os.listdir(dir) - for n in dir_list: - if n.startswith('.') and len(n)>1: - continue - full_path = os.path.join(dir,n) - if full_path.startswith(path): - if os.path.isdir(full_path): - matches.append(os.path.join(os.path.dirname(text),n)+'/') - elif n.endswith(extensions): - matches.append(os.path.join(os.path.dirname(text),n)) - - try: - response = matches[state] - except IndexError: - response = None - return response - -if readline_available: - readline.set_completer(Completer(['cd','pwd', - '--steps','-s','--seed','-S','--iterations','-n','--batch_size','-b', - '--width','-W','--height','-H','--cfg_scale','-C','--grid','-g', - '--individual','-i','--init_img','-I','--strength','-f','-v','--variants']).complete) - readline.set_completer_delims(" ") - readline.parse_and_bind('tab: complete') - - histfile = os.path.join(os.path.expanduser('~'),".dream_history") - try: - readline.read_history_file(histfile) - readline.set_history_length(1000) - except FileNotFoundError: - pass - atexit.register(readline.write_history_file,histfile) - diff --git a/ldm/dream/readline.py b/ldm/dream/readline.py new file mode 100644 index 0000000000..f46ac6e23a --- /dev/null +++ b/ldm/dream/readline.py @@ -0,0 +1,94 @@ +''' +Readline helper functions for dream.py (linux and mac only). +''' +import os +import re +import atexit +# ---------------readline utilities--------------------- +try: + import readline + readline_available = True +except: + readline_available = False + +class Completer(): + def __init__(self,options): + self.options = sorted(options) + return + + def complete(self,text,state): + buffer = readline.get_line_buffer() + + if text.startswith(('-I','--init_img')): + return self._path_completions(text,state,('.png')) + + if buffer.strip().endswith('cd') or text.startswith(('.','/')): + return self._path_completions(text,state,()) + + response = None + if state == 0: + # This is the first time for this text, so build a match list. + if text: + self.matches = [s + for s in self.options + if s and s.startswith(text)] + else: + self.matches = self.options[:] + + # Return the state'th item from the match list, + # if we have that many. + try: + response = self.matches[state] + except IndexError: + response = None + return response + + def _path_completions(self,text,state,extensions): + # get the path so far + if text.startswith('-I'): + path = text.replace('-I','',1).lstrip() + elif text.startswith('--init_img='): + path = text.replace('--init_img=','',1).lstrip() + else: + path = text + + matches = list() + + path = os.path.expanduser(path) + if len(path)==0: + matches.append(text+'./') + else: + dir = os.path.dirname(path) + dir_list = os.listdir(dir) + for n in dir_list: + if n.startswith('.') and len(n)>1: + continue + full_path = os.path.join(dir,n) + if full_path.startswith(path): + if os.path.isdir(full_path): + matches.append(os.path.join(os.path.dirname(text),n)+'/') + elif n.endswith(extensions): + matches.append(os.path.join(os.path.dirname(text),n)) + + try: + response = matches[state] + except IndexError: + response = None + return response + +if readline_available: + readline.set_completer(Completer(['cd','pwd', + '--steps','-s','--seed','-S','--iterations','-n','--batch_size','-b', + '--width','-W','--height','-H','--cfg_scale','-C','--grid','-g', + '--individual','-i','--init_img','-I','--strength','-f','-v','--variants']).complete) + readline.set_completer_delims(" ") + readline.parse_and_bind('tab: complete') + + histfile = os.path.join(os.path.expanduser('~'),".dream_history") + try: + readline.read_history_file(histfile) + readline.set_history_length(1000) + except FileNotFoundError: + pass + atexit.register(readline.write_history_file,histfile) + diff --git a/ldm/simplet2i.py b/ldm/simplet2i.py index 1cc199c119..0de3a33237 100644 --- a/ldm/simplet2i.py +++ b/ldm/simplet2i.py @@ -27,7 +27,7 @@ from ldm.util import instantiate_from_config from ldm.models.diffusion.ddim import DDIMSampler from ldm.models.diffusion.plms import PLMSSampler from ldm.models.diffusion.ksampler import KSampler -from ldm.dream_util import PngWriter +from ldm.dream.pngwriter import PngWriter """Simplified text to image API for stable diffusion/latent diffusion diff --git a/scripts/dream.py b/scripts/dream.py index 4def627519..542f28c9bf 100755 --- a/scripts/dream.py +++ b/scripts/dream.py @@ -6,9 +6,9 @@ import shlex import os import sys import copy +import ldm.dream.readline -from ldm.dream_util import Completer,PngWriter,PromptFormatter - +from ldm.dream.pngwriter import PngWriter,PromptFormatter debugging = False def main():