Spaces:
Running
Running
Sean Powell commited on
Commit ·
a9ae6bb
1
Parent(s): fc4590f
Extract and refactor diamond crop img2img procedure.
Browse files- experiments/diamond-crop-img2img.py +35 -0
- generations/diamond_crop_img2img/half_drop_demo/.gitkeep +0 -0
- generations/diamond_crop_img2img/half_drops/.gitkeep +0 -0
- generations/diamond_crop_img2img/inner_rotated_tiles/.gitkeep +0 -0
- generations/diamond_crop_img2img/originals/.gitkeep +0 -0
- generations/diamond_crop_img2img/tiles/.gitkeep +0 -0
- utils/pipes.py +24 -0
- utils/tiling.py +61 -0
experiments/diamond-crop-img2img.py
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from utils import filenames, images, wallpaper, pipes
|
| 2 |
+
|
| 3 |
+
prompt = "seamless pattern of parrots. black and white, drawing, white background, seamless, ornament."
|
| 4 |
+
generation_dir = "./generations/diamond_crop_img2img"
|
| 5 |
+
|
| 6 |
+
sdxl_pipe = pipes.create_stable_diffusion_xl_pipeline()
|
| 7 |
+
|
| 8 |
+
original_image = sdxl_pipe(prompt=prompt, num_inference_steps=20).images[0]
|
| 9 |
+
original_image_filename = filenames.generate_filename(f"{generation_dir}/originals", prompt)
|
| 10 |
+
original_image.save(original_image_filename)
|
| 11 |
+
print("generated image generated", original_image_filename)
|
| 12 |
+
|
| 13 |
+
inner_rotated_tile = images.extract_inner_rotated_tile_from_image(original_image)
|
| 14 |
+
inner_rotated_tile_filename = filenames.generate_filename(f"{generation_dir}/inner_rotated_tiles", prompt,
|
| 15 |
+
"-inner-rotated")
|
| 16 |
+
inner_rotated_tile.save(inner_rotated_tile_filename)
|
| 17 |
+
print("generated inner rotated tile", inner_rotated_tile_filename)
|
| 18 |
+
|
| 19 |
+
sdxl_img2img_pipe = pipes.create_stable_diffusion_xl_img2img_pipe()
|
| 20 |
+
|
| 21 |
+
tileable_image = sdxl_img2img_pipe(prompt, image=inner_rotated_tile.convert("RGB"), num_inference_steps=20).images[0]
|
| 22 |
+
tileable_image_filename = filenames.generate_filename(f"{generation_dir}/tiles", prompt, "-tile")
|
| 23 |
+
tileable_image.save(tileable_image_filename)
|
| 24 |
+
print("generated tileable image", tileable_image_filename)
|
| 25 |
+
|
| 26 |
+
half_drop = wallpaper.convert_tile_to_half_drop(tileable_image)
|
| 27 |
+
half_drop_filename = filenames.generate_filename(f"{generation_dir}//half_drops", prompt, "_half-drop-tile")
|
| 28 |
+
half_drop.save(half_drop_filename)
|
| 29 |
+
print("generated half drop tile", tileable_image_filename)
|
| 30 |
+
|
| 31 |
+
half_drop_tiled = wallpaper.generate_tile_test_arrangement(half_drop)
|
| 32 |
+
half_drop_tiled_filename = filenames.generate_filename(f"{generation_dir}/half_drop_demo", prompt,
|
| 33 |
+
"_half-drop-demo")
|
| 34 |
+
half_drop_tiled.save(half_drop_tiled_filename)
|
| 35 |
+
print("generated half drop tiled image", tileable_image_filename)
|
generations/diamond_crop_img2img/half_drop_demo/.gitkeep
ADDED
|
File without changes
|
generations/diamond_crop_img2img/half_drops/.gitkeep
ADDED
|
File without changes
|
generations/diamond_crop_img2img/inner_rotated_tiles/.gitkeep
ADDED
|
File without changes
|
generations/diamond_crop_img2img/originals/.gitkeep
ADDED
|
File without changes
|
generations/diamond_crop_img2img/tiles/.gitkeep
ADDED
|
File without changes
|
utils/pipes.py
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import torch
|
| 2 |
+
from diffusers import StableDiffusionXLImg2ImgPipeline, StableDiffusionXLPipeline
|
| 3 |
+
|
| 4 |
+
from utils import tiling
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
def create_stable_diffusion_xl_pipeline():
|
| 8 |
+
pipe = StableDiffusionXLPipeline.from_pretrained(
|
| 9 |
+
"stabilityai/stable-diffusion-xl-base-1.0", torch_dtype=torch.float16, variant="fp16", use_safetensors=True
|
| 10 |
+
)
|
| 11 |
+
pipe = pipe.to("mps")
|
| 12 |
+
pipe.vae.disable_tiling()
|
| 13 |
+
tiling.enable_circular_tiling([pipe.vae, pipe.text_encoder, pipe.unet])
|
| 14 |
+
return pipe
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
def create_stable_diffusion_xl_img2img_pipe():
|
| 18 |
+
pipe = StableDiffusionXLImg2ImgPipeline.from_pretrained(
|
| 19 |
+
"stabilityai/stable-diffusion-xl-refiner-1.0", torch_dtype=torch.float16, variant="fp16", use_safetensors=True
|
| 20 |
+
)
|
| 21 |
+
pipe = pipe.to("mps")
|
| 22 |
+
pipe.vae.disable_tiling()
|
| 23 |
+
tiling.enable_circular_tiling([pipe.vae, pipe.text_encoder_2, pipe.unet])
|
| 24 |
+
return pipe
|
utils/tiling.py
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from typing import Optional
|
| 2 |
+
|
| 3 |
+
import diffusers
|
| 4 |
+
import torch
|
| 5 |
+
from torch import Tensor
|
| 6 |
+
from torch.nn import functional as F
|
| 7 |
+
from torch.nn.modules.utils import _pair
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
def asymmetric_conv2d_conv_forward(self, input: Tensor, weight: Tensor, bias: Optional[Tensor]):
|
| 11 |
+
"""
|
| 12 |
+
Perform a forward pass of a custom 2D convolution with asymmetric circular padding.
|
| 13 |
+
|
| 14 |
+
This method modifies the standard 2D convolution by applying asymmetric padding
|
| 15 |
+
to the input tensor before performing the convolution. The padding is circular,
|
| 16 |
+
meaning the input tensor wraps around itself.
|
| 17 |
+
|
| 18 |
+
Args:
|
| 19 |
+
self: An instance of the class containing convolution parameters.
|
| 20 |
+
input (Tensor): The input tensor to be convolved.
|
| 21 |
+
weight (Tensor): The weight tensor of the convolution kernel.
|
| 22 |
+
bias (Optional[Tensor]): An optional bias tensor for the convolution.
|
| 23 |
+
|
| 24 |
+
Returns:
|
| 25 |
+
Tensor: The output tensor after applying the asymmetric circular padding and 2D convolution.
|
| 26 |
+
"""
|
| 27 |
+
self
|
| 28 |
+
self.paddingX = (self._reversed_padding_repeated_twice[0], self._reversed_padding_repeated_twice[1], 0, 0)
|
| 29 |
+
self.paddingY = (0, 0, self._reversed_padding_repeated_twice[2], self._reversed_padding_repeated_twice[3])
|
| 30 |
+
working = F.pad(input, self.paddingX, mode='circular')
|
| 31 |
+
working = F.pad(working, self.paddingY, mode='circular')
|
| 32 |
+
return F.conv2d(working, weight, bias, self.stride, _pair(0), self.dilation, self.groups)
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
def enable_circular_tiling(targets):
|
| 36 |
+
"""
|
| 37 |
+
Enable circular tiling on convolutional layers within the given targets.
|
| 38 |
+
|
| 39 |
+
This function iterates through the given targets (which are parts of a neural
|
| 40 |
+
network model) and modifies each convolutional layer to use a custom asymmetric
|
| 41 |
+
convolution with circular padding. It is specifically designed for use with
|
| 42 |
+
the StableDiffusionXLPipeline to modify its convolution layers for circular tiling.
|
| 43 |
+
|
| 44 |
+
Args:
|
| 45 |
+
targets (list): A list of neural network components (e.g., layers or entire models)
|
| 46 |
+
from which to find and modify Conv2d layers.
|
| 47 |
+
|
| 48 |
+
Returns:
|
| 49 |
+
None: The function modifies the convolutional layers in-place.
|
| 50 |
+
"""
|
| 51 |
+
conv_layers = []
|
| 52 |
+
for target in targets:
|
| 53 |
+
for module in target.modules():
|
| 54 |
+
if isinstance(module, torch.nn.Conv2d):
|
| 55 |
+
conv_layers.append(module)
|
| 56 |
+
|
| 57 |
+
for cl in conv_layers:
|
| 58 |
+
if isinstance(cl, diffusers.models.lora.LoRACompatibleConv) and cl.lora_layer is None:
|
| 59 |
+
cl.lora_layer = lambda *x: 0
|
| 60 |
+
|
| 61 |
+
cl._conv_forward = asymmetric_conv2d_conv_forward.__get__(cl, torch.nn.Conv2d)
|