parent
cf2e0d3ed1
commit
ce5816d657
|
|
@ -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
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
Loading…
Reference in New Issue