{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Optical Flow example\n", "This notebook presents how to use Dali to calculate optical flow for given sequence of frames." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's start with some handy imports" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "from __future__ import print_function\n", "from __future__ import division\n", "import os.path\n", "import numpy as np\n", "\n", "from nvidia.dali.pipeline import Pipeline\n", "import nvidia.dali.ops as ops\n", "\n", "from matplotlib import pyplot as plt" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Setting metaparameters. \n", "As an example we use [Sintel trailer](https://durian.blender.org/), included in [DALI_extra](https://github.com/NVIDIA/DALI_extra) repository. Feel free to verify against your own video data.\n", "\n", "`DALI_EXTRA_PATH` environment variable should point to the place where data from [DALI extra repository](https://github.com/NVIDIA/DALI_extra) is downloaded. Please make sure that the proper release tag is checked out." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "batch_size = 1\n", "sequence_length = 10\n", "dali_extra_path = os.environ['DALI_EXTRA_PATH']\n", "video_filename = dali_extra_path + \"/db/optical_flow/sintel_trailer/sintel_trailer_short.mp4\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Functions used for Optical flow visualization. \n", "The code comes from [Tomrunia's GitHub](https://github.com/tomrunia/OpticalFlow_Visualization \"OpticalFlow_Visualization\")" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "def make_colorwheel():\n", " '''\n", " Generates a color wheel for optical flow visualization as presented in:\n", " Baker et al. \"A Database and Evaluation Methodology for Optical Flow\" (ICCV, 2007)\n", " URL: http://vision.middlebury.edu/flow/flowEval-iccv07.pdf\n", " According to the C++ source code of Daniel Scharstein\n", " According to the Matlab source code of Deqing Sun\n", " '''\n", "\n", " RY = 15\n", " YG = 6\n", " GC = 4\n", " CB = 11\n", " BM = 13\n", " MR = 6\n", "\n", " ncols = RY + YG + GC + CB + BM + MR\n", " colorwheel = np.zeros((ncols, 3))\n", " col = 0\n", "\n", " # RY\n", " colorwheel[0:RY, 0] = 255\n", " colorwheel[0:RY, 1] = np.floor(255 * np.arange(0, RY) / RY)\n", " col = col + RY\n", " # YG\n", " colorwheel[col:col + YG, 0] = 255 - np.floor(255 * np.arange(0, YG) / YG)\n", " colorwheel[col:col + YG, 1] = 255\n", " col = col + YG\n", " # GC\n", " colorwheel[col:col + GC, 1] = 255\n", " colorwheel[col:col + GC, 2] = np.floor(255 * np.arange(0, GC) / GC)\n", " col = col + GC\n", " # CB\n", " colorwheel[col:col + CB, 1] = 255 - np.floor(255 * np.arange(CB) / CB)\n", " colorwheel[col:col + CB, 2] = 255\n", " col = col + CB\n", " # BM\n", " colorwheel[col:col + BM, 2] = 255\n", " colorwheel[col:col + BM, 0] = np.floor(255 * np.arange(0, BM) / BM)\n", " col = col + BM\n", " # MR\n", " colorwheel[col:col + MR, 2] = 255 - np.floor(255 * np.arange(MR) / MR)\n", " colorwheel[col:col + MR, 0] = 255\n", " return colorwheel\n", "\n", "\n", "def flow_compute_color(u, v, convert_to_bgr=False):\n", " '''\n", " Applies the flow color wheel to (possibly clipped) flow components u and v.\n", " According to the C++ source code of Daniel Scharstein\n", " According to the Matlab source code of Deqing Sun\n", " :param u: np.ndarray, input horizontal flow\n", " :param v: np.ndarray, input vertical flow\n", " :param convert_to_bgr: bool, whether to change ordering and output BGR instead of RGB\n", " :return:\n", " '''\n", "\n", " flow_image = np.zeros((u.shape[0], u.shape[1], 3), np.uint8)\n", "\n", " colorwheel = make_colorwheel() # shape [55x3]\n", " ncols = colorwheel.shape[0]\n", "\n", " rad = np.sqrt(np.square(u) + np.square(v))\n", " a = np.arctan2(-v, -u) / np.pi\n", "\n", " fk = (a + 1) / 2 * (ncols - 1) + 1\n", " k0 = np.floor(fk).astype(np.int32)\n", " k1 = k0 + 1\n", " k1[k1 == ncols] = 1\n", " f = fk - k0\n", "\n", " for i in range(colorwheel.shape[1]):\n", " tmp = colorwheel[:, i]\n", " col0 = tmp[k0] / 255.0\n", " col1 = tmp[k1] / 255.0\n", " col = (1 - f) * col0 + f * col1\n", "\n", " idx = (rad <= 1)\n", " col[idx] = 1 - rad[idx] * (1 - col[idx])\n", " col[~idx] = col[~idx] * 0.75 # out of range?\n", "\n", " # Note the 2-i => BGR instead of RGB\n", " ch_idx = 2 - i if convert_to_bgr else i\n", " flow_image[:, :, ch_idx] = np.floor(255 * col)\n", "\n", " return flow_image\n", "\n", "\n", "def flow_to_color(flow_uv, clip_flow=None, convert_to_bgr=False):\n", " '''\n", " Expects a two dimensional flow image of shape [H,W,2]\n", " According to the C++ source code of Daniel Scharstein\n", " According to the Matlab source code of Deqing Sun\n", " :param flow_uv: np.ndarray of shape [H,W,2]\n", " :param clip_flow: float, maximum clipping value for flow\n", " :return:\n", " '''\n", "\n", " assert flow_uv.ndim == 3, 'input flow must have three dimensions'\n", " assert flow_uv.shape[2] == 2, 'input flow must have shape [H,W,2]'\n", "\n", " if clip_flow is not None:\n", " flow_uv = np.clip(flow_uv, 0, clip_flow)\n", "\n", " u = flow_uv[:, :, 0]\n", " v = flow_uv[:, :, 1]\n", "\n", " rad = np.sqrt(np.square(u) + np.square(v))\n", " rad_max = np.max(rad)\n", "\n", " epsilon = 1e-5\n", " u = u / (rad_max + epsilon)\n", " v = v / (rad_max + epsilon)\n", "\n", " return flow_compute_color(u, v, convert_to_bgr)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Using Dali\n", "### Define the Pipeline. \n", "For advanced usage, refer to SequenceReader and VideoReader docs." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "class OFPipeline(Pipeline):\n", " def __init__(self, batch_size, num_threads, device_id):\n", " super(OFPipeline, self).__init__(batch_size, num_threads, device_id, seed=16)\n", "\n", " self.input = ops.VideoReader(device=\"gpu\", filenames=video_filename, sequence_length=sequence_length)\n", " self.of_op = ops.OpticalFlow(device=\"gpu\", output_format=4)\n", "\n", " def define_graph(self):\n", " seq = self.input(name=\"Reader\")\n", " of = self.of_op(seq.gpu())\n", " return of" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Build and run DALI Pipeline." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(1, 10, 180, 320, 2)\n" ] } ], "source": [ "pipe = OFPipeline(batch_size=batch_size, num_threads=1, device_id=0)\n", "pipe.build()\n", "pipe_out = pipe.run()\n", "flow_vector = pipe_out[0].as_cpu().as_array()\n", "print(flow_vector.shape)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Above you can see the shape of calculated `flow_vector` (in NFHWC format). It contains 2 channels: flow vector in `x` axis and flow vector in `y` axis. Output resolution is determined by `output_format` option passed to `OpticalFlow` operator: for `output_format = 4`, 4x4 grid is used for flow calculation, thus resolution in every dimension being 4 times smaller, than resolution of the input image.\n", "\n", "### Visualize results" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "of_result = flow_to_color(flow_vector[0][int(sequence_length/2)])\n", "plt.imshow(of_result)" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.9" } }, "nbformat": 4, "nbformat_minor": 1 }