Skip to content

Commit 3a2be62

Browse files
authored
Merge branch 'development' into main
2 parents 91e826e + 5116c81 commit 3a2be62

File tree

10 files changed

+86
-30
lines changed

10 files changed

+86
-30
lines changed

README-Mac-MPS.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,3 +320,20 @@ something that depends on it-- Rosetta can translate some Intel instructions but
320320
not the specialized ones here. To avoid this, make sure to use the environment
321321
variable `CONDA_SUBDIR=osx-arm64`, which restricts the Conda environment to only
322322
use ARM packages, and use `nomkl` as described above.
323+
324+
### input types 'tensor<2x1280xf32>' and 'tensor<*xf16>' are not broadcast compatible
325+
326+
May appear when just starting to generate, e.g.:
327+
328+
```
329+
dream> clouds
330+
Generating: 0%| | 0/1 [00:00<?, ?it/s]/Users/[...]/dev/stable-diffusion/ldm/modules/embedding_manager.py:152: UserWarning: The operator 'aten::nonzero' is not currently supported on the MPS backend and will fall back to run on the CPU. This may have performance implications. (Triggered internally at /Users/runner/work/_temp/anaconda/conda-bld/pytorch_1662016319283/work/aten/src/ATen/mps/MPSFallback.mm:11.)
331+
placeholder_idx = torch.where(
332+
loc("mps_add"("(mpsFileLoc): /AppleInternal/Library/BuildRoots/20d6c351-ee94-11ec-bcaf-7247572f23b4/Library/Caches/com.apple.xbs/Sources/MetalPerformanceShadersGraph/mpsgraph/MetalPerformanceShadersGraph/Core/Files/MPSGraphUtilities.mm":219:0)): error: input types 'tensor<2x1280xf32>' and 'tensor<*xf16>' are not broadcast compatible
333+
LLVM ERROR: Failed to infer result type(s).
334+
Abort trap: 6
335+
/Users/[...]/opt/anaconda3/envs/ldm/lib/python3.9/multiprocessing/resource_tracker.py:216: UserWarning: resource_tracker: There appear to be 1 leaked semaphore objects to clean up at shutdown
336+
warnings.warn('resource_tracker: There appear to be %d '
337+
```
338+
339+
Macs do not support autocast/mixed-precision. Supply `--full_precision` to use float32 everywhere.

README.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,13 @@ You may also pass a -v<count> option to generate count variants on the original
138138
passing the first generated image back into img2img the requested number of times. It generates interesting
139139
variants.
140140

141+
## Seamless Tiling
142+
143+
The seamless tiling mode causes generated images to seamlessly tile with itself. To use it, add the --seamless option when starting the script which will result in all generated images to tile, or for each dream> prompt as shown here:
144+
```
145+
dream> "pond garden with lotus by claude monet" --seamless -s100 -n4
146+
```
147+
141148
## GFPGAN and Real-ESRGAN Support
142149

143150
The script also provides the ability to do face restoration and
@@ -400,7 +407,11 @@ repository and associated paper for details and limitations.
400407

401408
# Latest Changes
402409

