Add blends, update styles for dataframe
parent
379b0f51fc
commit
3a1cfd53d5
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 23 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 70 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 51 KiB |
|
|
@ -123,3 +123,14 @@ def clearPrompts():
|
|||
gr.DataFrame.update(value=[[0, "Infinite Zoom. Start over"]]),
|
||||
gr.Textbox.update(""),
|
||||
]
|
||||
|
||||
def value_to_bool(value):
|
||||
if isinstance(value, bool):
|
||||
return value
|
||||
elif isinstance(value, str):
|
||||
if value.lower() in ("true", "false"):
|
||||
return value.lower() == "true"
|
||||
elif isinstance(value, int):
|
||||
if value in (0, 1):
|
||||
return bool(value)
|
||||
return False
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
from PIL import Image
|
||||
from PIL import Image, ImageDraw, ImageEnhance
|
||||
import requests
|
||||
import base64
|
||||
import numpy as np
|
||||
import math
|
||||
from io import BytesIO
|
||||
|
||||
|
||||
|
|
@ -43,13 +45,245 @@ def open_image(image_path):
|
|||
|
||||
return img
|
||||
|
||||
def apply_alpha_mask(current_image, mask_image):
|
||||
|
||||
def apply_alpha_mask(image, mask_image):
|
||||
# Resize the mask to match the current image size
|
||||
mask_image = mask_image.resize(current_image.size)
|
||||
|
||||
mask_image = mask_image.resize(image.size)
|
||||
# Apply the mask as the alpha layer of the current image
|
||||
result_image = current_image.copy()
|
||||
result_image = image.copy()
|
||||
result_image.putalpha(mask_image.convert('L')) # convert to grayscale
|
||||
|
||||
return result_image
|
||||
|
||||
def resize_image_with_aspect_ratio(image, basewidth=512, baseheight=512):
|
||||
# Get the original size of the image
|
||||
orig_width, orig_height = image.size
|
||||
|
||||
# Calculate the height that corresponds to the given width while maintaining aspect ratio
|
||||
wpercent = (basewidth / float(orig_width))
|
||||
hsize = int((float(orig_height) * float(wpercent)))
|
||||
|
||||
# Resize the image with Lanczos resampling filter
|
||||
resized_image = image.resize((basewidth, hsize), resample=Image.LANCZOS)
|
||||
|
||||
# If the height of the resized image is still larger than the given baseheight,
|
||||
# then crop the image from the top and bottom to match the baseheight
|
||||
if hsize > baseheight:
|
||||
# Calculate the number of pixels to crop from the top and bottom
|
||||
crop_height = (hsize - baseheight) // 2
|
||||
# Crop the image
|
||||
resized_image = resized_image.crop((0, crop_height, basewidth, hsize - crop_height))
|
||||
else:
|
||||
if hsize < baseheight:
|
||||
# If the height of the resized image is smaller than the given baseheight,
|
||||
# then paste the resized image in the middle of a blank image with the given baseheight
|
||||
blank_image = Image.new("RGBA", (basewidth, baseheight), (255, 255, 255, 0))
|
||||
blank_image.paste(resized_image, (0, (baseheight - hsize) // 2))
|
||||
resized_image = blank_image
|
||||
|
||||
return resized_image
|
||||
|
||||
def resize_and_crop_image(image, new_width=512, new_height=512):
|
||||
# Get the dimensions of the original image
|
||||
orig_width, orig_height = image.size
|
||||
# Calculate the aspect ratios of the original and new images
|
||||
orig_aspect_ratio = orig_width / float(orig_height)
|
||||
new_aspect_ratio = new_width / float(new_height)
|
||||
# Calculate the new size of the image while maintaining aspect ratio
|
||||
if orig_aspect_ratio > new_aspect_ratio:
|
||||
# The original image is wider than the new image, so we need to crop the sides
|
||||
resized_width = int(new_height * orig_aspect_ratio)
|
||||
resized_height = new_height
|
||||
left_offset = (resized_width - new_width) / 2
|
||||
top_offset = 0
|
||||
else:
|
||||
# The original image is taller than the new image, so we need to crop the top and bottom
|
||||
resized_width = new_width
|
||||
resized_height = int(new_width / orig_aspect_ratio)
|
||||
left_offset = 0
|
||||
top_offset = (resized_height - new_height) / 2
|
||||
# Resize the image with Lanczos resampling filter
|
||||
resized_image = image.resize((resized_width, resized_height), resample=Image.LANCZOS)
|
||||
# Crop the image to fill the entire height and width of the new image
|
||||
cropped_image = resized_image.crop((left_offset, top_offset, left_offset + new_width, top_offset + new_height))
|
||||
return cropped_image
|
||||
|
||||
def grayscale_to_gradient(image, gradient_colors):
|
||||
"""
|
||||
Converts a grayscale PIL Image into a two color image using the specified gradient colors.
|
||||
|
||||
Args:
|
||||
image (PIL.Image.Image): The input grayscale image.
|
||||
gradient_colors (list): A list of two tuples representing the gradient colors.
|
||||
|
||||
Returns:
|
||||
PIL.Image.Image: A two color image with the same dimensions as the input grayscale image.
|
||||
"""
|
||||
# Create a new image with a palette
|
||||
result = Image.new("P", image.size)
|
||||
result.putpalette([c for color in gradient_colors for c in color])
|
||||
|
||||
# Convert the input image to a list of pixel values
|
||||
pixel_values = list(image.getdata())
|
||||
|
||||
# Convert the pixel values to indices in the palette and assign them to the output image
|
||||
result.putdata([gradient_colors[int(p * (len(gradient_colors) - 1))] for p in pixel_values])
|
||||
|
||||
return result
|
||||
|
||||
def rgb2gray(rgb):
|
||||
return np.dot(rgb[...,:3], [0.2989, 0.5870, 0.1140])
|
||||
|
||||
# _, (h, k) = ellipse_bbox(0,0,768,512,math.radians(0.0)) # Ellipse center
|
||||
def ellipse_bbox(h, k, a, b, theta):
|
||||
"""
|
||||
Computes the bounding box of an ellipse centered at (h,k) with semi-major axis 'a',
|
||||
semi-minor axis 'b', and rotation angle 'theta' (in radians).
|
||||
|
||||
Args:
|
||||
h (float): x-coordinate of the ellipse center.
|
||||
k (float): y-coordinate of the ellipse center.
|
||||
a (float): Length of the semi-major axis.
|
||||
b (float): Length of the semi-minor axis.
|
||||
theta (float): Angle of rotation (in radians) of the ellipse.
|
||||
|
||||
Returns:
|
||||
tuple: A tuple of two tuples representing the top left and bottom right corners of
|
||||
the bounding box of the ellipse, respectively.
|
||||
"""
|
||||
ux = a * math.cos(theta)
|
||||
uy = a * math.sin(theta)
|
||||
vx = b * math.cos(theta + math.pi / 2)
|
||||
vy = b * math.sin(theta + math.pi / 2)
|
||||
box_halfwidth = np.ceil(math.sqrt(ux**2 + vx**2))
|
||||
box_halfheight = np.ceil(math.sqrt(uy**2 + vy**2))
|
||||
return ((int(h - box_halfwidth), int(k - box_halfheight))
|
||||
, (int(h + box_halfwidth), int(k + box_halfheight)))
|
||||
|
||||
|
||||
# intel = make_gradient_v2(768,512,h/2,k/2,h*2/3,k*2/3,math.radians(0.0))
|
||||
def make_gradient_v1(width, height, h, k, a, b, theta):
|
||||
"""
|
||||
Generates a gradient image with an elliptical shape.
|
||||
|
||||
Args:
|
||||
width (int): Width of the output image.
|
||||
height (int): Height of the output image.
|
||||
h (float): x-coordinate of the center of the ellipse.
|
||||
k (float): y-coordinate of the center of the ellipse.
|
||||
a (float): Length of the semi-major axis.
|
||||
b (float): Length of the semi-minor axis.
|
||||
theta (float): Angle of rotation (in radians) of the ellipse.
|
||||
|
||||
Returns:
|
||||
PIL.Image.Image: A PIL Image object representing the gradient with an elliptical shape.
|
||||
"""
|
||||
# Precalculate constants
|
||||
st, ct = math.sin(theta), math.cos(theta)
|
||||
aa, bb = a**2, b**2
|
||||
|
||||
# Initialize an empty array to hold the weights
|
||||
weights = np.zeros((height, width), np.float64)
|
||||
|
||||
# Calculate the weight for each pixel
|
||||
for y in range(height):
|
||||
for x in range(width):
|
||||
weights[y, x] = ((((x-h) * ct + (y-k) * st) ** 2) / aa
|
||||
+ (((x-h) * st - (y-k) * ct) ** 2) / bb)
|
||||
|
||||
# Convert the weights to pixel values and create a PIL Image
|
||||
pixel_values = np.uint8(np.clip(1.0 - weights, 0, 1) * 255)
|
||||
return Image.fromarray(pixel_values, mode='L')
|
||||
|
||||
|
||||
# make_gradient_v2(768,512,h/2,k/2,h-192,k-192,math.radians(30.0))
|
||||
def make_gradient_v2(width, height, h, k, a, b, theta):
|
||||
"""
|
||||
Generates a gradient image with an elliptical shape.
|
||||
|
||||
Args:
|
||||
width (int): Width of the output image.
|
||||
height (int): Height of the output image.
|
||||
h (float): x-coordinate of the center of the ellipse.
|
||||
k (float): y-coordinate of the center of the ellipse.
|
||||
a (float): Length of the semi-major axis.
|
||||
b (float): Length of the semi-minor axis.
|
||||
theta (float): Angle of rotation (in radians) of the ellipse.
|
||||
|
||||
Returns:
|
||||
PIL.Image.Image: A PIL Image object representing the gradient with an elliptical shape.
|
||||
"""
|
||||
# Precalculate constants
|
||||
st, ct = math.sin(theta), math.cos(theta)
|
||||
aa, bb = a**2, b**2
|
||||
# Generate (x,y) coordinate arrays
|
||||
y,x = np.mgrid[-k:height-k,-h:width-h]
|
||||
# Calculate the weight for each pixel
|
||||
weights = (((x * ct + y * st) ** 2) / aa) + (((x * st - y * ct) ** 2) / bb)
|
||||
# Convert the weights to pixel values and create a PIL Image
|
||||
pixel_values = np.uint8(np.clip(1.0 - weights, 0, 1) * 255)
|
||||
return Image.fromarray(pixel_values, mode='L')
|
||||
|
||||
def make_gradient_v3(width, height, h, k, a, b, theta, gradient_colors=[(255, 255, 255, 1), (0, 0, 0, 1)]):
|
||||
"""
|
||||
Generates a gradient image with an elliptical shape and the specified gradient colors.
|
||||
|
||||
Args:
|
||||
width (int): Width of the output image.
|
||||
height (int): Height of the output image.
|
||||
h (float): x-coordinate of the center of the ellipse.
|
||||
k (float): y-coordinate of the center of the ellipse.
|
||||
a (float): Length of the semi-major axis.
|
||||
b (float): Length of the semi-minor axis.
|
||||
theta (float): Angle of rotation (in radians) of the ellipse.
|
||||
gradient_colors (list): A list of two tuples representing the gradient colors.
|
||||
|
||||
Returns:
|
||||
PIL.Image.Image: A two color gradient image with an elliptical shape.
|
||||
"""
|
||||
# Precalculate constants
|
||||
st, ct = math.sin(theta), math.cos(theta)
|
||||
aa, bb = a**2, b**2
|
||||
# Generate (x,y) coordinate arrays
|
||||
y, x = np.mgrid[-k:height-k, -h:width-h]
|
||||
# Calculate the weight for each pixel
|
||||
weights = (((x * ct + y * st) ** 2) / aa) + (((x * st - y * ct) ** 2) / bb)
|
||||
# Normalize the weights to the range [0, 1]
|
||||
weights = 1.0 - np.clip(weights / np.max(weights), 0.0, 1.0)
|
||||
# Create a grayscale image from the weights array
|
||||
grayscale_image = Image.fromarray(np.uint8(weights * 255))
|
||||
# Convert the grayscale image into a two color gradient image using the specified gradient colors
|
||||
gradient_image = grayscale_to_gradient(grayscale_image, gradient_colors)
|
||||
|
||||
return gradient_image
|
||||
|
||||
def draw_gradient_ellipse(width=512, height=512, white_amount=1.0, rotation = 0.0, contrast = 1.0):
|
||||
"""
|
||||
Draw an ellipse with a radial gradient fill, and a variable amount of white in the center.
|
||||
|
||||
:param height: The height of the output image. Default is 512.
|
||||
:param width: The width of the output image. Default is 512.
|
||||
:param white_amount: The amount of white in the center of the ellipse, as a float between 0.0 and 1.0. Default is 1.0.
|
||||
:return: An RGBA image with the gradient ellipse.
|
||||
"""
|
||||
# Create a new image for outer ellipse
|
||||
size = (width, height)
|
||||
image = Image.new('RGBA', size, (255, 255, 255, 0))
|
||||
theta = rotation * (math.pi / 180)
|
||||
# Define the ellipse parameters
|
||||
center = (int(width // 2), int(height // 2))
|
||||
# Draw the ellipse and fill it with the radial gradient
|
||||
image = make_gradient_v2(width, height, center[0], center[1], width * white_amount, height * white_amount, theta)
|
||||
# Apply brightness method of ImageEnhance class
|
||||
image = ImageEnhance.Contrast(image).enhance(contrast).convert('RGBA')
|
||||
# Apply the alpha mask to the image
|
||||
image = apply_alpha_mask(image, image)
|
||||
# Define the radial gradient parameters
|
||||
#ellipse_width, ellipse_height = (int((width * white_amount) // 1.5), int((height * white_amount) // 1.5))
|
||||
#ellipse_colors = [(255, 255, 255, 255), (0, 0, 0, 0)]
|
||||
# Create a new image for inner ellipse
|
||||
#inner_ellipse = Image.new("L", size, 0)
|
||||
#inner_ellipse = make_gradient_v2(width, height, center[0], center[1], ellipse_width, ellipse_height, theta)
|
||||
#inner_ellipse = apply_alpha_mask(inner_ellipse, inner_ellipse)
|
||||
#image.paste(inner_ellipse, center, mask=inner_ellipse)
|
||||
# Creating object of Brightness class
|
||||
# Return the result image
|
||||
return image
|
||||
|
|
@ -8,10 +8,10 @@ from .helpers import (
|
|||
fix_env_Path_ffprobe,
|
||||
closest_upper_divisible_by_eight,
|
||||
load_model_from_setting,
|
||||
do_upscaleImg,
|
||||
do_upscaleImg,value_to_bool
|
||||
)
|
||||
from .sd_helpers import renderImg2Img, renderTxt2Img
|
||||
from .image import shrink_and_paste_on_blank, open_image, apply_alpha_mask
|
||||
from .image import shrink_and_paste_on_blank, open_image, apply_alpha_mask, draw_gradient_ellipse, resize_and_crop_image
|
||||
from .video import write_video
|
||||
|
||||
|
||||
|
|
@ -125,7 +125,7 @@ def create_zoom_single(
|
|||
prompts[key] = value
|
||||
prompt_images[key] = file_loc
|
||||
prompt_alpha_mask_images[key] = alpha_mask_loc
|
||||
prompt_image_is_keyframe[key] = is_keyframe
|
||||
prompt_image_is_keyframe[key] = value_to_bool(is_keyframe)
|
||||
except ValueError:
|
||||
pass
|
||||
assert len(prompts_array) > 0, "prompts is empty"
|
||||
|
|
@ -143,9 +143,7 @@ def create_zoom_single(
|
|||
extra_frames = 0
|
||||
|
||||
if custom_init_image:
|
||||
current_image = custom_init_image.resize(
|
||||
(width, height), resample=Image.LANCZOS
|
||||
)
|
||||
current_image = resize_and_crop_image(custom_init_image, width, height)
|
||||
print("using Custom Initial Image")
|
||||
else:
|
||||
if prompt_images[min(k for k in prompt_images.keys() if k >= 0)] == "":
|
||||
|
|
@ -165,14 +163,8 @@ def create_zoom_single(
|
|||
)
|
||||
current_image = processed.images[0]
|
||||
else:
|
||||
current_image = open_image(prompt_images[min(k for k in prompt_images.keys() if k >= 0)]).resize(
|
||||
(width, height), resample=Image.LANCZOS
|
||||
)
|
||||
|
||||
# apply available alpha mask
|
||||
if prompt_alpha_mask_images[min(k for k in prompt_alpha_mask_images.keys() if k >= 0)] != "":
|
||||
current_image = apply_alpha_mask(current_image, open_image(prompt_alpha_mask_images[min(k for k in prompt_alpha_mask_images.keys() if k >= 0)]))
|
||||
|
||||
current_image = open_image(prompt_images[min(k for k in prompt_images.keys() if k >= 0)])
|
||||
current_image = resize_and_crop_image(current_image, width, height)
|
||||
|
||||
mask_width = math.trunc(width / 4) # was initially 512px => 128px
|
||||
mask_height = math.trunc(height / 4) # was initially 512px => 128px
|
||||
|
|
@ -208,6 +200,14 @@ def create_zoom_single(
|
|||
if progress:
|
||||
progress(((i + 1) / num_outpainting_steps), desc=print_out)
|
||||
|
||||
# apply available alpha mask of previous image
|
||||
if prompt_alpha_mask_images[max(k for k in prompt_alpha_mask_images.keys() if k <= (i + 1))] != "":
|
||||
current_image = apply_alpha_mask(current_image, open_image(prompt_alpha_mask_images[max(k for k in prompt_alpha_mask_images.keys() if k <= (i + 1))]))
|
||||
else:
|
||||
#generate automatic alpha mask
|
||||
current_image_gradient_ratio = 0.615 #max((min(current_image.width/current_image.height,current_image.height/current_image.width) * 0.89),0.1)
|
||||
current_image = apply_alpha_mask(current_image, draw_gradient_ellipse(current_image.width, current_image.height, current_image_gradient_ratio, 0.0, 3.0).convert("RGB"))
|
||||
|
||||
prev_image_fix = current_image
|
||||
prev_image = shrink_and_paste_on_blank(current_image, mask_width, mask_height)
|
||||
current_image = prev_image
|
||||
|
|
@ -219,13 +219,11 @@ def create_zoom_single(
|
|||
# inpainting step
|
||||
current_image = current_image.convert("RGB")
|
||||
|
||||
paste_previous_image = prompt_image_is_keyframe[max(k for k in prompt_image_is_keyframe.keys() if k <= (i + 1))]
|
||||
paste_previous_image = not prompt_image_is_keyframe[max(k for k in prompt_image_is_keyframe.keys() if k <= (i + 1))]
|
||||
|
||||
# Custom and specified images work like keyframes
|
||||
if custom_exit_image and (i + 1) >= (num_outpainting_steps + extra_frames):
|
||||
current_image = custom_exit_image.resize(
|
||||
(width, height), resample=Image.LANCZOS
|
||||
)
|
||||
current_image = resize_and_crop_image(custom_exit_image, width, height)
|
||||
print("using Custom Exit Image")
|
||||
else:
|
||||
if prompt_images[max(k for k in prompt_images.keys() if k <= (i + 1))] == "":
|
||||
|
|
@ -251,13 +249,16 @@ def create_zoom_single(
|
|||
#current_image.paste(prev_image, mask=prev_image)
|
||||
paste_previous_image = True
|
||||
else:
|
||||
current_image = open_image(prompt_images[max(k for k in prompt_images.keys() if k <= (i + 1))]).resize(
|
||||
(width, height), resample=Image.LANCZOS
|
||||
)
|
||||
# use prerendered image, known as keyframe. Resize to target size
|
||||
current_image = open_image(prompt_images[max(k for k in prompt_images.keys() if k <= (i + 1))])
|
||||
current_image = resize_and_crop_image(current_image, width, height)
|
||||
|
||||
# apply available alpha mask
|
||||
if prompt_alpha_mask_images[max(k for k in prompt_alpha_mask_images.keys() if k <= (i + 1))] != "":
|
||||
current_image = apply_alpha_mask(current_image, open_image(prompt_alpha_mask_images[max(k for k in prompt_alpha_mask_images.keys() if k <= (i + 1))]))
|
||||
# apply available alpha mask of previous image
|
||||
#if prompt_alpha_mask_images[max(k for k in prompt_alpha_mask_images.keys() if k <= (i + 1))] != "":
|
||||
# current_image = apply_alpha_mask(current_image, open_image(prompt_alpha_mask_images[max(k for k in prompt_alpha_mask_images.keys() if k <= (i + 1))]))
|
||||
#else:
|
||||
# current_image_gradient_ratio = 0.65 #max((min(current_image.width/current_image.height,current_image.height/current_image.width) * 0.925),0.1)
|
||||
# current_image = draw_gradient_ellipse(current_image.width, current_image.height, current_image_gradient_ratio, 0.0, 1.8).convert("RGB")
|
||||
|
||||
# paste previous image on current image
|
||||
if paste_previous_image:
|
||||
|
|
|
|||
13
style.css
13
style.css
|
|
@ -8,3 +8,16 @@
|
|||
flex: 0 0 0%;
|
||||
width: 0;
|
||||
}
|
||||
.gradio-container-3-23-0 .gradio-dataframe input {
|
||||
height: 90%;
|
||||
width: 90%;
|
||||
}
|
||||
.gradio-container-3-23-0 .gradio-dataframe .scroll-hide {
|
||||
scrollbar-width: unset;
|
||||
}
|
||||
#component-2115, #component-2065 .gradio-column:nth-child(1) {
|
||||
flex-grow: .66 !important;
|
||||
}
|
||||
#component-2115 .gradio-video, #component-2065 .gradio-column:nth-child(1) .gradio-video {
|
||||
height: auto !important;
|
||||
}
|
||||
Loading…
Reference in New Issue