2

I am now trying to interpolate video using optical flow. I was able to interpolate the video by referring to this question and using it as a reference. So my question is: Is it possible to interpolate the video in 1/4 units even finer using the original frame and the optical flow frame? Thank you in advance.

I tried halving the optical flow frame and remapped it to the original image, but it did not work. (It's obvious, of course, but...).

taku397
  • 23
  • 3

1 Answers1

1

I will try solving this problem with the help of an example. Suppose my previous image is enter image description here

and my next image is enter image description here

The next image was created by translating the previous image towards right (I hope it is visible).

Now, let's calculate the optical flow between the two images and plot the flow vectors.

optical_flow = cv2.calcOpticalFlowFarneback(img1, img2, None, pyr_scale = 0.5, levels = 3, winsize = 200, iterations = 3, poly_n = 5, poly_sigma = 1.1, flags = 0)

I have taken the previous image and drawn flow vectors on top of it. enter image description here This image shows that, previous image was formed by translating the next image towards the left.

If you followed this, it is pretty easy to accomplish the task at hand .i.e interpolate frames between these two frames

Essentially, optical flow vectors tell us for each pixel, where has the pixel come from the previous image. Lets talk about a particular pixel, which has moved from (100, 100) to (200, 100) .i.e moved in the right direction by 100 pixels. The question is where will this pixel be if there was uniform motion between these 2 frames? Example: if there were 4 frames in between these two frames, the pixel will be at locations

initial location     =  (100, 100)  
interpolated frame 1 =  (120, 100)
interpolated frame 2 =  (140, 100)
interpolated frame 3 =  (160, 100)
interpolated frame 4 =  (180, 100)
final location.      =  (200, 100)

Enough talking, let me show you some code.

def load_image(image_path):
    "Load the image and convert it into a grayscale image"
    img = cv2.imread(image_path)
    return cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)


def plot_flow_vectors(img, flow):
    """
    Plots the flow vectors
    """
    img = img.copy()
    h, w = img.shape[:2]
    step_size = 40
    cv2.imshow("original_image", img)
    for y in range(0, h, step_size):
        for x in range(0, w, step_size):
            # Get the flow vector at this point
            dx, dy = flow[y, x]
            # Draw an arrow to represent the flow vector
            cv2.arrowedLine(img, (x, y), (int(x + dx), int(y + dy)), (0, 255, 0), 1, cv2.LINE_AA, tipLength=0.8)
    cv2.imshow("image_with_flow_vectors", img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

img1 = load_image('first.jpeg') // load previous image
img2 = load_image('second.jpeg') // load next image
optical_flow = cv2.calcOpticalFlowFarneback(img1, img2, None, pyr_scale = 0.5, levels = 3, winsize = 200, iterations = 3, poly_n = 5, poly_sigma = 1.1, flags = 0) // calculate optical flow

plot_flow_vectors(img1, optical_flow) // plot flow vectors


// Generate frames in between 
num_frames = 10
h, w = optical_flow.shape[:2]
for frame_num in range(1, num_frames+1):
    alpha = frame_num / num_frames
    flow =  alpha * optical_flow
    flow[:,:,0] += np.arange(w)
    flow[:,:,1] += np.arange(h)[:,np.newaxis]
    interpolated_frame = cv2.remap(img2, flow, None, cv2.INTER_LINEAR)
    cv2.imshow("intermediate_frame", interpolated_frame)
    cv2.waitKey(0)

PS: optical flow vectors also show an motion in the y direction (when there isn't). I think it is an artifact of the large motion between the two frames. This is generally not the case for frames in a video.

Edit: I created a github repository to interpolate frames in between two video frames to increase the video fps or get a slow motion video out of the input video. Check it out here

  • thanks a lot! Now, I can not try to run this code, so I will come home and try as soon as possible!!! – taku397 Apr 12 '23 at 15:55
  • sorry for replying. I carried out your code, and compare 10 interpolation frames with first.jpg and second.jpg and show [a image of mixing band , which is composed of second frame and 10th interpolation frame](https://drive.google.com/file/d/1ywmAosa-k3miKVUQzz8VrJoqAZq8kMCA/view?usp=share_link) . Looking at this image, I checked that 10th interpolation image is right below the second. Is it a same result in your environment? – taku397 Apr 17 '23 at 09:57
  • If you run the code I have provided and press any key, you will see the image move towards the right and will end right below the second.jpeg image. – satinder singh Apr 17 '23 at 12:36
  • I ran your code and saved interpolation frames with cv2.imwrite(). Looking at images, I feel the interpolation is working well. But comparing with the10th interpolation image and second.jpeg, the 10th interpolation image is bottom right second.jpeg.(I wrote BOTTOM RIGHT as RIGHT BELOW earlier. sorry for my bad English) – taku397 Apr 17 '23 at 15:23
  • I did the same exact thing, wrote the frames using `imwrite`. [Here](https://drive.google.com/drive/folders/1jZbOGZbjSoMlagMKnQXYRG-HJY1mZB1v?usp=share_link) are all the 10 frames. Are you talking about the minor movement in the Y axis? – satinder singh Apr 18 '23 at 06:38
  • sorry for my replying lately. Yes. When I compare the result of interpolating the two parallel moving frames with second.jpeg, the interpolated image has moved to the lower right corner of second.jpeg. I find this strange. Ahh the flow vector image you attached shows that the flow vector is also present in the blank area where there is no AB. Is this affecting the interpolation? – taku397 Apr 19 '23 at 15:58
  • Did you see the images I added? I don't see "the interpolated image has moved to the lower right corner of second.jpeg" behaviour when I run the code. The flow vectors in the blank region are because of high `window size` while calculating ht optical flow between the frames. – satinder singh Apr 20 '23 at 07:40
  • Yes, I did. Thay are same mine. Sorry if I didn't word it right. The interpolated AB is located in the lower right of second.jpg. The movement between the two images moved horizontally to the right, so it seems that the interpolation is not working as the completed AB is located in the lower right of second.jpg. Would you like to overlay the second.jpg and the interpolated 10th image and check it? can you confirm that AB is not interpolating as you want? – taku397 Apr 21 '23 at 05:09