403-
- v1.13 (3 September 2022)
410+
- v1.14 (In progress)
411+
412+
- Add "seamless mode" for circular tiling of image. Generates beautiful effects. ([prixt](https://github.com/prixt))
413+
414+
- v1.13 (3 September 2022
404415

405416
- Support image variations (see [VARIATIONS](VARIATIONS.md) ([Kevin Gibbons](https://github.com/bakkot) and many contributors and reviewers)
406417
- Supports a Google Colab notebook for a standalone server running on Google hardware [Arturo Mendivil](https://github.com/artmen1516)

VARIATIONS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,6 @@ the chosen two images. Here's the one I like best:
108108

109109
<img src="static/variation_walkthru/000004.3747154981.png">
110110

111-
As you can see, this is a very powerful too, which when combined with
111+
As you can see, this is a very powerful tool, which when combined with
112112
subprompt weighting, gives you great control over the content and
113113
quality of your generated images.

environment-mac.yaml

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,29 @@
11
name: ldm
22
channels:
3-
- pytorch-nightly
3+
- pytorch
44
- conda-forge
55
dependencies:
6-
- python==3.9.13
6+
- python==3.10.5
77
- pip==22.2.2
88

9-
# pytorch-nightly, left unpinned
9+
# pytorch left unpinned
1010
- pytorch
11-
- torchmetrics
1211
- torchvision
1312

1413
# I suggest to keep the other deps sorted for convenience.
15-
# If you wish to upgrade to 3.10, try to run this:
14+
# To determine what the latest versions should be, run:
1615
#
1716
# ```shell
18-
# CONDA_CMD=conda
19-
# sed -E 's/python==3.9.13/python==3.10.5/;s/ldm/ldm-3.10/;21,99s/- ([^=]+)==.+/- \1/' environment-mac.yaml > /tmp/environment-mac-updated.yml
20-
# CONDA_SUBDIR=osx-arm64 $CONDA_CMD env create -f /tmp/environment-mac-updated.yml && $CONDA_CMD list -n ldm-3.10 | awk ' {print " - " $1 "==" $2;} '
17+
# sed -E 's/ldm/ldm-updated/;20,99s/- ([^=]+)==.+/- \1/' environment-mac.yaml > environment-mac-updated.yml
18+
# CONDA_SUBDIR=osx-arm64 conda env create -f environment-mac-updated.yml && conda list -n ldm-updated | awk ' {print " - " $1 "==" $2;} '
2119
# ```
22-
#
23-
# Unfortunately, as of 2022-08-31, this fails at the pip stage.
2420
- albumentations==1.2.1
2521
- coloredlogs==15.0.1
2622
- einops==0.4.1
2723
- grpcio==1.46.4
28-
- humanfriendly
29-
- imageio-ffmpeg==0.4.7
24+
- humanfriendly==10.0
3025
- imageio==2.21.2
26+
- imageio-ffmpeg==0.4.7
3127
- imgaug==0.4.0
3228
- kornia==0.6.7
3329
- mpmath==1.2.1
@@ -43,13 +39,11 @@ dependencies:
4339
- streamlit==1.12.2
4440
- sympy==1.10.1
4541
- tensorboard==2.9.0
46-
- transformers==4.21.2
42+
- torchmetrics==0.9.3
4743
- pip:
48-
- invisible-watermark
49-
- test-tube
50-
- tokenizers
51-
- torch-fidelity
52-
- -e git+https://github.com/huggingface/[email protected]#egg=diffusers
44+
- test-tube==0.7.5
45+
- transformers==4.21.2
46+
- torch-fidelity==0.3.0
5347
- -e git+https://github.com/CompVis/taming-transformers.git@master#egg=taming-transformers
5448
- -e git+https://github.com/openai/CLIP.git@main#egg=clip
5549
- -e git+https://github.com/Birch-san/k-diffusion.git@mps#egg=k_diffusion

ldm/dream/pngwriter.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ def normalize_prompt(self):
5959
switches.append(f'-H{opt.height or t2i.height}')
6060
switches.append(f'-C{opt.cfg_scale or t2i.cfg_scale}')
6161
switches.append(f'-A{opt.sampler_name or t2i.sampler_name}')
62+
if opt.seamless or t2i.seamless:
63+
switches.append(f'--seamless')
6264
if opt.init_img:
6365
switches.append(f'-I{opt.init_img}')
6466
if opt.fit:

ldm/dream/server.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,8 @@ def do_POST(self):
7676
steps = int(post_data['steps'])
7777
width = int(post_data['width'])
7878
height = int(post_data['height'])
79-
fit = 'fit' in post_data
79+
fit = 'fit' in post_data
80+
seamless = 'seamless' in post_data
8081
cfgscale = float(post_data['cfgscale'])
8182
sampler_name = post_data['sampler']
8283
gfpgan_strength = float(post_data['gfpgan_strength']) if gfpgan_model_exists else 0
@@ -92,7 +93,7 @@ def do_POST(self):
9293
# across images generated by each call to prompt2img(), so we define it in
9394
# the outer scope of image_done()
9495
config = post_data.copy() # Shallow copy
95-
config['initimg'] = ''
96+
config['initimg'] = config.pop('initimg_name','')
9697

9798
images_generated = 0 # helps keep track of when upscaling is started
9899
images_upscaled = 0 # helps keep track of when upscaling is completed
@@ -170,6 +171,7 @@ def image_progress(sample, step):
170171
gfpgan_strength = gfpgan_strength,
171172
upscale = upscale,
172173
sampler_name = sampler_name,
174+
seamless = seamless,
173175
step_callback=image_progress,
174176
image_callback=image_done)
175177
else:
@@ -191,6 +193,7 @@ def image_progress(sample, step):
191193
width = width,
192194
height = height,
193195
fit = fit,
196+
seamless = seamless,
194197
gfpgan_strength=gfpgan_strength,
195198
upscale = upscale,
196199
step_callback=image_progress,

ldm/simplet2i.py

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from tqdm import tqdm, trange
1515
from itertools import islice
1616
from einops import rearrange, repeat
17+
from torch import nn
1718
from torchvision.utils import make_grid
1819
from pytorch_lightning import seed_everything
1920
from torch import autocast
@@ -109,6 +110,7 @@ class T2I:
109110
downsampling_factor
110111
precision
111112
strength
113+
seamless
112114
embedding_path
113115
114116
The vast majority of these arguments default to reasonable values.
@@ -132,6 +134,7 @@ def __init__(
132134
precision='autocast',
133135
full_precision=False,
134136
strength=0.75, # default in scripts/img2img.py
137+
seamless=False,
135138
embedding_path=None,
136139
device_type = 'cuda',
137140
# just to keep track of this parameter when regenerating prompt
@@ -153,6 +156,7 @@ def __init__(
153156
self.precision = precision
154157
self.full_precision = True if choose_torch_device() == 'mps' else full_precision
155158
self.strength = strength
159+
self.seamless = seamless
156160
self.embedding_path = embedding_path
157161
self.device_type = device_type
158162
self.model = None # empty for now
@@ -217,6 +221,7 @@ def prompt2image(
217221
step_callback = None,
218222
width = None,
219223
height = None,
224+
seamless = False,
220225
# these are specific to img2img
221226
init_img = None,
222227
fit = False,
@@ -240,6 +245,7 @@ def prompt2image(
240245
width // width of image, in multiples of 64 (512)
241246
height // height of image, in multiples of 64 (512)
242247
cfg_scale // how strongly the prompt influences the image (7.5) (must be >1)
248+
seamless // whether the generated image should tile
243249
init_img // path to an initial image - its dimensions override width and height
244250
strength // strength for noising/unnoising init_img. 0.0 preserves image exactly, 1.0 replaces it completely
245251
gfpgan_strength // strength for GFPGAN. 0.0 preserves image exactly, 1.0 replaces it completely
@@ -268,6 +274,7 @@ def process_image(image,seed):
268274
steps = steps or self.steps
269275
width = width or self.width
270276
height = height or self.height
277+
seamless = seamless or self.seamless
271278
cfg_scale = cfg_scale or self.cfg_scale
272279
ddim_eta = ddim_eta or self.ddim_eta
273280
iterations = iterations or self.iterations
@@ -278,6 +285,10 @@ def process_image(image,seed):
278285
model = (
279286
self.load_model()
280287
) # will instantiate the model or return it from cache
288+
for m in model.modules():
289+
if isinstance(m, (nn.Conv2d, nn.ConvTranspose2d)):
290+
m.padding_mode = 'circular' if seamless else m._orig_padding_mode
291+
281292
assert cfg_scale > 1.0, 'CFG_Scale (-C) must be >1.0'
282293
assert (
283294
0.0 <= strength <= 1.0
@@ -324,7 +335,6 @@ def process_image(image,seed):
324335
self.model.encode_first_stage(init_image)
325336
) # move to latent space
326337

327-
print(f' DEBUG: seed at make_image time ={seed}')
328338
make_image = self._img2img(
329339
prompt,
330340
steps=steps,
@@ -413,10 +423,7 @@ def process_image(image,seed):
413423
f'>> Error running RealESRGAN - Your image was not upscaled.\n{e}'
414424
)
415425
if image_callback is not None:
416-
if save_original:
417-
image_callback(image, seed)
418-
else:
419-
image_callback(image, seed, upscaled=True)
426+
image_callback(image, seed, upscaled=True)
420427
else: # no callback passed, so we simply replace old image with rescaled one
421428
result[0] = image
422429

@@ -604,6 +611,10 @@ def load_model(self):
604611

605612
self._set_sampler()
606613

614+
for m in self.model.modules():
615+
if isinstance(m, (nn.Conv2d, nn.ConvTranspose2d)):
616+
m._orig_padding_mode = m.padding_mode
617+
607618
return self.model
608619

609620
# returns a tensor filled with random numbers from a normal distribution

scripts/dream.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ def main():
6262
grid = opt.grid,
6363
# this is solely for recreating the prompt
6464
latent_diffusion_weights=opt.laion400m,
65+
seamless=opt.seamless,
6566
embedding_path=opt.embedding_path,
6667
device_type=opt.device
6768
)
@@ -87,6 +88,9 @@ def main():
8788
print(f'{e}. Aborting.')
8889
sys.exit(-1)
8990

91+
if opt.seamless:
92+
print(">> changed to seamless tiling mode")
93+
9094
# preload the model
9195
tic = time.time()
9296
t2i.load_model()
@@ -418,6 +422,11 @@ def create_argv_parser():
418422
default='outputs/img-samples',
419423
help='Directory to save generated images and a log of prompts and seeds. Default: outputs/img-samples',
420424
)
425+
parser.add_argument(
426+
'--seamless',
427+
action='store_true',
428+
help='Change the model to seamless tiling (circular) mode',
429+
)
421430
parser.add_argument(
422431
'--embedding_path',
423432
type=str,
@@ -540,6 +549,11 @@ def create_cmd_parser():
540549
default=None,
541550
help='Directory to save generated images and a log of prompts and seeds',
542551
)
552+
parser.add_argument(
553+
'--seamless',
554+
action='store_true',
555+
help='Change the model to seamless tiling (circular) mode',
556+
)
543557
parser.add_argument(
544558
'-i',
545559
'--individual',

static/dream_web/index.html

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ <h2 id="header">Stable Diffusion Dream Server</h2>
3737
<option value="k_euler_a">KEULER_A</option>
3838
<option value="k_heun">KHEUN</option>
3939
</select>
40+
<input type="checkbox" name="seamless" id="seamless">
41+
<label for="seamless">Seamless circular tiling</label>
4042
<br>
4143
<label title="Set to multiple of 64" for="width">Width:</label>
4244
<select id="width" name="width" value="512">
@@ -64,7 +66,7 @@ <h2 id="header">Stable Diffusion Dream Server</h2>
6466
<input value="-1" type="number" id="seed" name="seed">
6567
<button type="button" id="reset-seed">&olarr;</button>
6668
<input type="checkbox" name="progress_images" id="progress_images">
67-
<label for="progress_images">Display in-progress images (slows down generation):</label>
69+
<label for="progress_images">Display in-progress images (slower)</label>
6870
<button type="button" id="reset-all">Reset to Defaults</button>
6971
</div>
7072
<div id="img2img">
@@ -74,7 +76,7 @@ <h2 id="header">Stable Diffusion Dream Server</h2>
7476
<label for="strength">Img2Img Strength:</label>
7577
<input value="0.75" type="number" id="strength" name="strength" step="0.01" min="0" max="1">
7678
<input type="checkbox" id="fit" name="fit" checked>
77-
<label title="Rescale image to fit within requested width and height" for="fit">Fit to width/height:</label>
79+
<label title="Rescale image to fit within requested width and height" for="fit">Fit to width/height</label>
7880
</div>
7981
<div id="gfpgan">
8082
<label title="Strength of the gfpgan (face fixing) algorithm." for="gfpgan_strength">GPFGAN Strength (0 to disable):</label>

static/dream_web/index.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ function appendOutput(src, seed, config) {
1919
outputNode.addEventListener('click', () => {
2020
let form = document.querySelector("#generate-form");
2121
for (const [k, v] of new FormData(form)) {
22-
form.querySelector(`*[name=${k}]`).value = config[k];
22+
if (k == 'initimg') { continue; }
23+
form.querySelector(`*[name=${k}]`).value = config[k];
2324
}
2425
document.querySelector("#seed").value = seed;
2526

@@ -59,6 +60,7 @@ async function generateSubmit(form) {
5960

6061
// Convert file data to base64
6162
let formData = Object.fromEntries(new FormData(form));
63+
formData.initimg_name = formData.initimg.name
6264
formData.initimg = formData.initimg.name !== '' ? await toBase64(formData.initimg) : null;
6365

6466
let strength = formData.strength;

0 commit comments

Comments
 (0)