Add some functions to run.py to prepare for integration with overmasking

exit_image
Charles Fettinger 2023-05-22 15:44:47 -07:00
parent 0333b721a2
commit 21b14f510f
2 changed files with 123 additions and 0 deletions

View File

@ -29,6 +29,12 @@ class InfZoomConfig():
upscale_by:float
overmask:int
outpaintStrategy: str
blend_image:Image
blend_mode:str
blend_gradient_size:int
blend_invert_do:bool
blend_color:str
audio_filename=None,
inpainting_denoising_strength:float=1
inpainting_full_res:int =0
inpainting_padding:int=0

View File

@ -23,9 +23,81 @@ class InfZoomer:
def __init__(self, config: InfZoomConfig) -> None:
self.C = config
self.prompts = {}
self.prompt_images = {}
self.prompt_alpha_mask_images = {}
self.prompt_image_is_keyframe = {}
self.main_frames = []
self.out_config = {}
for x in self.C.prompts_array:
try:
key = int(x[0])
value = str(x[1])
file_loc = str(x[2])
alpha_mask_loc = str(x[3])
is_keyframe = bool(x[4])
self.prompts[key] = value
self.prompt_images[key] = file_loc
self.prompt_alpha_mask_images[key] = alpha_mask_loc
self.prompt_image_is_keyframe[key] = value_to_bool(is_keyframe)
except ValueError:
pass
assert len(self.C.prompts_array) > 0, "prompts is empty"
fix_env_Path_ffprobe()
self.out_config = self.prepare_output_path()
self.current_seed = self.C.seed
# knowing the mask_height and desired outputsize find a compromise due to align 8 contraint of diffuser
self.width = closest_upper_divisible_by_eight(self.C.outputsizeW)
self.height = closest_upper_divisible_by_eight(self.C.outputsizeH)
if self.width > self.height:
self.mask_width = self.C.outpaint_amount_px
self.mask_height = math.trunc(self.C.outpaint_amount_px * self.height/self.width)
else:
self.mask_height = self.C.outpaint_amount_px
self.mask_width = math.trunc(self.C.outpaint_amount_px * self.width/self.height)
# here we leave slightly the desired ratio since if size+2*mask_size % 8 != 0
# distribute "aligning pixels" to the mask size equally.
# only consider mask_size since image size is alread 8-aligned
self.mask_width -= self.mask_width % 4
self.mask_height -= self.mask_height % 4
assert 0 == (2*self.mask_width+self.width) % 8
assert 0 == (2*self.mask_height+self.height) % 8
print (f"Adapted sizes for diffusers to: {self.width}x{self.height}+mask:{self.mask_width}x{self.mask_height}. New ratio: {(self.width+self.mask_width)/(self.height+self.mask_height)} ")
self.num_interpol_frames = round(self.C.video_frame_rate * self.C.zoom_speed) - 1 # keyframe not to be interpolated
if (self.C.outpaintStrategy == "Corners"):
self.fnOutpaintMainFrames = self.outpaint_steps_cornerStrategy
self.fnInterpolateFrames = self.interpolateFramesOuterZoom
elif (self.C.outpaintStrategy == "Center"):
self.fnOutpaintMainFrames = self.outpaint_steps_v8hid
self.fnInterpolateFrames = self.interpolateFramesSmallCenter
else:
raise ValueError("Unsupported outpaint strategy in Infinite Zoom")
self.outerZoom = True # scale from overscan to target viewport
# object properties, different from user input config
out_config = {}
prompts = {}
main_frames:Image = []
outerZoom: bool
mask_width: int
mask_height: int
current_seed: int
contVW: ContinuousVideoWriter
fnOutpaintMainFrames: Callable
fnInterpolateFrames: Callable
def outpaint_steps(
width,
height,
@ -569,3 +641,48 @@ def create_zoom_single(
plaintext_to_html(processed.info),
plaintext_to_html(""),
)
def create_mask_with_circles(original_image, border_width, border_height, overmask: int, radius=4):
# Create a new image with border and draw a mask
new_width = original_image.width + 2 * border_width
new_height = original_image.height + 2 * border_height
# Create new image, default is black
mask = Image.new('RGB', (new_width, new_height), 'white')
# Draw black rectangle
draw = ImageDraw.Draw(mask)
draw.rectangle([border_width+overmask, border_height+overmask, new_width - border_width-overmask, new_height - border_height-overmask], fill='black')
# Coordinates for circles
circle_coords = [
(border_width, border_height), # Top-left
(new_width - border_width, border_height), # Top-right
(border_width, new_height - border_height), # Bottom-left
(new_width - border_width, new_height - border_height), # Bottom-right
(new_width // 2, border_height), # Middle-top
(new_width // 2, new_height - border_height), # Middle-bottom
(border_width, new_height // 2), # Middle-left
(new_width - border_width, new_height // 2) # Middle-right
]
# Draw circles
for coord in circle_coords:
draw.ellipse([coord[0] - radius, coord[1] - radius, coord[0] + radius, coord[1] + radius], fill='white')
return mask
def pil_to_cv2(image):
return cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR)
def cv2_to_pil(image):
return Image.fromarray(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
def cv2_crop_center(img, toSize: tuple[int,int]):
y,x = img.shape[:2]
startx = x//2-(toSize[0]//2)
starty = y//2-(toSize[1]//2)
return img[starty:starty+toSize[1],startx:startx+toSize[0]]