File size: 9,445 Bytes
be6d4fe
 
bbe8153
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d4a56f6
bbe8153
e2f851a
 
bbe8153
4c8c2c3
bbe8153
 
856a15a
cf309f8
 
4fceacd
b6488dd
bbe8153
 
 
 
212f3d8
fd0a544
3ec7744
 
 
8727e48
8084825
53c7f91
 
8084825
 
 
53c7f91
 
 
8084825
53c7f91
8f08c01
53c7f91
8084825
 
 
 
 
 
 
 
 
53c7f91
8084825
3ec7744
fcb0ea5
7e3803b
 
 
 
ffd7140
cf309f8
ffd7140
 
856a15a
 
 
81b9dd6
 
ffd7140
 
 
7e3803b
 
bbe8153
 
81b9dd6
 
 
 
bbe8153
 
81b9dd6
bbe8153
81b9dd6
bbe8153
 
 
 
 
 
 
 
 
 
 
cf309f8
bbe8153
 
7e3803b
bbe8153
7e3803b
 
bbe8153
81b9dd6
6d8f6a3
 
bbe8153
 
 
 
 
 
 
 
 
 
 
 
 
 
7e3803b
6d8f6a3
 
 
bbe8153
 
 
 
 
 
 
 
 
 
 
 
 
 
7e3803b
bbe8153
4fceacd
bbe8153
4fceacd
bbe8153
4fceacd
089d664
 
ffd7140
4fceacd
8ca72f6
29224cf
56704ce
c213593
b6488dd
29224cf
b6488dd
 
4555a55
040b02f
b6488dd
 
c213593
 
 
 
 
 
56d6a08
e6f82a5
5bd181a
 
 
2e90b3c
 
 
 
 
 
 
 
 
 
c213593
7a51391
d66afa3
4c8c2c3
ea75628
d66afa3
 
c213593
 
d66afa3
c213593
bbe8153
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e642140
 
23b843d
4555a55
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
import gradio as gr

"""
=====================================================
Optical Flow: Predicting movement with the RAFT model
=====================================================

Optical flow is the task of predicting movement between two images, usually two
consecutive frames of a video. Optical flow models take two images as input, and
predict a flow: the flow indicates the displacement of every single pixel in the
first image, and maps it to its corresponding pixel in the second image. Flows
are (2, H, W)-dimensional tensors, where the first axis corresponds to the
predicted horizontal and vertical displacements.

The following example illustrates how torchvision can be used to predict flows
using our implementation of the RAFT model. We will also see how to convert the
predicted flows to RGB images for visualization.
"""

import cv2
import numpy as np
import os
import sys
import torch
from PIL import Image
import matplotlib.pyplot as plt
import torchvision.transforms.functional as F
from torchvision.io import read_video, read_image
from torchvision.models.optical_flow import Raft_Large_Weights
from torchvision.models.optical_flow import raft_large
from torchvision.io import write_jpeg
import torchvision.transforms as T

import tempfile
from pathlib import Path
from urllib.request import urlretrieve
import tensorflow as tf
from scipy.interpolate import LinearNDInterpolator
from imageio import imread, imwrite
from flowio import readFlowFile

def write_flo(flow, filename):
    """
    Write optical flow in Middlebury .flo format
    
    :param flow: optical flow map
    :param filename: optical flow file path to be saved
    :return: None
    
    from https://github.com/liruoteng/OpticalFlowToolkit/
    
    """
    # forcing conversion to float32 precision
    flow = flow.cpu().data.numpy()
    flow = flow.astype(np.float32)
    f = open(filename, 'wb')
    magic = np.array([202021.25], dtype=np.float32)
    (height, width) = flow.shape[0:2]
    w = np.array([width], dtype=np.int32)
    h = np.array([height], dtype=np.int32)
    magic.tofile(f)
    w.tofile(f)
    h.tofile(f)
    flow.tofile(f)
    f.close()


    
