content: import numpy as np
  import cv2
  
  
  def make_colorwheel():
      '''
      Generates a color wheel for optical flow visualization as presented in:
          Baker et al. "A Database and Evaluation Methodology for Optical Flow" (ICCV, 2007)
          URL: http://vision.middlebury.edu/flow/flowEval-iccv07.pdf
  
      According to the C++ source code of Daniel Scharstein
      According to the Matlab source code of Deqing Sun
      '''
  
      RY = 15
      YG = 6
      GC = 4
      CB = 11
      BM = 13
      MR = 6
  
      ncols = RY + YG + GC + CB + BM + MR
      colorwheel = np.zeros((ncols, 3))
      col = 0
  
      # RY
      colorwheel[0:RY, 0] = 255
      colorwheel[0:RY, 1] = np.floor(255 * np.arange(0, RY) / RY)
      col = col + RY
      # YG
      colorwheel[col:col + YG, 0] = 255 - np.floor(255 * np.arange(0, YG) / YG)
      colorwheel[col:col + YG, 1] = 255
      col = col + YG
      # GC
      colorwheel[col:col + GC, 1] = 255
      colorwheel[col:col + GC, 2] = np.floor(255 * np.arange(0, GC) / GC)
      col = col + GC
      # CB
      colorwheel[col:col + CB, 1] = 255 - np.floor(255 * np.arange(CB) / CB)
      colorwheel[col:col + CB, 2] = 255
      col = col + CB
      # BM
      colorwheel[col:col + BM, 2] = 255
      colorwheel[col:col + BM, 0] = np.floor(255 * np.arange(0, BM) / BM)
      col = col + BM
      # MR
      colorwheel[col:col + MR, 2] = 255 - np.floor(255 * np.arange(MR) / MR)
      colorwheel[col:col + MR, 0] = 255
      return colorwheel
  
  
  def flow_compute_color(u, v, convert_to_bgr=False):
      '''
      Applies the flow color wheel to (possibly clipped) flow components u and v.
  
      According to the C++ source code of Daniel Scharstein
      According to the Matlab source code of Deqing Sun
  
      :param u: np.ndarray, input horizontal flow
      :param v: np.ndarray, input vertical flow
      :param convert_to_bgr: bool, whether to change ordering and output BGR instead of RGB
      :return:
      '''
  
      flow_image = np.zeros((u.shape[0], u.shape[1], 3), np.uint8)
  
      colorwheel = make_colorwheel()  # shape [55x3]
      ncols = colorwheel.shape[0]
  
      rad = np.sqrt(np.square(u) + np.square(v))
      a = np.arctan2(-v, -u) / np.pi
  
      fk = (a + 1) / 2 * (ncols - 1) + 1
      k0 = np.floor(fk).astype(np.int32)
      k0[k0 > 53] = 53
      k1 = k0 + 1
      k1[k1 == ncols] = 1
      f = fk - k0
  
      for i in range(colorwheel.shape[1]):
  
          tmp = colorwheel[:, i]
          col0 = tmp[k0] / 255.0
          col1 = tmp[k1] / 255.0
          col = (1 - f) * col0 + f * col1
  
          idx = (rad <= 1)
          col[idx] = 1 - rad[idx] * (1 - col[idx])
          col[~idx] = col[~idx] * 0.75  # out of range?
  
          # Note the 2-i => BGR instead of RGB
          ch_idx = 2 - i if convert_to_bgr else i
          flow_image[:, :, ch_idx] = np.floor(255 * col)
  
      return flow_image
  
  
  def flow_to_color(flow_uv, clip_flow=None, convert_to_bgr=False):
      '''
      Expects a two dimensional flow image of shape [H,W,2]
  
      According to the C++ source code of Daniel Scharstein
      According to the Matlab source code of Deqing Sun
  
      :param flow_uv: np.ndarray of shape [H,W,2]
      :param clip_flow: float, maximum clipping value for flow
      :return:
      '''
  
      assert flow_uv.ndim == 3, 'input flow must have three dimensions'
      assert flow_uv.shape[2] == 2, 'input flow must have shape [H,W,2]'
  
      if clip_flow is not None:
          flow_uv = np.clip(flow_uv, 0, clip_flow)
  
      u = flow_uv[:, :, 0]
      v = flow_uv[:, :, 1]
  
      rad = np.sqrt(np.square(u) + np.square(v))
      rad_max = np.max(rad)
  
      epsilon = 1e-5
      u = u / (rad_max + epsilon)
      v = v / (rad_max + epsilon)
  
      return flow_compute_color(u, v, convert_to_bgr)
  
  
  def readFlow(name):
      f = open(name, 'rb')
  
      header = f.read(4)
      if header.decode("utf-8") != 'PIEH':
          raise Exception('Flow file header does not contain PIEH')
  
      width = np.fromfile(f, np.int32, 1).squeeze()
      height = np.fromfile(f, np.int32, 1).squeeze()
  
      flow = np.fromfile(f, np.float32, width * height * 2).reshape((height,
                                                                     width, 2))
      f.close()
      return flow.astype(np.float32)
  
  
  def get_warp_label(flow1, flow2, label1, th=50, value=0):
      label2 = np.ones_like(label1, dtype=label1.dtype) * value
      height = flow1.shape[0]
      width = flow1.shape[1]
      flow_t = np.zeros_like(flow1, dtype=flow1.dtype)
  
      grid = np.indices((height, width)).swapaxes(0, 1).swapaxes(1, 2)
      dx = grid[:, :, 0] + flow2[:, :, 1]
      dy = grid[:, :, 1] + flow2[:, :, 0]
      sx = np.floor(dx).astype(int)
      sy = np.floor(dy).astype(int)
      valid = (sx >= 0) & (sx < height - 1) & (sy >= 0) & (sy < width - 1)
  
      sx_mat = np.dstack((sx, sx + 1, sx, sx + 1)).clip(0, height - 1)
      sy_mat = np.dstack((sy, sy, sy + 1, sy + 1)).clip(0, width - 1)
      sxsy_mat = np.abs((1 - np.abs(sx_mat - dx[:, :, np.newaxis])) *
                        (1 - np.abs(sy_mat - dy[:, :, np.newaxis])))
  
      for i in range(4):
          flow_t = flow_t + sxsy_mat[:, :, i][:, :, np.
                                              newaxis] * flow1[sx_mat[:, :, i],
                                                               sy_mat[:, :, i], :]
  
      valid = valid & (np.linalg.norm(
          flow_t[:, :, [1, 0]] + np.dstack((dx, dy)) - grid, axis=2) < th)
  
      flow_t = (flow2 - flow_t) / 2.0
      dx = grid[:, :, 0] + flow_t[:, :, 1]
      dy = grid[:, :, 1] + flow_t[:, :, 0]
  
      valid = valid & (dx >= 0) & (dx < height - 1) & (dy >= 0) & (dy < width - 1)
      label2[valid, :] = label1[dx[valid].round().astype(int), dy[valid].round()
                                .astype(int), :]
      return label2
  
  
  def flow_tf(flow, size):
      flow_shape = flow.shape
      flow_resized = cv2.resize(flow, (size[1], size[0]))
      flow_resized[:, :, 0] *= (float(size[1]) / float(flow_shape[1]))
      flow_resized[:, :, 1] *= (float(size[0]) / float(flow_shape[0]))
  
      return flow_resized