| | import os |
| | import sys |
| | from cgi import test |
| | from pathlib import Path |
| |
|
| | import cv2 |
| | import mediapy |
| | import numpy as np |
| | from frame_interpolation.eval import interpolator, util |
| | from huggingface_hub import snapshot_download |
| | from image_tools.sizes import resize_and_crop |
| | from moviepy.editor import CompositeVideoClip, ImageClip |
| | from moviepy.editor import VideoFileClip as vfc |
| | from PIL import Image |
| |
|
| |
|
| | |
| | def list_of_positions(num_contours, num_frames=100): |
| | positions = [] |
| | for i in range(0, num_frames): |
| | positions.append(int(num_contours / num_frames * i)) |
| | return positions |
| |
|
| |
|
| | def contourfinder(image1, image2, text=None, num_frames=100, output_dir=Path("temp")): |
| | |
| | |
| | blank = np.zeros(np.shape(image1), dtype="uint8") |
| | blank2 = np.zeros(np.shape(image2), dtype="uint8") |
| | |
| | threshold = cv2.Canny(image=image1, threshold1=100, threshold2=200) |
| | contours, hierarchies = cv2.findContours( |
| | threshold, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE |
| | ) |
| |
|
| | threshold2 = cv2.Canny(image=image2, threshold1=100, threshold2=200) |
| | contours2, hierarchies2 = cv2.findContours( |
| | threshold2, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE |
| | ) |
| |
|
| | |
| | vid1 = cv2.VideoWriter( |
| | Path(output_dir / "vid1.mp4").as_posix(), |
| | cv2.VideoWriter_fourcc(*"mp4v"), |
| | 24, |
| | threshold.shape, |
| | ) |
| | vid2 = cv2.VideoWriter( |
| | Path(output_dir / "vid2.mp4").as_posix(), |
| | cv2.VideoWriter_fourcc(*"mp4v"), |
| | 24, |
| | threshold.shape, |
| | ) |
| | text_vid = cv2.VideoWriter( |
| | Path(output_dir / "text_video.mp4").as_posix(), |
| | cv2.VideoWriter_fourcc(*"mp4v"), |
| | 10, |
| | threshold.shape, |
| | ) |
| |
|
| | |
| | positions = list_of_positions((len(contours))) |
| | frames = [] |
| |
|
| | |
| | for i in range(0, len(contours)): |
| | cv2.drawContours( |
| | blank, contours=contours, contourIdx=i, color=(125, 200, 255), thickness=1 |
| | ) |
| |
|
| | if i in positions: |
| | frames.append(blank) |
| | |
| | vid1.write(blank) |
| |
|
| | vid1.release() |
| | clip1 = vfc(Path(output_dir / "vid1.mp4").as_posix()) |
| | positions = list_of_positions((len(contours2))) |
| |
|
| | for i in range(0, len(contours2)): |
| | cv2.drawContours( |
| | blank2, contours=contours2, contourIdx=i, color=(125, 200, 255), thickness=1 |
| | ) |
| | if i in positions: |
| | frames.append(blank2) |
| |
|
| | vid2.write(blank2) |
| |
|
| | vid2.release() |
| | clip3 = vfc(Path(output_dir / "vid2.mp4").as_posix()) |
| |
|
| | |
| |
|
| | if text != None: |
| | |
| | image = np.zeros(original.shape, dtype="uint8") |
| |
|
| | |
| | font = cv2.FONT_HERSHEY_COMPLEX |
| |
|
| | |
| | org = (10, 400) |
| |
|
| | |
| | fontScale = 3 |
| |
|
| | |
| | color = (186, 184, 108) |
| |
|
| | |
| | thickness = 4 |
| |
|
| | def text_frames(text, image, org): |
| | spacing = 55 |
| | blink = image |
| | cv2.imwrite(Path(output_dir / "blink.png").as_posix(), blink) |
| | for i in range(0, len(text) - 1): |
| |
|
| | text_vid.write(blink) |
| |
|
| | |
| | image = cv2.putText( |
| | image, text[i], org, font, fontScale, color, thickness, cv2.LINE_AA |
| | ) |
| |
|
| | |
| | org = (org[0] + spacing, org[1]) |
| | if text[i].isupper(): |
| | org = (org[0] + spacing + 1, org[1]) |
| | print(f"Upper {text[i]}") |
| | print(org) |
| |
|
| | |
| | cv2.imwrite(Path(output_dir / f"text_im{i}.png").as_posix, image) |
| |
|
| | |
| | text_vid.write(image) |
| | text_vid.release() |
| |
|
| | text_frames(text, image, org) |
| | return clip1, clip3 |
| |
|
| |
|
| | def load_model(model_name): |
| | model = interpolator.Interpolator(snapshot_download(repo_id=model_name), None) |
| | return model |
| |
|
| |
|
| | model_names = [ |
| | "akhaliq/frame-interpolation-film-style", |
| | "NimaBoscarino/frame-interpolation_film_l1", |
| | "NimaBoscarino/frame_interpolation_film_vgg", |
| | ] |
| |
|
| | models = {model_name: load_model(model_name) for model_name in model_names} |
| |
|
| | ffmpeg_path = util.get_ffmpeg_path() |
| | mediapy.set_ffmpeg(ffmpeg_path) |
| |
|
| |
|
| | def resize(width, img): |
| | basewidth = width |
| | img = Image.open(img) |
| | wpercent = basewidth / float(img.size[0]) |
| | hsize = int((float(img.size[1]) * float(wpercent))) |
| | img = img.resize((basewidth, hsize), Image.ANTIALIAS) |
| | return img |
| |
|
| |
|
| | def resize_img(img1, img2, output_dir): |
| | img_target_size = Image.open(img1) |
| | img_to_resize = resize_and_crop( |
| | img2, |
| | ( |
| | img_target_size.size[0], |
| | img_target_size.size[1], |
| | ), |
| | crop_origin="middle", |
| | ) |
| | img_to_resize.save(Path(output_dir / "resized_img2.png")) |
| |
|
| |
|
| | def get_video_frames( |
| | images, vid_output_dir="temp", times_to_interpolate=6, model_name_index=0 |
| | ): |
| | frame1 = images[0] |
| | frame2 = images[1] |
| |
|
| | model = models[model_names[model_name_index]] |
| | cv2_images = [cv2.imread(frame1), cv2.imread(frame2)] |
| |
|
| | frame1 = resize(256, frame1) |
| | frame2 = resize(256, frame2) |
| | test_1 = Path(vid_output_dir / "test1.png") |
| | test_2 = Path(vid_output_dir / "test2.png") |
| | frame1.save(test_1) |
| | frame2.save(test_2) |
| |
|
| | resize_img(test_1, test_2, vid_output_dir) |
| | input_frames = [ |
| | Path(vid_output_dir / "test1.png").as_posix(), |
| | Path(vid_output_dir / "resized_img2.png").as_posix(), |
| | ] |
| |
|
| | frames = list( |
| | util.interpolate_recursively_from_files( |
| | input_frames, times_to_interpolate, model |
| | ) |
| | ) |
| | return frames, cv2_images |
| |
|
| |
|
| | def create_mp4_with_audio( |
| | frames, cv2_images, duration, audio, output_path, overlay_image |
| | ): |
| | vid_output_dir = output_path.parent |
| | temp_vid_path = Path(vid_output_dir / "TEMP.mp4") |
| | mediapy.write_video(temp_vid_path, frames, fps=10) |
| | print( |
| | f"TYPES....{type(cv2_images[0])},{type(cv2_images[1])} SHAPES{cv2_images[0].shape} Img {cv2_images[0]}" |
| | ) |
| | clip1, clip3 = contourfinder( |
| | cv2_images[0], cv2_images[1], output_dir=vid_output_dir |
| | ) |
| |
|
| | |
| | |
| | clip1 = clip1 |
| | clip2 = ( |
| | vfc(temp_vid_path.as_posix()) |
| | .resize(2) |
| | .set_start(clip1.duration - 0.5) |
| | .crossfadein(2) |
| | ) |
| | clip3 = clip3.set_start((clip1.duration - 0.5) + (clip2.duration)).crossfadein(2) |
| |
|
| | new_clip = CompositeVideoClip([clip1, clip2, clip3]) |
| | new_clip.audio = audio |
| | image = ( |
| | ImageClip(overlay_image).set_duration(duration).resize(0.5).set_pos("center") |
| | ) |
| |
|
| | new_clip.set_duration(duration) |
| | |
| | final_clip = CompositeVideoClip([new_clip, image]) |
| | final_clip.write_videofile(output_path.as_posix(), audio_codec="aac") |
| | return output_path.as_posix() |
| |
|