File size: 7,571 Bytes
13a5199
 
299cfef
2224f3b
13a5199
 
 
 
4498d9d
13a5199
 
2e38275
13a5199
 
 
 
 
 
 
 
 
 
 
 
bc014af
13a5199
 
2224f3b
 
13a5199
 
 
 
 
 
 
 
 
 
 
 
 
8756e93
2224f3b
 
 
13a5199
 
8756e93
2224f3b
 
 
13a5199
 
8756e93
2224f3b
 
 
13a5199
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2224f3b
13a5199
8756e93
13a5199
 
 
 
 
 
 
 
 
 
 
 
8756e93
13a5199
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8756e93
13a5199
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8756e93
13a5199
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2224f3b
77f594c
13a5199
77f594c
13a5199
 
 
bc1258a
13a5199
 
2224f3b
13a5199
 
2224f3b
 
 
bc1258a
 
13a5199
77f594c
bc1258a
13a5199
 
 
299cfef
 
 
 
13a5199
299cfef
2224f3b
5f6f7a2
 
2224f3b
13a5199
 
 
 
 
 
bc1258a
13a5199
 
2e38275
 
 
2224f3b
 
daaeae3
2224f3b
 
 
 
1d126b4
2224f3b
13a5199
 
 
 
605c7d5
 
2b595b3
605c7d5
 
 
13a5199
 
0b0dc7f
2224f3b
2e38275
 
 
 
bc1258a
2e38275
 
 
61aea0c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
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


# get key positions at which frame needs to be generated
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")):
    # Create two blank pages to write into
    # I just hardcoded 1024*1024 as the size, ideally this should be np.shape(image1)
    blank = np.zeros(np.shape(image1), dtype="uint8")
    blank2 = np.zeros(np.shape(image2), dtype="uint8")
    # Threshold and contours for image 1 and 2
    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
    )

    # Initialize three empty videos
    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,
    )

    # Get positions
    positions = list_of_positions((len(contours)))
    frames = []

    # Loop over contours adding them to blank image then writing to video
    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)
            # Complile to video
            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())

    # Next is the text vid

    if text != None:
        # Reading an image in default mode
        image = np.zeros(original.shape, dtype="uint8")

        # font
        font = cv2.FONT_HERSHEY_COMPLEX

        # org
        org = (10, 400)

        # fontScale
        fontScale = 3

        # Blue color in BGR
        color = (186, 184, 108)

        # Line thickness of 2 px
        thickness = 4

        def text_frames(text, image, org):
            spacing = 55  # spacing between letters
            blink = image
            cv2.imwrite(Path(output_dir / "blink.png").as_posix(), blink)
            for i in range(0, len(text) - 1):

                text_vid.write(blink)

                # Using cv2.putText() method
                image = cv2.putText(
                    image, text[i], org, font, fontScale, color, thickness, cv2.LINE_AA
                )

                # Take care of org spacing
                org = (org[0] + spacing, org[1])
                if text[i].isupper():
                    org = (org[0] + spacing + 1, org[1])
                    print(f"Upper {text[i]}")
                print(org)

                # Displaying the image
                cv2.imwrite(Path(output_dir / f"text_im{i}.png").as_posix, image)

                # Complile to video
                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],
        ),  # set width and height to match cv2_images[0]
        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
    )  # has a third text option

    # Use open CV and moviepy code
    # So we move from open CV video 1 to out.mp4 to open CV video2
    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  # Naviely append audio without considering the length of the video, could be a problem, no idea, but it works, so I'm not touching it
    image = (
        ImageClip(overlay_image).set_duration(duration).resize(0.5).set_pos("center")
    )

    new_clip.set_duration(duration)
    # Now overlay the image with moviepy
    final_clip = CompositeVideoClip([new_clip, image])
    final_clip.write_videofile(output_path.as_posix(), audio_codec="aac")
    return output_path.as_posix()