feature: image edit gifs and demo-reels

pull/178/head
Bryce 1 year ago committed by Bryce Drennan
parent 2a3e19f5a1
commit 7c05c3aae2

@ -61,6 +61,17 @@ with prompt-based masking.
<img src="assets/bowl_of_fruit_strawberries.jpg" height="256"><img src="assets/freckled_woman_cyborg.jpg" height="256"><br>
<img src="assets/girl_with_a_pearl_earring_clown_makeup.jpg" height="256"><img src="assets/mona-lisa-headshot-photo.jpg" height="256"><br>
Want just quickly have some fun? Try `--suprise-me` to apply some pre-defined edits.
```bash
>> aimg edit --gif --suprise-me pearl_girl.jpg
>> aimg edit --gif --suprise-me mona-lisa.jpg
>> aimg edit --gif --suprise-me luke.jpg
>> aimg edit --gif --suprise-me spock.jpg
```
<img src="assets/girl_with_a_pearl_earring_suprise.gif" height="256"><img src="assets/mona-lisa-suprise.gif" height="256"><br>
<img src="assets/luke-suprise.gif" height="256"><img src="assets/spock-suprise.gif" height="256"><br>
<img src="assets/gg-bridge-suprise.gif" height="256"><img src="assets/shire-suprise.gif" height="256"><br>
### Prompt Based Masking [by clipseg](https://github.com/timojl/clipseg)
Specify advanced text based masks using boolean logic and strength modifiers.
@ -274,6 +285,8 @@ docker run -it --gpus all -v $HOME/.cache/huggingface:/root/.cache/huggingface -
**8.0.0**
- feature: 🎉 edit images with instructions alone!
- feature: when editing an image add `--gif` to create a comparision gif
- feature: `aimg edit --suprise-me --gif my-image.jpg` for some fun pre-programmed edits
- feature: prune-ckpt command also removes the non-ema weights
**7.6.0**

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