def infer():
    video_url = "https://download.pytorch.org/tutorial/pexelscom_pavel_danilyuk_basketball_hd.mp4"
    video_path = Path(tempfile.mkdtemp()) / "basketball.mp4"
    _ = urlretrieve(video_url, video_path)
   
    frames, _, _ = read_video(str(video_path), output_format="TCHW")
    print(f"FRAME BEFORE stack: {frames[100]}")
    
    input_frame_1 = read_image(str("./frame1.jpg"), ImageReadMode = ImageReadMode.UNCHANGED)
    input_frame_2 = read_image(str("./frame2.jpg"), ImageReadMode = ImageReadMode.UNCHANGED)
    
    img1_batch = torch.stack([frames[100]])
    img2_batch = torch.stack([frames[101]])
    
    print(f"FRAME AFTER stack: {img1_batch}")
    
    weights = Raft_Large_Weights.DEFAULT
    transforms = weights.transforms()


    def preprocess(img1_batch, img2_batch):
        img1_batch = F.resize(img1_batch, size=[520, 960])
        img2_batch = F.resize(img2_batch, size=[520, 960])
        return transforms(img1_batch, img2_batch)


    img1_batch, img2_batch = preprocess(img1_batch, img2_batch)

    print(f"shape = {img1_batch.shape}, dtype = {img1_batch.dtype}")


####################################
# Estimating Optical flow using RAFT
# ----------------------------------
# We will use our RAFT implementation from
# :func:`~torchvision.models.optical_flow.raft_large`, which follows the same
# architecture as the one described in the `original paper <https://arxiv.org/abs/2003.12039>`_.
# We also provide the :func:`~torchvision.models.optical_flow.raft_small` model
# builder, which is smaller and faster to run, sacrificing a bit of accuracy.

    

# If you can, run this example on a GPU, it will be a lot faster.
    device = "cuda" if torch.cuda.is_available() else "cpu"

    model = raft_large(weights=Raft_Large_Weights.DEFAULT, progress=False).to(device)
    model = model.eval()

    list_of_flows = model(img1_batch.to(device), img2_batch.to(device))
    print(f"list_of_flows type = {type(list_of_flows)}")
    print(f"list_of_flows length = {len(list_of_flows)} = number of iterations of the model")

####################################
# The RAFT model outputs lists of predicted flows where each entry is a
# (N, 2, H, W) batch of predicted flows that corresponds to a given "iteration"
# in the model. For more details on the iterative nature of the model, please
# refer to the `original paper <https://arxiv.org/abs/2003.12039>`_. Here, we
# are only interested in the final predicted flows (they are the most acccurate
# ones), so we will just retrieve the last item in the list.
#
# As described above, a flow is a tensor with dimensions (2, H, W) (or (N, 2, H,
# W) for batches of flows) where each entry corresponds to the horizontal and
# vertical displacement of each pixel from the first image to the second image.
# Note that the predicted flows are in "pixel" unit, they are not normalized
# w.r.t. the dimensions of the images.
    predicted_flows = list_of_flows[-1]
    print(f"predicted_flows dtype = {predicted_flows.dtype}")
    print(f"predicted_flows shape = {predicted_flows.shape} = (N, 2, H, W)")
    print(f"predicted_flows min = {predicted_flows.min()}, predicted_flows max = {predicted_flows.max()}")


