Spaces:
Runtime error
Runtime error
import copy | |
import os | |
import shutil | |
import cv2 | |
import gradio as gr | |
import modules.scripts as scripts | |
from modules import images | |
from modules.processing import process_images | |
from modules.shared import opts | |
from PIL import Image | |
def get_all_frames(video_path): | |
if video_path is None: | |
return None | |
cap = cv2.VideoCapture(video_path) | |
frame_list = [] | |
if not cap.isOpened(): | |
return | |
while True: | |
ret, frame = cap.read() | |
if ret: | |
frame_list.append(frame) | |
else: | |
return frame_list | |
def get_min_frame_num(video_list): | |
min_frame_num = -1 | |
for video in video_list: | |
if video is None: | |
continue | |
else: | |
frame_num = len(video) | |
print(frame_num) | |
if min_frame_num < 0: | |
min_frame_num = frame_num | |
elif frame_num < min_frame_num: | |
min_frame_num = frame_num | |
return min_frame_num | |
def save_gif(path, image_list, name, duration): | |
tmp_dir = path + "/tmp/" | |
if os.path.isdir(tmp_dir): | |
shutil.rmtree(tmp_dir) | |
os.mkdir(tmp_dir) | |
for i, image in enumerate(image_list): | |
images.save_image(image, tmp_dir, f"output_{i}") | |
os.makedirs(path + "/controlnet-m2m", exist_ok=True) | |
image_list[0].save(path + f"/controlnet-m2m/{name}.gif", save_all=True, append_images=image_list[1:], optimize=False, duration=duration, loop=0) | |
class Script(scripts.Script): | |
def title(self): | |
return "controlnet m2m" | |
def show(self, is_img2img): | |
return True | |
def ui(self, is_img2img): | |
# How the script's is displayed in the UI. See https://gradio.app/docs/#components | |
# for the different UI components you can use and how to create them. | |
# Most UI components can return a value, such as a boolean for a checkbox. | |
# The returned values are passed to the run method as parameters. | |
ctrls_group = () | |
max_models = opts.data.get("control_net_max_models_num", 1) | |
with gr.Group(): | |
with gr.Accordion("ControlNet-M2M", open = False): | |
with gr.Tabs(): | |
for i in range(max_models): | |
with gr.Tab(f"ControlNet-{i}", open=False): | |
ctrls_group += (gr.Video(format='mp4', source='upload', elem_id = f"video_{i}"), ) | |
duration = gr.Slider(label=f"Duration", value=50.0, minimum=10.0, maximum=200.0, step=10, interactive=True) | |
ctrls_group += (duration,) | |
return ctrls_group | |
def run(self, p, *args): | |
# This is where the additional processing is implemented. The parameters include | |
# self, the model object "p" (a StableDiffusionProcessing class, see | |
# processing.py), and the parameters returned by the ui method. | |
# Custom functions can be defined here, and additional libraries can be imported | |
# to be used in processing. The return value should be a Processed object, which is | |
# what is returned by the process_images method. | |
video_num = opts.data.get("control_net_max_models_num", 1) | |
video_list = [get_all_frames(video) for video in args[:video_num]] | |
duration, = args[video_num:] | |
frame_num = get_min_frame_num(video_list) | |
if frame_num > 0: | |
output_image_list = [] | |
for frame in range(frame_num): | |
copy_p = copy.copy(p) | |
copy_p.control_net_input_image = [] | |
for video in video_list: | |
if video is None: | |
continue | |
copy_p.control_net_input_image.append(video[frame]) | |
proc = process_images(copy_p) | |
img = proc.images[0] | |
output_image_list.append(img) | |
copy_p.close() | |
# TODO: Generate new name for each movie2movie output | |
save_gif(p.outpath_samples, output_image_list, "animation", duration) | |
proc.images = [p.outpath_samples + "/controlnet-m2m/animation.gif"] | |
else: | |
proc = process_images(p) | |
return proc |