@ -13,7 +13,11 @@ from imaginairy.enhancers.clip_masking import get_img_mask
from imaginairy.enhancers.describe_image_blip import generate_caption
from imaginairy.enhancers.face_restoration_codeformer import enhance_faces
from imaginairy.enhancers.upscale_realesrgan import upscale_image
from imaginairy.img_utils import pillow_fit_image_within, pillow_img_to_torch_image
from imaginairy.img_utils import (
make_gif_image,
pillow_fit_image_within,
pillow_img_to_torch_image,
)
from imaginairy.log_utils import (
ImageLoggingContext,
log_conditioning,
@ -55,6 +59,8 @@ def imagine_image_files(
record_step_images=False,
output_file_extension="jpg",
print_caption=False,
make_comparison_gif=False,
return_filename_type="generated",
):
generated_imgs_path = os.path.join(outdir, "generated")
os.makedirs(generated_imgs_path, exist_ok=True)
@ -74,6 +80,7 @@ def imagine_image_files(
draw.text((10, 10), str(description))
img.save(destination)
result_filenames = []
for result in imagine(
prompts,
precision=precision,
@ -97,9 +104,25 @@ def imagine_image_files(
)
result.save(filepath, image_type=image_type)
logger.info(f"🖼 [{image_type}] saved to: {filepath}")
if image_type == return_filename_type:
result_filenames.append(filepath)
if make_comparison_gif and prompt.init_image:
subpath = os.path.join(outdir, "gif")
os.makedirs(subpath, exist_ok=True)
filepath = os.path.join(subpath, f"{basefilename}.gif")
resized_init_image = pillow_fit_image_within(
prompt.init_image, prompt.width, prompt.height
)
make_gif_image(
filepath,
imgs=[result.images["generated"], resized_init_image],
duration=1750,
)
base_count += 1
del result
return result_filenames
def imagine(
prompts,

@ -11,6 +11,7 @@ from imaginairy.enhancers.prompt_expansion import expand_prompts
from imaginairy.log_utils import configure_logging
from imaginairy.samplers import SAMPLER_TYPE_OPTIONS
from imaginairy.schema import ImaginePrompt
from imaginairy.suprise_me import create_suprise_me_images
from imaginairy.train import train_diffusion_model
from imaginairy.training_tools.image_prep import (
create_class_images,
@ -220,6 +221,9 @@ logger = logging.getLogger(__name__)
is_flag=True,
help="Print the version and exit.",
)
@click.option(
"--gif", "make_gif", default=False, is_flag=True, help="Generate a gif of the edit."
)
@click.pass_context
def imagine_cmd(
ctx,
@ -255,6 +259,7 @@ def imagine_cmd(
model_config_path,
prompt_library_path,
version, # noqa
make_gif,
):
"""Have the AI generate images. alias:imagine."""
return _imagine_cmd(
@ -291,6 +296,7 @@ def imagine_cmd(
model_config_path,
prompt_library_path,
version, # noqa
make_gif
)
@ -487,8 +493,22 @@ def imagine_cmd(
is_flag=True,
help="Print the version and exit.",
)
@click.option(
"--gif",
"make_gif",
default=False,
is_flag=True,
help="Generate a gif comparing the original image to the modified one.",
)
@click.option(
"--suprise-me",
"suprise_me",
default=False,
is_flag=True,
help="make some fun edits to the provided image",
)
@click.pass_context
def edit_image(
def edit_image( # noqa
ctx,
init_image,
prompt_texts,
@ -521,8 +541,21 @@ def edit_image(
model_config_path,
prompt_library_path,
version, # noqa
make_gif,
suprise_me,
):
init_image_strength = 1
if suprise_me and prompt_texts:
raise ValueError("Cannot use suprise_me and prompt_texts together")
if suprise_me:
if quiet:
log_level = "ERROR"
configure_logging(log_level)
create_suprise_me_images(init_image, outdir=outdir, make_gif=make_gif)
return
return _imagine_cmd(
ctx,
prompt_texts,
@ -557,6 +590,7 @@ def edit_image(
model_config_path,
prompt_library_path,
version, # noqa
make_gif,
)
@ -593,7 +627,8 @@ def _imagine_cmd(
model_weights_path,
model_config_path,
prompt_library_path,
version, # noqa
version=False, # noqa
make_gif=False,
):
"""Have the AI generate images. alias:imagine."""
if ctx.invoked_subcommand is not None:
@ -670,6 +705,7 @@ def _imagine_cmd(
output_file_extension="jpg",
print_caption=caption,
precision=precision,
make_comparison_gif=make_gif,
)

@ -70,3 +70,15 @@ def pillow_img_to_model_latent(model, img, batch_size=1, half=True):
model.encode_first_stage(init_image.half())
)
return model.get_first_stage_encoding(model.encode_first_stage(init_image))
def make_gif_image(filepath, imgs, duration=1000, loop=0):
imgs[0].save(
filepath,
save_all=True,
append_images=imgs[1:],
duration=duration,
loop=loop,
optimize=False,
)

@ -32,6 +32,7 @@ from imaginairy.modules.diffusion.util import (
)
from imaginairy.modules.distributions import DiagonalGaussianDistribution
from imaginairy.modules.ema import LitEma
from imaginairy.paths import PKG_ROOT
from imaginairy.samplers.kdiff import DPMPP2MSampler
from imaginairy.utils import instantiate_from_config
@ -47,7 +48,7 @@ def log_txt_as_img(wh, xc, size=10):
for bi in range(b):
txt = Image.new("RGB", wh, color="white")
draw = ImageDraw.Draw(txt)
font = ImageFont.truetype("data/DejaVuSans.ttf", size=size)
font = ImageFont.truetype(f"{PKG_ROOT}/data/DejaVuSans.ttf", size=size)
nc = int(40 * (wh[0] / 256))
lines = "\n".join(
xc[bi][start : start + nc] for start in range(0, len(xc[bi]), nc)

@ -0,0 +1,128 @@
"""
aimg.
"""
import os.path
from PIL import ImageDraw, ImageFont
from imaginairy import ImaginePrompt, LazyLoadingImage, imagine_image_files
from imaginairy.enhancers.facecrop import detect_faces
from imaginairy.img_utils import make_gif_image, pillow_fit_image_within
from imaginairy.paths import PKG_ROOT
generic_prompts = [
("make it anime style", 18, ""),
("make it pen and ink style", 20, ""),
("make it a thomas kinkade painting", 20, ""),
("make it pixar style", 20, ""),
("make it look like a marble statue", 15, ""),
("make it look like a golden statue", 15, ""),
("make it look like a snowstorm", 20, ""),
("make it night", 15, ""),
("make it a sunny day", 15, ""),
("put fireworks in the background", 15, ""),
("make it in a forest", 15, ""),
]
person_prompts = [
("make the person close their eyes", 10, ""),
("make the person wear clown makeup", 10, ""),
("make the person a cyborg", 14, ""),
("make the person wear shiny metal clothes", 14, ""),
("make the person wear a tie-dye shirt", 7.5, ""),
("make the person wear a suit", 7.5, ""),
("make the person bald", 7.5, ""),
("change the hair to pink", 7.5, ""),
(
"make it a color professional photo headshot. Canon EOS, sharp focus",
10,
"old, ugly",
),
("make the face smiling", 5, ""),
# ("make the person sad", 20, ""),
# ("make the person angry", 20, ""),
("make the person look like a celebrity", 10, ""),
("make the person younger", 10, ""),
("make the person older", 10, ""),
("make the person a disney cartoon character", 7.5, ""),
]
def suprise_me_prompts(img, person=None):
prompts = []
if isinstance(img, str):
if img.startswith("http"):
img = LazyLoadingImage(url=img)
else:
img = LazyLoadingImage(filepath=img)
if person is None:
person = bool(detect_faces(img))
if person:
for prompt_text, strength, neg_prompt_text in person_prompts:
prompts.append(
ImaginePrompt(
prompt_text,
init_image=img,
prompt_strength=strength,
negative_prompt=neg_prompt_text,
model="edit",
steps=20,
)
)
for prompt_text, strength, neg_prompt_text in generic_prompts:
prompts.append(
ImaginePrompt(
prompt_text,
init_image=img,
prompt_strength=strength,
negative_prompt=neg_prompt_text,
model="edit",
steps=20,
)
)
return prompts
def create_suprise_me_images(img, outdir, person=None, make_gif=True):
if isinstance(img, str):
if img.startswith("http"):
img = LazyLoadingImage(url=img)
else:
img = LazyLoadingImage(filepath=img)
prompts = suprise_me_prompts(img, person=person)
generated_filenames = imagine_image_files(
prompts,
outdir=outdir,
record_step_images=False,
output_file_extension="jpg",
print_caption=False,
make_comparison_gif=make_gif,
)
if make_gif:
imgs_path = os.path.join(outdir, "compilations")
os.makedirs(imgs_path, exist_ok=True)
base_count = len(os.listdir(imgs_path))
new_filename = os.path.join(imgs_path, f"suprise_me_{base_count:03d}.gif")
simg = pillow_fit_image_within(img, prompts[0].width, prompts[0].height)
gif_imgs = [simg]
for prompt, filename in zip(prompts, generated_filenames):
gen_img = LazyLoadingImage(filepath=filename)
draw = ImageDraw.Draw(gen_img)
font_size = 16
font = ImageFont.truetype(f"{PKG_ROOT}/data/DejaVuSans.ttf", font_size)
x = 15
y = 485
draw.text((x, y), prompt.prompt_text, font=font, fill=(255, 255, 255))
gif_imgs.append(gen_img)
make_gif_image(new_filename, gif_imgs)

@ -25,6 +25,7 @@ setup(
package_data={
"imaginairy": [
"configs/*.yaml",
"data/*.*",
"enhancers/phraselists/*.txt",
"vendored/clip/*.txt.gz",
"vendored/clipseg/*.pth",

Loading…
Cancel
Save