####################################
# Visualizing predicted flows
# ---------------------------
# Torchvision provides the :func:`~torchvision.utils.flow_to_image` utlity to
# convert a flow into an RGB image. It also supports batches of flows.
# each "direction" in the flow will be mapped to a given RGB color. In the
# images below, pixels with similar colors are assumed by the model to be moving
# in similar directions. The model is properly able to predict the movement of
# the ball and the player. Note in particular the different predicted direction
# of the ball in the first image (going to the left) and in the second image
# (going up).

    from torchvision.utils import flow_to_image

    #flow_imgs = flow_to_image(predicted_flows)

    #print(flow_imgs)

    predicted_flow = list_of_flows[-1][0]
    print(f"predicted flow dtype = {predicted_flow.dtype}")
    print(f"predicted flow shape = {predicted_flow.shape}")
    
    flow_img = flow_to_image(predicted_flow).to("cpu")
    write_jpeg(flow_img, f"predicted_flow.jpg")
    
    flo_file = write_flo(predicted_flow, "flofile.flo")
      
    # define a transform to convert a tensor to PIL image
    transform = T.ToPILImage()
    
    # convert the tensor to PIL image using above transform
    img = transform(frames[101])
    img = img.resize((960, 520))
    # display the PIL image
    #img.show()
    frame2pil = np.array(img.convert('RGB'))
    print(f"frame1pil: {frame2pil}")
    print(f"frame1pil shape: {frame2pil.shape}")
    print(f"frame1pil dtype: {frame2pil.dtype}")
    img.save('raw_frame2.jpg')
    

    numpy_array_flow = predicted_flow.permute(1, 2, 0).detach().cpu().numpy()
    print(f"numpy_array_flow: {numpy_array_flow}")
    print(f"numpy_array_flow shape: {numpy_array_flow.shape}")
    print(f"numpy_array_flow dtype: {numpy_array_flow.dtype}")

    h, w = numpy_array_flow.shape[:2]
    numpy_array_flow = numpy_array_flow.copy()
    numpy_array_flow[:, :, 0] + np.arange(w)
    numpy_array_flow[:, :, 1] + np.arange(h)[:, np.newaxis]
    # print('flow stats', flow.max(), flow.min(), flow.mean())
    # print(flow)
    numpy_array_flow*1.
    # print('flow stats mul', flow.max(), flow.min(), flow.mean())
    # res = cv2.remap(img, flow, None, cv2.INTER_LINEAR)
    res = cv2.remap(frame2pil, numpy_array_flow, None, cv2.INTER_LANCZOS4)
    print(res)
    
    res = Image.fromarray(res)
    res.save('wraped.jpg')

    blend2 = Image.open('frame_input.jpg')
    blend2 = Image.blend(res,blend2,0.5)
    blend2.save("blended2.jpg")
    
    return "done", "predicted_flow.jpg", ["flofile.flo"], 'raw_frame2.jpg', 'wraped.jpg', "blended2.jpg"
####################################
# Bonus: Creating GIFs of predicted flows
# ---------------------------------------
# In the example above we have only shown the predicted flows of 2 pairs of
# frames. A fun way to apply the Optical Flow models is to run the model on an
# entire video, and create a new video from all the predicted flows. Below is a
# snippet that can get you started with this. We comment out the code, because
# this example is being rendered on a machine without a GPU, and it would take
# too long to run it.

# from torchvision.io import write_jpeg
# for i, (img1, img2) in enumerate(zip(frames, frames[1:])):
#     # Note: it would be faster to predict batches of flows instead of individual flows
#     img1, img2 = preprocess(img1, img2)

#     list_of_flows = model(img1.to(device), img2.to(device))
#     predicted_flow = list_of_flows[-1][0]
#     flow_img = flow_to_image(predicted_flow).to("cpu")
#     output_folder = "/tmp/"  # Update this to the folder of your choice
#     write_jpeg(flow_img, output_folder + f"predicted_flow_{i}.jpg")

####################################
# Once the .jpg flow images are saved, you can convert them into a video or a
# GIF using ffmpeg with e.g.:
#
# ffmpeg -f image2 -framerate 30 -i predicted_flow_%d.jpg -loop -1 flow.gif

      
gr.Interface(fn=infer, inputs=[], outputs=[gr.Textbox(), gr.Image(), gr.Files(), gr.Image(), gr.Image(), gr.Image()]).launch()