|
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() |
|
|