Prep for merging overmasking

UI and superficial changes
exit_image
Charles Fettinger 2023-05-20 00:36:50 -07:00
parent cf2e0d3ed1
commit ce5816d657
6 changed files with 211 additions and 31 deletions

View File

@ -0,0 +1,36 @@
from dataclasses import dataclass
from PIL import Image
@dataclass
class InfZoomConfig():
common_prompt_pre:str
prompts_array:list[str]
common_prompt_suf:str
negative_prompt:str
num_outpainting_steps: int
guidance_scale:float
num_inference_steps:int
custom_init_image:Image
custom_exit_image:Image
video_frame_rate:int
video_zoom_mode:int #0: ZoomOut, 1: ZoomIn
video_start_frame_dupe_amount:int
video_last_frame_dupe_amount:int
video_ffmpeg_opts: str
inpainting_mask_blur:int
inpainting_fill_mode:int
zoom_speed:float
seed:int
outputsizeW:int
outputsizeH:int
batchcount:int
sampler:str
upscale_do:bool
upscaler_name:str
upscale_by:float
overmask:int
outpaintStrategy: str
inpainting_denoising_strength:float=1
inpainting_full_res:int =0
inpainting_padding:int=0
outpaint_amount_px: int=64
progress:any=None

View File

@ -42,6 +42,8 @@ def open_image(image_path):
Returns:
Image: A PIL Image object of the opened image.
"""
# Strip leading and trailing double quotation marks, if present
image_path = image_path.strip('"')
if image_path.startswith('http'):
# If the image path is a URL, download the image using requests
response = requests.get(image_path)

View File

@ -1,5 +1,8 @@
import math, time, os
import numpy as np
from scipy.signal import savgol_filter
from typing import Callable
import cv2
from PIL import Image, ImageFilter, ImageDraw, ImageColor
from modules.ui import plaintext_to_html
import modules.shared as shared
@ -13,7 +16,15 @@ from .helpers import (
)
from .sd_helpers import renderImg2Img, renderTxt2Img
from .image import shrink_and_paste_on_blank, open_image, apply_alpha_mask, draw_gradient_ellipse, resize_and_crop_image, crop_fethear_ellipse, crop_inner_image
from .video import write_video, add_audio_to_video
from .video import write_video, add_audio_to_video, ContinuousVideoWriter
from .InfZoomConfig import InfZoomConfig
class InfZoomer:
def __init__(self, config: InfZoomConfig) -> None:
self.C = config
self.prompts = {}
self.main_frames = []
self.out_config = {}
def outpaint_steps(
width,
@ -193,6 +204,7 @@ def create_zoom(
video_zoom_mode,
video_start_frame_dupe_amount,
video_last_frame_dupe_amount,
video_ffmpeg_opts,
inpainting_mask_blur,
inpainting_fill_mode,
zoom_speed,
@ -204,6 +216,9 @@ def create_zoom(
upscale_do,
upscaler_name,
upscale_by,
overmask,
outpaintStrategy,
outpaint_amount_px,
blend_image,
blend_mode,
blend_gradient_size,

View File

@ -0,0 +1,77 @@
from .run import (InfZoomer)
from .InfZoomConfig import InfZoomConfig
from PIL import Image
# to be called from Gradio or other client
def createZoom(
common_prompt_pre:str,
prompts_array:list[str],
common_prompt_suf:str,
negative_prompt:str,
num_outpainting_steps: int,
guidance_scale:float,
num_inference_steps:int,
custom_init_image:Image,
custom_exit_image:Image,
video_frame_rate:int,
video_zoom_mode:int,
video_start_frame_dupe_amount:int,
video_last_frame_dupe_amount:int,
video_ffmpeg_opts:str,
inpainting_mask_blur:int,
inpainting_fill_mode:int,
zoom_speed:float,
seed:int,
outputsizeW:int,
outputsizeH:int,
batchcount:int,
sampler:str,
upscale_do:bool,
upscaler_name:str,
upscale_by:float,
overmask:int,
outpaintStrategy:str,
outpaint_amount_px: int,
inpainting_denoising_strength:float=1,
inpainting_full_res:int =0,
inpainting_padding:int=0,
progress:any=None
):
izc = InfZoomConfig(
common_prompt_pre,
prompts_array,
common_prompt_suf,
negative_prompt,
num_outpainting_steps,
guidance_scale,
num_inference_steps,
custom_init_image,
custom_exit_image,
video_frame_rate,
video_zoom_mode,
video_start_frame_dupe_amount,
video_last_frame_dupe_amount,
video_ffmpeg_opts,
inpainting_mask_blur,
inpainting_fill_mode,
zoom_speed,
seed,
outputsizeW,
outputsizeH,
batchcount,
sampler,
upscale_do,
upscaler_name,
upscale_by,
overmask,
outpaintStrategy,
inpainting_denoising_strength,
inpainting_full_res,
inpainting_padding,
outpaint_amount_px,
progress
)
iz= InfZoomer(izc)
r = iz.create_zoom()
del iz
return r

View File

@ -5,6 +5,7 @@ from .run import create_zoom
import modules.shared as shared
from webui import wrap_gradio_gpu_call
from modules.ui import create_output_panel
from .run_interface import createZoom
from .static_variables import (
default_prompt,
@ -16,6 +17,7 @@ from .static_variables import (
default_cfg_scale,
default_mask_blur,
default_sampler,
default_overmask,
default_gradient_size,
)
from .helpers import validatePromptJson_throws, putPrompts, clearPrompts, renumberDataframe
@ -175,6 +177,23 @@ def on_ui_tabs():
step=0.1,
info="Zoom speed in seconds (higher values create slower zoom)",
)
with gr.Accordion("FFMPEG Expert", open=False):
gr.Markdown(
"""# I need FFMPEG control
You can put CLI options here as documented <a href='https://ffmpeg.org/ffmpeg.html#Options'>FFMPEG OPTIONS</a> and <a href='https://ffmpeg.org/ffmpeg-filters.html'>FILTER OPTIONS</a>
## Examples:
* ```-vf crop=200:200``` crop down to 200x200 pixel from center (useful to cutoff jumpy borders)
* ```-vf scale=320:240``` scales your video to 320x240
* ```-c:v libx264 -preset veryslow -qp 0``` uses lossless compression
You might give multiple options in one line.
"""
)
video_ffmpeg_opts=gr.Textbox(
value="", label="FFMPEG Opts"
)
with gr.Accordion("Blend settings"):
with gr.Row():
blend_image = gr.Image(type="pil", label="Custom in/out Blend Image")
@ -223,12 +242,27 @@ Ideas for custom blend images: https://www.pexels.com/search/gradient/
audio_file.change(get_filename, inputs=[audio_file], outputs=[audio_filename])
with gr.Tab("Outpaint"):
outpaint_amount_px = gr.Slider(
label="Outpaint pixels",
minimum=4,
maximum=508,
step=8,
value=64,
)
inpainting_mask_blur = gr.Slider(
label="Mask Blur",
minimum=0,
maximum=64,
step=1,
value=default_mask_blur,
step=1
)
overmask = gr.Slider(
label="Overmask (px) paint a bit into centered image",
minimum=0,
maximum=64,
step=1,
value=default_overmask,
)
inpainting_fill_mode = gr.Radio(
label="Masked content",
@ -237,6 +271,15 @@ Ideas for custom blend images: https://www.pexels.com/search/gradient/
type="index",
)
outpaintStrategy= gr.Radio(
label="Outpaint Strategy",
choices=["Center", "Corners"],
value="Corners",
type="value"
)
with gr.Tab("Post proccess"):
upscale_do = gr.Checkbox(False, label="Enable Upscale")
upscaler_name = gr.Dropdown(
@ -358,6 +401,7 @@ Our best experience and trade-off is the R-ERSGAn4x upscaler.
video_zoom_mode,
video_start_frame_dupe_amount,
video_last_frame_dupe_amount,
video_ffmpeg_opts,
inpainting_mask_blur,
inpainting_fill_mode,
video_zoom_speed,
@ -369,6 +413,9 @@ Our best experience and trade-off is the R-ERSGAn4x upscaler.
upscale_do,
upscaler_name,
upscale_by,
overmask,
outpaintStrategy,
outpaint_amount_px,
blend_image,
blend_mode,
blend_gradient_size,

View File

@ -70,41 +70,44 @@ def write_video(file_path, frames, fps, reversed=True, start_frame_dupe_amount=1
writer.close()
class ContinuousVideoWriter:
class ContinuousVideoWriter:
_writer = None
_writer = None
def __init__(self, file_path, initframe, fps, start_frame_dupe_amount=15):
"""
Writes initial frame to a new mp4 video file
:param file_path: Path to output video, must end with .mp4
:param frame: Start image PIL.Image objects
:param fps: Desired frame rate
:param reversed: if order of images to be reversed (default = True)
"""
def __init__(self, file_path, initframe, fps, start_frame_dupe_amount=15, video_ffmpeg_opts="" ):
"""
Writes initial frame to a new mp4 video file
:param file_path: Path to output video, must end with .mp4
:param frame: Start image PIL.Image objects
:param fps: Desired frame rate
:param reversed: if order of images to be reversed (default = True)
"""
ffopts = []
if video_ffmpeg_opts is not "":
ffopts= video_ffmpeg_opts.split(" ")
writer = imageio.get_writer(file_path, fps=fps, macro_block_size=None)
start_frames = [initframe] * start_frame_dupe_amount
for f in start_frames:
writer.append_data(np.array(f))
self._writer = writer
writer = imageio.get_writer(file_path, fps=fps, macro_block_size=None, ffmpeg_params=ffopts)
start_frames = [initframe] * start_frame_dupe_amount
for f in start_frames:
writer.append_data(np.array(f))
self._writer = writer
def append(self, frames):
"""
Append a list of image PIL.Image objects to the end of the file.
:param frames: List of image PIL.Image objects
"""
for i,f in enumerate(frames):
self._writer.append_data(np.array(f))
def append(self, frames):
"""
Append a list of image PIL.Image objects to the end of the file.
:param frames: List of image PIL.Image objects
"""
for i,f in enumerate(frames):
self._writer.append_data(np.array(f))
def finish(self, frame, last_frame_dupe_amount=30 ):
"""
Closes the file writer.
"""
for i in range(last_frame_dupe_amount):
self._writer.append_data(np.array(frame))
def finish(self, frame, last_frame_dupe_amount=30 ):
"""
Closes the file writer.
"""
for i in range(last_frame_dupe_amount):
self._writer.append_data(np.array(frame))
self._writer.close()
self._writer.close()
def add_audio_to_video(video_path, audio_path, output_path, ffmpeg_location = 'ffmpeg'):
command = [ffmpeg_location, '-i', video_path, '-i', audio_path, '-c:v', 'copy', '-c:a', 'aac', '-map', '0:v:0', '-map', '1:a:0', '-shortest', output_path]