{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import pandas as pd\n",
    "import cv2\n",
    "import matplotlib.pyplot as plt\n",
    "import os\n",
    "from azure.storage.blob import ContainerClient\n",
    "import io\n",
    "import time\n",
    "from PIL import Image\n",
    "import datetime"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "523\n"
     ]
    }
   ],
   "source": [
    "file_path_color_left = \"data/00\\image_left/\"\n",
    "file_path_color_right = \"data/00\\image_right/\"\n",
    "\n",
    "left_images = os.listdir(file_path_color_left)\n",
    "right_images = os.listdir(file_path_color_right)\n",
    "\n",
    "print(len(left_images))\n",
    "# plt.figure(figsize=(12,4))\n",
    "# plt.imshow(cv2.imread(file_path_color_left + left_images[165],0)) \n",
    "#turning it into greyscale because we don't really need color unless we're interested in matching moving objects/features. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [],
   "source": [
    "def pixel_coord_np(height,width):\n",
    "    \"\"\"\n",
    "    Pixel in homogenous coordinate\n",
    "    Returns:\n",
    "        Pixel coordinate:       [3, width * height]\n",
    "    \"\"\"\n",
    "    x = np.linspace(0, width - 1, width).astype(np.float32)\n",
    "    y = np.linspace(0, height - 1, height).astype(np.float32)\n",
    "    [x, y] = np.meshgrid(x, y)\n",
    "    return np.vstack((x.flatten(), y.flatten(), np.ones_like(x.flatten())))\n",
    "\n",
    "\n",
    "def intrinsic_from_fov(height, width, fov=90):\n",
    "    \"\"\"\n",
    "    Basic Pinhole Camera Model\n",
    "    intrinsic params from fov and sensor width and height in pixels\n",
    "    Returns:\n",
    "        K:      [4, 4]\n",
    "    \"\"\"\n",
    "    px, py = (width / 2, height / 2)\n",
    "    hfov = fov / 360. * 2. * np.pi\n",
    "    fx = width / (2. * np.tan(hfov / 2.))\n",
    "\n",
    "    vfov = 2. * np.arctan(np.tan(hfov / 2) * height / width)\n",
    "    fy = height / (2. * np.tan(vfov / 2.))\n",
    "\n",
    "    return np.array([[fx, 0, px, 0.],\n",
    "                     [0, fy, py, 0.],\n",
    "                     [0, 0, 1., 0.],\n",
    "                     [0., 0., 0., 1.]])\n",
    "\n",
    "def quaternion_rotation_matrix(Q):\n",
    "    \"\"\"\n",
    "    Covert a quaternion into a full projection matrix.\n",
    " \n",
    "    Input\n",
    "    :param Q: A 7 element array representing translation and the quaternion (q0,q1,q2,q3) \n",
    " \n",
    "    Output\n",
    "    :return: A 3x4 element matrix representing the full projection matrix. \n",
    "             This projection matrix converts a point in the local reference \n",
    "             frame to a point in the global reference frame.\n",
    "    \"\"\"\n",
    "    # Extract the values from Q\n",
    "    t0 = Q[0]\n",
    "    t1 = Q[1]\n",
    "    t2 = Q[2]\n",
    "    q0 = Q[3]\n",
    "    q1 = Q[4]\n",
    "    q2 = Q[5]\n",
    "    q3 = Q[6]\n",
    "     \n",
    "    # First row of the rotation matrix\n",
    "    r00 = 2 * (q0 * q0 + q1 * q1) - 1\n",
    "    r01 = 2 * (q1 * q2 - q0 * q3)\n",
    "    r02 = 2 * (q1 * q3 + q0 * q2)\n",
    "     \n",
    "    # Second row of the rotation matrix\n",
    "    r10 = 2 * (q1 * q2 + q0 * q3)\n",
    "    r11 = 2 * (q0 * q0 + q2 * q2) - 1\n",
    "    r12 = 2 * (q2 * q3 - q0 * q1)\n",
    "     \n",
    "    # Third row of the rotation matrix\n",
    "    r20 = 2 * (q1 * q3 - q0 * q2)\n",
    "    r21 = 2 * (q2 * q3 + q0 * q1)\n",
    "    r22 = 2 * (q0 * q0 + q3 * q3) - 1\n",
    "     \n",
    "    # 3x4 projection matrix\n",
    "    pro_matrix = np.array([[r00, r01, r02, t0],\n",
    "                           [r10, r11, r12, t1],\n",
    "                           [r20, r21, r22, t2]])\n",
    "                            \n",
    "    return pro_matrix"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "523\n"
     ]
    }
   ],
   "source": [
    "class Dataset_Handler():\n",
    "    def __init__(self, sequence, lidar=False, progress_bar=True, low_memory=True):\n",
    "        \n",
    "        \n",
    "        # This will tell our odometry function if handler contains lidar info\n",
    "        self.lidar = lidar\n",
    "        # This will tell odometry functin how to access data from this object\n",
    "        self.low_memory = low_memory\n",
    "        \n",
    "        # Set file paths and get ground truth poses\n",
    "        self.seq_dir = \"data\\{}/\".format(sequence)\n",
    "        self.poses_dir = \"data\\{}.csv\".format(sequence)\n",
    "        self.depth_dir = \"data\\{}/\".format(sequence)\n",
    "\n",
    "        poses = pd.read_csv(self.poses_dir, header=None)\n",
    "        \n",
    "        # Get names of files to iterate through\n",
    "        self.left_image_files = os.listdir(self.seq_dir + 'image_left')\n",
    "        self.right_image_files = os.listdir(self.seq_dir + 'image_right')\n",
    "        self.left_depth_files = os.listdir(self.depth_dir + 'depth_left')\n",
    "        self.right_depth_files = os.listdir(self.depth_dir + 'depth_right')\n",
    "        \n",
    "        # self.velodyne_files = os.listdir(self.seq_dir + 'flow')\n",
    "        self.num_frames = len(self.left_image_files)\n",
    "        print(self.num_frames)\n",
    "        # self.lidar_path = self.seq_dir + 'flow/'\n",
    "        self.first_image_left = cv2.imread(self.seq_dir + 'image_left/' \n",
    "                                               + self.left_image_files[0])\n",
    "        height = 480\n",
    "        width = 640\n",
    "        K = intrinsic_from_fov(height,width)\n",
    "        self.P0 = np.array(K[:3,:4])\n",
    "        self.P1 = np.array(K[:3,:4])\n",
    "        \n",
    "        \n",
    "        # Get calibration details for scene\n",
    "        # calib = pd.read_csv(self.seq_dir + 'calib.txt', delimiter=' ', header=None, index_col=0)\n",
    "        # self.P0 = np.array(calib.loc['P0:']).reshape((3,4))\n",
    "        # self.P1 = np.array(calib.loc['P1:']).reshape((3,4))\n",
    "        # self.P2 = np.array(calib.loc['P2:']).reshape((3,4)) #RGB cams\n",
    "        # self.P3 = np.array(calib.loc['P3:']).reshape((3,4)) #RGB cams\n",
    "        # This is the transformation matrix for LIDAR\n",
    "        # self.Tr = np.array(calib.loc['Tr:']).reshape((3,4))\n",
    "        \n",
    "        # Get times and ground truth poses\n",
    "        self.times = np.array(pd.read_csv(self.seq_dir + 'times.txt', \n",
    "                                          delimiter=' ', \n",
    "                                          header=None))\n",
    "        self.gt = np.zeros((len(poses), 3, 4))\n",
    "        for i in range(len(poses)):\n",
    "            self.gt[i] = np.array(quaternion_rotation_matrix(poses.iloc[i])).reshape((3, 4))\n",
    "        \n",
    "        # Get images and lidar loaded\n",
    "        if self.low_memory:\n",
    "            # Will use generators to provide data sequentially to save RAM\n",
    "            # Use class method to set up generators\n",
    "            self.reset_frames()\n",
    "            # Store original frame to memory for testing functions\n",
    "            self.first_image_left = cv2.imread(self.seq_dir + 'image_left/' \n",
    "                                               + self.left_image_files[0])\n",
    "            self.first_image_right = cv2.imread(self.seq_dir + 'image_right/' \n",
    "                                               + self.right_image_files[0])\n",
    "            self.second_image_left = cv2.imread(self.seq_dir + 'image_left/' \n",
    "                                               + self.left_image_files[1])\n",
    "            self.first_depth_left = np.load(self.depth_dir + 'depth_left/'\n",
    "                                                + self.left_depth_files[0])\n",
    "            self.first_depth_right = np.load(self.depth_dir + 'depth_right/'\n",
    "                                                + self.right_depth_files[0])\n",
    "            self.second_depth_left = np.load(self.depth_dir + 'depth_left/'\n",
    "                                                + self.left_depth_files[1])\n",
    "                                                \n",
    "            if self.lidar:\n",
    "                self.first_pointcloud = np.fromfile(self.lidar_path + self.velodyne_files[0],\n",
    "                                                    dtype=np.float32, \n",
    "                                                    count=-1).reshape((-1, 4))\n",
    "            self.imheight = height\n",
    "            self.imwidth = width\n",
    "            \n",
    "        else:\n",
    "            # If RAM is not a concern (>32GB), pass low_memory=False\n",
    "            if progress_bar:\n",
    "                import progressbar\n",
    "                bar = progressbar.ProgressBar(max_value=self.num_frames)\n",
    "            self.images_left = []\n",
    "            self.images_right = []\n",
    "            self.depths_left = []\n",
    "            self.depths_right =[]\n",
    "            self.pointclouds = []\n",
    "            for i, name_left in enumerate(self.left_image_files):\n",
    "                name_right = self.right_image_files[i]\n",
    "                d_left = self.left_depth_files\n",
    "                d_right = self.right_depth_files\n",
    "                self.images_left.append(cv2.imread(self.seq_dir + 'image_left/' + name_left))\n",
    "                self.images_right.append(cv2.imread(self.seq_dir + 'image_right/' + name_right))\n",
    "                self.depths_left.append(np.load(self.depth_dir + 'depth_left/' + d_left))\n",
    "                self.depths_right.append(np.load(self.depth_dir + 'depth_right/' + d_right))\n",
    "                if self.lidar:\n",
    "                    pointcloud = np.fromfile(self.lidar_path + self.velodyne_files[i], \n",
    "                                             dtype=np.float32, \n",
    "                                             count=-1).reshape([-1,4])\n",
    "                    self.pointclouds.append(pointcloud)\n",
    "                if progress_bar:\n",
    "                    bar.update(i+1)\n",
    "                \n",
    "            self.imheight = self.images_left[0].shape[0]\n",
    "            self.imwidth = self.images_left[0].shape[1]\n",
    "            # Keep consistent instance variable names as when using low_memory\n",
    "            self.first_image_left = self.images_left[0]\n",
    "            self.first_image_right = self.images_right[0]\n",
    "            self.second_image_left = self.images_left[1]\n",
    "            if self.lidar:\n",
    "                self.first_pointcloud = self.pointclouds[0]\n",
    "            \n",
    "    def reset_frames(self):\n",
    "        # Resets all generators to the first frame of the sequence\n",
    "        self.images_left = (cv2.imread(self.seq_dir + 'image_left/' + name_left)\n",
    "                            for name_left in self.left_image_files)\n",
    "        self.images_right = (cv2.imread(self.seq_dir + 'image_right/' + name_right)\n",
    "                            for name_right in self.right_image_files)\n",
    "        self.depths_left = (np.load(self.depth_dir+'depth_left/' + d_left)\n",
    "                            for d_left in self.left_depth_files)\n",
    "        self.depths_right = (np.load(self.depth_dir+'depth_right/' + d_right)\n",
    "                            for d_right in self.right_depth_files)                    \n",
    "        if self.lidar:\n",
    "            self.pointclouds = (np.fromfile(self.lidar_path + velodyne_file, \n",
    "                                            dtype=np.float32, \n",
    "                                            count=-1).reshape((-1, 4))\n",
    "                                for velodyne_file in self.velodyne_files)\n",
    "        pass\n",
    "handler = Dataset_Handler(\"00\")\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [],
   "source": [
    "def compute_left_disparity_map(left_image, right_image, matcher = 'bm', rgb = True, verbose = True):\n",
    "    '''\n",
    "    Takes a left and right pair of images to computes the disparity map for the left\n",
    "    image. \n",
    "    \n",
    "    Arguments:\n",
    "    img_left -- image from left camera\n",
    "    img_right -- image from right camera\n",
    "    \n",
    "    Optional Arguments:\n",
    "    matcher -- (str) can be 'bm' for StereoBM or 'sgbm' for StereoSGBM matching.\n",
    "    rgb -- (bool) set to True if passing RGB images as input. \n",
    "    verbose -- (bool) set to True to report matching type and time to compute\n",
    "    \n",
    "    Returns:\n",
    "    disp_left -- disparity map for the left camera image\n",
    "    \n",
    "    '''\n",
    "    sad_window = 6\n",
    "    num_disparities = sad_window * 16\n",
    "    block_size = 11\n",
    "    matcher_name = matcher\n",
    "\n",
    "    if matcher_name == 'bm':\n",
    "        matcher = cv2.StereoBM_create(numDisparities=num_disparities,\n",
    "                                        blockSize=block_size)\n",
    "                                        \n",
    "    elif matcher_name == 'sgbm':\n",
    "        matcher = cv2.StereoSGBM_create(numDisparities=num_disparities,\n",
    "                                        blockSize=block_size,\n",
    "                                        P1 = 8*3*sad_window**2,\n",
    "                                        P2 = 32*3*sad_window**2,\n",
    "                                        mode = cv2.STEREO_SGBM_MODE_SGBM_3WAY)\n",
    "    if rgb:\n",
    "        left_image = cv2.cvtColor(left_image, cv2.COLOR_BGR2GRAY)\n",
    "        right_image = cv2.cvtColor(right_image, cv2.COLOR_BGR2GRAY)\n",
    "    \n",
    "    start = datetime.datetime.now()\n",
    "    disp_left = matcher.compute(left_image, right_image).astype(np.float32)/16\n",
    "    end = datetime.datetime.now()\n",
    "\n",
    "    if verbose:\n",
    "        print(f'Time to compute disparity map using Stereo{matcher_name.upper()}:', end-start)\n",
    "    \n",
    "    return disp_left\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Time to compute disparity map using StereoBM: 0:00:00.009997\n"
     ]
    }
   ],
   "source": [
    "first_left = cv2.imread(file_path_color_left + left_images[167])\n",
    "first_right = cv2.imread(file_path_color_right + right_images[167])\n",
    "\n",
    "disp = compute_left_disparity_map(left_image=first_left, right_image=first_right,\n",
    "                                    matcher = 'bm', verbose = True)\n",
    "\n",
    "plt.figure(figsize=(15,15))\n",
    "plt.imshow(disp);"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [],
   "source": [
    "def decompose_projection_matrix(p):\n",
    "    '''\n",
    "    Shortcut to use cv2.decomposeProjectionMatrix(), which only returns k, r, t, and divides\n",
    "    t by the scale, then returns it as a vector with shape (3,) (non-homogeneous)\n",
    "    \n",
    "    Arguments:\n",
    "    p -- projection matrix to be decomposed\n",
    "    \n",
    "    Returns:\n",
    "    k, r, t -- intrinsic matrix, rotation matrix, and 3D translation vector\n",
    "    \n",
    "    '''\n",
    "    k, r, t, _, _, _, _ = cv2.decomposeProjectionMatrix(p)\n",
    "    t = (t / t[3])[:3]\n",
    "    \n",
    "    return k, r, t\n",
    "def calc_depth_map(disp_left, k_left, t_left, t_right, rectified=True):\n",
    "    '''\n",
    "    Assuming we don't have access to the depth map...\n",
    "    \n",
    "    Calculate depth map using a disparity map, intrinsic camera matrix, and translation vectors\n",
    "    from camera extrinsic matrices (to calculate baseline). Note that default behavior is for\n",
    "    rectified projection matrix for right camera. If using a regular projection matrix, pass\n",
    "    rectified=False to avoid issues.\n",
    "\n",
    "    \n",
    "    \n",
    "    Arguments:\n",
    "    disp_left -- disparity map of left camera\n",
    "    k_left -- intrinsic matrix for left camera\n",
    "    t_left -- translation vector for left camera\n",
    "    t_right -- translation vector for right camera\n",
    "    \n",
    "    Optional Arguments:\n",
    "    rectified -- (bool) set to False if t_right is not from rectified projection matrix\n",
    "    \n",
    "    Returns:\n",
    "    depth_map -- calculated depth map for left camera\n",
    "    \n",
    "    '''\n",
    "    # Get focal length of x axis for left camera\n",
    "    f = k_left[0][0]\n",
    "    \n",
    "    # Calculate baseline of stereo pair\n",
    "    if rectified:\n",
    "        b = t_right[0] - t_left[0] \n",
    "    else:\n",
    "        b = t_left[0] - t_right[0]\n",
    "        \n",
    "    # Avoid instability and division by zero\n",
    "    disp_left[disp_left == 0.0] = 0.1\n",
    "    disp_left[disp_left == -1.0] = 0.1\n",
    "    \n",
    "    # Make empty depth map then fill with depth\n",
    "    depth_map = np.ones(disp_left.shape)\n",
    "    depth_map = f * b / disp_left\n",
    "    \n",
    "    return depth_map"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[3.1132812, 3.1132812, 3.1152344, ..., 3.9003906, 3.9023438,\n",
       "        3.9042969],\n",
       "       [3.1171875, 3.1191406, 3.1191406, ..., 3.9082031, 3.9101562,\n",
       "        3.9121094],\n",
       "       [3.1230469, 3.1230469, 3.125    , ..., 3.9160156, 3.9179688,\n",
       "        3.9199219],\n",
       "       ...,\n",
       "       [2.0664062, 2.0664062, 2.0683594, ..., 3.1738281, 3.2265625,\n",
       "        3.2285156],\n",
       "       [2.0625   , 2.0644531, 2.0644531, ..., 3.1679688, 3.21875  ,\n",
       "        3.2207031],\n",
       "       [2.0585938, 2.0605469, 2.0605469, ..., 3.2070312, 3.2089844,\n",
       "        3.2128906]], dtype=float32)"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "handler.first_depth_left"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [],
   "source": [
    "def pointcloud2image(pointcloud, imheight, imwidth, Tr, P0):\n",
    "    '''\n",
    "    ...\n",
    "    Takes a pointcloud of shape Nx4 and projects it onto an image plane, first transforming\n",
    "    the X, Y, Z coordinates of points to the camera frame with tranformation matrix Tr, then\n",
    "    projecting them using camera projection matrix P0.\n",
    "    \n",
    "    Arguments:\n",
    "    pointcloud -- array of shape Nx4 containing (X, Y, Z, reflectivity)\n",
    "    imheight -- height (in pixels) of image plane\n",
    "    imwidth -- width (in pixels) of image plane\n",
    "    Tr -- 3x4 transformation matrix between lidar (X, Y, Z, 1) homogeneous and camera (X, Y, Z)\n",
    "    P0 -- projection matrix of camera (should have identity transformation if Tr used)\n",
    "    \n",
    "    Returns:\n",
    "    render -- a (imheight x imwidth) array containing depth (Z) information from lidar scan\n",
    "    \n",
    "    '''\n",
    "\n",
    "    pointcloud = pointcloud[pointcloud[:, 0] > 0]\n",
    "    \n",
    "\n",
    "    pointcloud = np.hstack([pointcloud[:, :3], np.ones(pointcloud.shape[0]).reshape((-1,1))])\n",
    "    \n",
    "    # Transform pointcloud into camera coordinate frame\n",
    "    cam_xyz = Tr.dot(pointcloud.T)\n",
    "    \n",
    "    # Ignore any points behind the camera (probably redundant but just in case)\n",
    "    cam_xyz = cam_xyz[:, cam_xyz[2] > 0]\n",
    "    \n",
    "    # Extract the Z row which is the depth from camera\n",
    "    depth = cam_xyz[2].copy()\n",
    "    \n",
    "    # Project coordinates in camera frame to flat plane at Z=1 by dividing by Z\n",
    "    cam_xyz /= cam_xyz[2]\n",
    "    \n",
    "    # Add row of ones to make our 3D coordinates on plane homogeneous for dotting with P0\n",
    "    cam_xyz = np.vstack([cam_xyz, np.ones(cam_xyz.shape[1])])\n",
    "    \n",
    "    # Get pixel coordinates of X, Y, Z points in camera coordinate frame\n",
    "    projection = P0.dot(cam_xyz)\n",
    "    #projection = (projection / projection[2])\n",
    "    \n",
    "    # Turn pixels into integers for indexing\n",
    "    pixel_coordinates = np.round(projection.T, 0)[:, :2].astype('int')\n",
    "    #pixel_coordinates = np.array(pixel_coordinates)\n",
    "    \n",
    "    # Limit pixel coordinates considered to those that fit on the image plane\n",
    "    indices = np.where((pixel_coordinates[:, 0] < imwidth)\n",
    "                       & (pixel_coordinates[:, 0] >= 0)\n",
    "                       & (pixel_coordinates[:, 1] < imheight)\n",
    "                       & (pixel_coordinates[:, 1] >= 0)\n",
    "                      )\n",
    "    pixel_coordinates = pixel_coordinates[indices]\n",
    "    depth = depth[indices]\n",
    "    \n",
    "    # Establish empty render image, then fill with the depths of each point\n",
    "    render = np.zeros((imheight, imwidth))\n",
    "    for j, (u, v) in enumerate(pixel_coordinates):\n",
    "        if u >= imwidth or u < 0:\n",
    "            continue\n",
    "        if v >= imheight or v < 0:\n",
    "            continue\n",
    "        render[v, u] = depth[j]\n",
    "    # Fill zero values with large distance so they will be ignored. (Using same max value)\n",
    "\n",
    "\n",
    "    \n",
    "    return render"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [],
   "source": [
    "def stereo_2_depth(img_left, img_right, P0, P1, matcher='bm', rgb=True, verbose=False, \n",
    "                   rectified=True):\n",
    "    '''\n",
    "    Takes stereo pair of images and returns a depth map for the left camera. If your projection\n",
    "    matrices are not rectified, set rectified=False.\n",
    "    \n",
    "    Arguments:\n",
    "    img_left -- image of left camera\n",
    "    img_right -- image of right camera\n",
    "    P0 -- Projection matrix for the left camera\n",
    "    P1 -- Projection matrix for the right camera\n",
    "    \n",
    "    Optional Arguments:\n",
    "    matcher -- (str) can be 'bm' for StereoBM or 'sgbm' for StereoSGBM\n",
    "    rgb -- (bool) set to True if images passed are RGB. Default is False\n",
    "    verbose -- (bool) set to True to report computation time and method\n",
    "    rectified -- (bool) set to False if P1 not rectified to P0. Default is True\n",
    "    \n",
    "    Returns:\n",
    "    depth -- depth map for left camera\n",
    "    \n",
    "    '''\n",
    "    # Compute disparity map\n",
    "    disp = compute_left_disparity_map(img_left, \n",
    "                                      img_right, \n",
    "                                      matcher=matcher, \n",
    "                                      rgb=rgb, \n",
    "                                      verbose=verbose)\n",
    "    # Decompose projection matrices\n",
    "    k_left, r_left, t_left = decompose_projection_matrix(P0)\n",
    "    k_right, r_right, t_right = decompose_projection_matrix(P1)\n",
    "    # Calculate depth map for left camera\n",
    "    depth = calc_depth_map(disp, k_left, t_left, t_right)\n",
    "    \n",
    "    return depth"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [],
   "source": [
    "def extract_features(image, detector='sift', mask=None):\n",
    "    \"\"\"\n",
    "    Find keypoints and descriptors for the image\n",
    "\n",
    "    Arguments:\n",
    "    image -- a grayscale image\n",
    "\n",
    "    Returns:\n",
    "    kp -- list of the extracted keypoints (features) in an image\n",
    "    des -- list of the keypoint descriptors in an image\n",
    "    \"\"\"\n",
    "    if detector == 'sift':\n",
    "        det = cv2.SIFT_create()\n",
    "    elif detector == 'orb':\n",
    "        det = cv2.ORB_create()\n",
    "    elif detector == 'surf':\n",
    "        det = cv2.xfeatures2d.SURF_create()\n",
    "        \n",
    "    kp, des = det.detectAndCompute(image, mask)\n",
    "    \n",
    "    return kp, des"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [],
   "source": [
    "def match_features(des1, des2, matching='BF', detector='sift', sort=True, k=2):\n",
    "    \"\"\"\n",
    "    Match features from two images\n",
    "\n",
    "    Arguments:\n",
    "    des1 -- list of the keypoint descriptors in the first image\n",
    "    des2 -- list of the keypoint descriptors in the second image\n",
    "    matching -- (str) can be 'BF' for Brute Force or 'FLANN'\n",
    "    detector -- (str) can be 'sift or 'orb'. Default is 'sift'\n",
    "    sort -- (bool) whether to sort matches by distance. Default is True\n",
    "    k -- (int) number of neighbors to match to each feature.\n",
    "\n",
    "    Returns:\n",
    "    matches -- list of matched features from two images. Each match[i] is k or less matches for \n",
    "               the same query descriptor\n",
    "    \"\"\"\n",
    "    if matching == 'BF':\n",
    "        if detector == 'sift':\n",
    "            matcher = cv2.BFMatcher_create(cv2.NORM_L2, crossCheck=False)\n",
    "        elif detector == 'orb':\n",
    "            matcher = cv2.BFMatcher_create(cv2.NORM_HAMMING2, crossCheck=False)\n",
    "        matches = matcher.knnMatch(des1, des2, k=k)\n",
    "    elif matching == 'FLANN':\n",
    "        FLANN_INDEX_KDTREE = 1\n",
    "        index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees=5)\n",
    "        search_params = dict(checks=50)\n",
    "        matcher = cv2.FlannBasedMatcher(index_params, search_params)\n",
    "        matches = matcher.knnMatch(des1, des2, k=k)\n",
    "    \n",
    "    if sort:\n",
    "        matches = sorted(matches, key = lambda x:x[0].distance)\n",
    "\n",
    "    return matches"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [],
   "source": [
    "def visualize_matches(image1, kp1, image2, kp2, match):\n",
    "    \"\"\"\n",
    "    Visualize corresponding matches in two images\n",
    "\n",
    "    Arguments:\n",
    "    image1 -- the first image in a matched image pair\n",
    "    kp1 -- list of the keypoints in the first image\n",
    "    image2 -- the second image in a matched image pair\n",
    "    kp2 -- list of the keypoints in the second image\n",
    "    match -- list of matched features from the pair of images\n",
    "\n",
    "    Returns:\n",
    "    image_matches -- an image showing the corresponding matches on both image1 and image2 or None if you don't use this function\n",
    "    \"\"\"\n",
    "    image_matches = cv2.drawMatches(image1, kp1, image2, kp2, match, None, flags=2)\n",
    "    plt.figure(figsize=(16, 6), dpi=100)\n",
    "    plt.imshow(image_matches)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [],
   "source": [
    "def filter_matches_distance(matches, dist_threshold):\n",
    "    \"\"\"\n",
    "    Filter matched features from two images by distance between the best matches\n",
    "\n",
    "    Arguments:\n",
    "    match -- list of matched features from two images\n",
    "    dist_threshold -- maximum allowed relative distance between the best matches, (0.0, 1.0) \n",
    "\n",
    "    Returns:\n",
    "    filtered_match -- list of good matches, satisfying the distance threshold\n",
    "    \"\"\"\n",
    "    filtered_match = []\n",
    "    for m, n in matches:\n",
    "        if m.distance <= dist_threshold*n.distance:\n",
    "            filtered_match.append(m)\n",
    "\n",
    "    return filtered_match"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [],
   "source": [
    "def estimate_motion(match, kp1, kp2, k, depth1=None, max_depth=3000):\n",
    "    \"\"\"\n",
    "    Estimate camera motion from a pair of subsequent image frames\n",
    "\n",
    "    Arguments:\n",
    "    match -- list of matched features from the pair of images\n",
    "    kp1 -- list of the keypoints in the first image\n",
    "    kp2 -- list of the keypoints in the second image\n",
    "    k -- camera intrinsic calibration matrix \n",
    "    \n",
    "    Optional arguments:\n",
    "    depth1 -- Depth map of the first frame. Set to None to use Essential Matrix decomposition\n",
    "    max_depth -- Threshold of depth to ignore matched features. 3000 is default\n",
    "\n",
    "    Returns:\n",
    "    rmat -- estimated 3x3 rotation matrix\n",
    "    tvec -- estimated 3x1 translation vector\n",
    "    image1_points -- matched feature pixel coordinates in the first image. \n",
    "                     image1_points[i] = [u, v] -> pixel coordinates of i-th match\n",
    "    image2_points -- matched feature pixel coordinates in the second image. \n",
    "                     image2_points[i] = [u, v] -> pixel coordinates of i-th match\n",
    "               \n",
    "    \"\"\"\n",
    "    rmat = np.eye(3)\n",
    "    tvec = np.zeros((3, 1))\n",
    "    \n",
    "    image1_points = np.float32([kp1[m.queryIdx].pt for m in match])\n",
    "    image2_points = np.float32([kp2[m.trainIdx].pt for m in match])\n",
    "\n",
    "   \n",
    "    # if depth1 is not None:\n",
    "    cx = k[0, 2]\n",
    "    cy = k[1, 2]\n",
    "    fx = k[0, 0]\n",
    "    fy = k[1, 1]\n",
    "    object_points = np.zeros((0, 3))\n",
    "    delete = []\n",
    "    \n",
    "    # Extract depth information of query image at match points and build 3D positions\n",
    "    for i, (u, v) in enumerate(image1_points):\n",
    "        z = depth1[int(v), int(u)]\n",
    "        \n",
    "\n",
    "        if z > max_depth:\n",
    "            delete.append(i)\n",
    "            continue\n",
    "            \n",
    "        # Use arithmetic to extract x and y (faster than using inverse of k)\n",
    "        x = z*(u-cx)/fx\n",
    "        y = z*(v-cy)/fy\n",
    "\n",
    "        object_points = np.vstack([object_points, np.array([x, y, z])])\n",
    "\n",
    "        # Equivalent math with dot product w/ inverse of k matrix, but SLOWER (see Appendix A)\n",
    "        #object_points = np.vstack([object_points, np.linalg.inv(k).dot(z*np.array([u, v, 1]))])\n",
    "\n",
    "    image1_points = np.delete(image1_points, delete, 0)\n",
    "\n",
    "    image2_points = np.delete(image2_points, delete, 0)\n",
    "\n",
    "    \n",
    "    # Use PnP algorithm with RANSAC for robustness to outliers\n",
    "    \n",
    "    _,rvec, tvec, inliers = cv2.solvePnPRansac(object_points, image2_points, cameraMatrix=k, distCoeffs=None)\n",
    "\n",
    "    rmat = cv2.Rodrigues(rvec)[0]\n",
    "\n",
    "    \n",
    "    return rmat, tvec, image1_points, image2_points"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Number of matches before filtering: 47\n",
      "Number of matches after filtering: 5\n"
     ]
    }
   ],
   "source": [
    "image_left11 = handler.first_image_left\n",
    "image_plus11 = handler.second_image_left\n",
    "depth_left11 = np.load(handler.depth_dir + 'depth_left/'\n",
    "                                                + handler.left_depth_files[133])\n",
    "image_right11 = handler.first_image_right\n",
    "depth_plus11 = np.load(handler.depth_dir + 'depth_left/'\n",
    "                                                + handler.left_depth_files[1])\n",
    "\n",
    "kp0, des0 = extract_features(image_left11, 'sift')\n",
    "kp1, des1 = extract_features(image_plus11, 'sift')\n",
    "matches = match_features(des0, des1, matching='BF', detector='sift', sort=True)\n",
    "print('Number of matches before filtering:', len(matches))\n",
    "matches = filter_matches_distance(matches, 0.45)\n",
    "print('Number of matches after filtering:', len(matches))\n",
    "visualize_matches(image_left11, kp0, image_plus11, kp1, matches)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Time to compute disparity map using StereoBM: 0:00:00.006027\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005975\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007059\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005005\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006033\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006032\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007002\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008971\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005008\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010032\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008002\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006968\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006027\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005998\n",
      "Time to compute disparity map using StereoBM: 0:00:00.004999\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006000\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009004\n",
      "Time to compute disparity map using StereoBM: 0:00:00.004030\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005006\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007015\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006002\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007987\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007984\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006001\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005040\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009011\n",
      "Time to compute disparity map using StereoBM: 0:00:00.004999\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006999\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006990\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005026\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006000\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005007\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006002\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010000\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008001\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007071\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006003\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007002\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006000\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005973\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009014\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007000\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005959\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005027\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008971\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005963\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006999\n",
      "Time to compute disparity map using StereoBM: 0:00:00.004992\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008035\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005034\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008070\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005965\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007045\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005029\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005024\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008015\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007006\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008035\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005035\n",
      "Time to compute disparity map using StereoBM: 0:00:00.004987\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007000\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006003\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006999\n",
      "Time to compute disparity map using StereoBM: 0:00:00.004999\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006024\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005034\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007015\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005999\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006997\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005005\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007992\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006002\n",
      "Time to compute disparity map using StereoBM: 0:00:00.004994\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006998\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009008\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005032\n",
      "Time to compute disparity map using StereoBM: 0:00:00.004998\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008012\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008000\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008001\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005029\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009059\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005999\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005999\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005002\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005032\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007999\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008033\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007001\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005010\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005015\n",
      "Time to compute disparity map using StereoBM: 0:00:00.004998\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006998\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008027\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005032\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008001\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008007\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005975\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006999\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006000\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007000\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007033\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006002\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005990\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009987\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007999\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005026\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006980\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008000\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006998\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005025\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005005\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008969\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005910\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006022\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007034\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007029\n",
      "Time to compute disparity map using StereoBM: 0:00:00.004999\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006002\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005030\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007997\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007996\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005998\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005034\n",
      "Time to compute disparity map using StereoBM: 0:00:00.011007\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010080\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010015\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006014\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008999\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008984\n",
      "Time to compute disparity map using StereoBM: 0:00:00.011999\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006001\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008001\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006000\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006001\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009995\n",
      "Time to compute disparity map using StereoBM: 0:00:00.004999\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010038\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009000\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008999\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010001\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009986\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009037\n",
      "Time to compute disparity map using StereoBM: 0:00:00.004969\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010025\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010075\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009000\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009035\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007008\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008998\n",
      "Time to compute disparity map using StereoBM: 0:00:00.011004\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009992\n",
      "Time to compute disparity map using StereoBM: 0:00:00.011044\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010033\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005036\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006029\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009970\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005899\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010003\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005994\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010007\n",
      "Time to compute disparity map using StereoBM: 0:00:00.004999\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006975\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005996\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008987\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009998\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005997\n",
      "Time to compute disparity map using StereoBM: 0:00:00.011049\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009039\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010054\n",
      "Time to compute disparity map using StereoBM: 0:00:00.011027\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007001\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009010\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005970\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009969\n",
      "Time to compute disparity map using StereoBM: 0:00:00.011046\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010001\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010000\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009003\n",
      "Time to compute disparity map using StereoBM: 0:00:00.011048\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010034\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010001\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008964\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007957\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009027\n",
      "Time to compute disparity map using StereoBM: 0:00:00.011011\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007996\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005027\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010033\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010005\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008010\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009967\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009992\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006000\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009014\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007999\n",
      "Time to compute disparity map using StereoBM: 0:00:00.012012\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010999\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010998\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010000\n",
      "Time to compute disparity map using StereoBM: 0:00:00.014005\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006994\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005996\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005999\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009001\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010002\n",
      "Time to compute disparity map using StereoBM: 0:00:00.004999\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010041\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007048\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009997\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009001\n",
      "Time to compute disparity map using StereoBM: 0:00:00.004999\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009000\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010001\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010005\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010004\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007001\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009017\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009010\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006998\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008003\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010036\n",
      "Time to compute disparity map using StereoBM: 0:00:00.004999\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009999\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010003\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007010\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006029\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009018\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007000\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008998\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008000\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010000\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005970\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006001\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006001\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006002\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005000\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009032\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005996\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008999\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006001\n",
      "Time to compute disparity map using StereoBM: 0:00:00.004999\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005994\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008985\n",
      "Time to compute disparity map using StereoBM: 0:00:00.004993\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005997\n",
      "Time to compute disparity map using StereoBM: 0:00:00.004998\n",
      "Time to compute disparity map using StereoBM: 0:00:00.004999\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009031\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007001\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010998\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008033\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006027\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009046\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006003\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009002\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010007\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005965\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009961\n",
      "Time to compute disparity map using StereoBM: 0:00:00.004987\n",
      "Time to compute disparity map using StereoBM: 0:00:00.004999\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007998\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005001\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006001\n",
      "Time to compute disparity map using StereoBM: 0:00:00.011039\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009011\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006999\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007998\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008057\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005000\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009999\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009045\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005992\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009001\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006000\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008996\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009004\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007071\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010038\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006999\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010032\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005971\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009007\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006037\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010002\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006007\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008999\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006033\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008996\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005997\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009968\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009032\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006007\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005998\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008996\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006036\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008036\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005027\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009998\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006004\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006001\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007002\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010994\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005992\n",
      "Time to compute disparity map using StereoBM: 0:00:00.004999\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008999\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009033\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009001\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005999\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008000\n",
      "Time to compute disparity map using StereoBM: 0:00:00.004999\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009069\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009001\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008988\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009001\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008999\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009996\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009970\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008998\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008999\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008014\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008961\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005040\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006032\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008999\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008013\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008035\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006031\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006002\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006001\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008998\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006031\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009963\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010033\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006014\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010002\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005027\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006009\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009035\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010035\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009021\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005985\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007986\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008978\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005999\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009034\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008998\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010032\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007999\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006008\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010964\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006996\n",
      "Time to compute disparity map using StereoBM: 0:00:00.004996\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009017\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009980\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010007\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010005\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005997\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008963\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009998\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008002\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010010\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009032\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008025\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010026\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008063\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009036\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006003\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009039\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010046\n",
      "Time to compute disparity map using StereoBM: 0:00:00.014001\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006007\n",
      "Time to compute disparity map using StereoBM: 0:00:00.012032\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008033\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010000\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009000\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008004\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010000\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005998\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007998\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009964\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006001\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005995\n",
      "Time to compute disparity map using StereoBM: 0:00:00.011002\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010004\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009933\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010035\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010035\n",
      "Time to compute disparity map using StereoBM: 0:00:00.004998\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006025\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007981\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006032\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009012\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009059\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009984\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005973\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007974\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009002\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007999\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008000\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009004\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006034\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009964\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009051\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009999\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008034\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006078\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006003\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006000\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008001\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008001\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008040\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008037\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009033\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008034\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008006\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007007\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007034\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008006\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006999\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005005\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008032\n",
      "Time to compute disparity map using StereoBM: 0:00:00.022001\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007014\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006997\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007877\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006998\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009037\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008012\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005001\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006035\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007033\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009032\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010000\n",
      "Time to compute disparity map using StereoBM: 0:00:00.012070\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010004\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005001\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009000\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007992\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007963\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007965\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009997\n",
      "Time to compute disparity map using StereoBM: 0:00:00.004999\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005003\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005998\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005975\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008004\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005969\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009924\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008001\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005033\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008029\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009001\n",
      "Time to compute disparity map using StereoBM: 0:00:00.004987\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006002\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007002\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009012\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009001\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005029\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005001\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006000\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006944\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007000\n",
      "Time to compute disparity map using StereoBM: 0:00:00.010026\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005997\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007038\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007999\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009001\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009036\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005003\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009934\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008003\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008051\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008010\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007011\n",
      "Time to compute disparity map using StereoBM: 0:00:00.011069\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006030\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008996\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009026\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009965\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008966\n",
      "Time to compute disparity map using StereoBM: 0:00:00.004977\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005035\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008004\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006007\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007000\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008001\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009014\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009001\n",
      "Time to compute disparity map using StereoBM: 0:00:00.004993\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005036\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007999\n",
      "Time to compute disparity map using StereoBM: 0:00:00.037998\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007999\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009011\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008009\n",
      "Time to compute disparity map using StereoBM: 0:00:00.009003\n",
      "Time to compute disparity map using StereoBM: 0:00:00.004964\n",
      "Time to compute disparity map using StereoBM: 0:00:00.004998\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005001\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008062\n",
      "Time to compute disparity map using StereoBM: 0:00:00.004998\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005018\n",
      "Time to compute disparity map using StereoBM: 0:00:00.004998\n",
      "Time to compute disparity map using StereoBM: 0:00:00.004951\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008989\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006039\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007039\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005001\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006007\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005006\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007057\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007002\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005982\n",
      "Time to compute disparity map using StereoBM: 0:00:00.004997\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006892\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008000\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006012\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007031\n",
      "Time to compute disparity map using StereoBM: 0:00:00.005031\n",
      "Time to compute disparity map using StereoBM: 0:00:00.008998\n",
      "Time to compute disparity map using StereoBM: 0:00:00.007997\n",
      "Time to compute disparity map using StereoBM: 0:00:00.006002\n"
     ]
    }
   ],
   "source": [
    "stereo_l = handler.images_left\n",
    "stereo_r = handler.images_right\n",
    "\n",
    "depth_l = handler.depths_left\n",
    "depth_r = handler.depths_right\n",
    "\n",
    "%matplotlib tk\n",
    "\n",
    "xs = []\n",
    "ys = []\n",
    "zs = []\n",
    "compute_times = []\n",
    "fig1 = plt.figure()\n",
    "##########################################\n",
    "#uncomment this for viewing ground truth\n",
    "################################################################################\n",
    "ax = fig1.add_subplot(projection='3d')\n",
    "ax.view_init(elev=-20, azim=270)\n",
    "ax.plot(handler.gt[:,0,3], handler.gt[:,1,3], handler.gt[:,2,3], c = 'k')\n",
    "###############################################################################\n",
    "poses = (gt for gt in handler.gt)\n",
    "\n",
    "for i in range(handler.num_frames):\n",
    "    i\n",
    "    img_l = next(stereo_l)\n",
    "    img_r = next(stereo_r)\n",
    "    D_left = next(depth_l)\n",
    "    D_right = next(depth_r)\n",
    "\n",
    "\n",
    "    start = datetime.datetime.now()\n",
    "    disp = compute_left_disparity_map(img_l, img_r, matcher='bm')\n",
    "\n",
    "    gt = next(poses)\n",
    "    xs.append(gt[0,3])\n",
    "    ys.append(gt[1,3])\n",
    "    zs.append(gt[2,3])\n",
    "    \n",
    "\n",
    "    plt.plot(xs,ys, zs, c = 'chartreuse')\n",
    "    plt.pause(0.00000000001)\n",
    "     \n",
    "    cv2.imshow('L-Camera', img_l)\n",
    "    cv2.imshow('R-Camera', img_r)\n",
    "    cv2.imshow('Disparity', disp)\n",
    "    ##########################################\n",
    "    #uncomment this for viewing depth image// BUT, super slow. \n",
    "    ################################################################################\n",
    "    # plt.imshow(D_left)\n",
    "    ################################################################################   \n",
    "    plt.pause(0.00000000001)\n",
    "    \n",
    "    cv2.waitKey(1)\n",
    "\n",
    "    end = datetime.datetime.now()\n",
    "    compute_times.append(end-start)\n",
    "plt.close()\n",
    "cv2.destroyAllWindows()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "k,r,t,_,_,_,_ = cv2.decomposeProjectionMatrix(handler.P0)\n",
    "depth = handler.first_depth_left\n",
    "rmat, tvec, image1_points, image2_points = estimate_motion(matches,kp0,kp1,depth1 = depth,k=k)\n",
    "transformation_matrix = np.hstack([rmat,tvec])\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 92,
   "metadata": {},
   "outputs": [],
   "source": [
    "def visual_odometry(handler, detector='sift', matching='BF', filter_match_distance=None, \n",
    "                    stereo_matcher='bm', mask=None, depth_type='stereo', subset=None,\n",
    "                    plot=False):\n",
    "    '''\n",
    "    Function to perform visual odometry on a sequence from the KITTI visual odometry dataset.\n",
    "    Takes as input a Data_Handler object and optional parameters.\n",
    "    \n",
    "    Arguments:\n",
    "    handler -- Data_Handler object instance\n",
    "    \n",
    "    Optional Arguments:\n",
    "    detector -- (str) can be 'sift' or 'orb'. Default is 'sift'.\n",
    "    matching -- (str) can be 'BF' for Brute Force or 'FLANN'. Default is 'BF'.\n",
    "    filter_match_distance -- (float) value for ratio test on matched features. Default is None.\n",
    "    stereo_matcher -- (str) can be 'bm' (faster) or 'sgbm' (more accurate). Default is 'bm'.\n",
    "    mask -- (array) mask to reduce feature search area to where depth information available.\n",
    "    depth_type -- (str) can be 'stereo' or set to None to use Essential matrix decomposition.\n",
    "                        Note that scale will be incorrect with no depth used.\n",
    "    subset -- (int) number of frames to compute. Defaults to None to compute all frames.\n",
    "    plot -- (bool) whether to plot the estimated vs ground truth trajectory. Only works if\n",
    "                   matplotlib is set to tk mode. Default is False.\n",
    "    \n",
    "    Returns:\n",
    "    trajectory -- Array of shape Nx3x4 of estimated poses of vehicle for each computed frame.\n",
    "    \n",
    "    '''\n",
    "    # Determine if handler has lidar data\n",
    "    lidar = handler.lidar\n",
    "    \n",
    "    # Report methods being used to user\n",
    "    print('Generating disparities with Stereo{}'.format(str.upper(stereo_matcher)))\n",
    "    print('Detecting features with {} and matching with {}'.format(str.upper(detector), \n",
    "                                                                   matching))\n",
    "    if filter_match_distance is not None:\n",
    "        print('Filtering feature matches at threshold of {}*distance'.format(filter_match_distance))\n",
    "    if lidar:\n",
    "        print('Improving stereo depth estimation with lidar data')\n",
    "    if subset is not None:\n",
    "        #subset = subset + 1\n",
    "        num_frames = subset\n",
    "    else:\n",
    "        # Set num_frames to one less than the number of frames so we have sequential images\n",
    "        # in the last frame run.\n",
    "        num_frames = handler.num_frames\n",
    "        \n",
    "    if plot:\n",
    "        fig = plt.figure(figsize=(14, 14))\n",
    "        ax = fig.add_subplot(projection='3d')\n",
    "        ax.view_init(elev=-20, azim=270)\n",
    "        xs = handler.gt[:, 0, 3]\n",
    "        ys = handler.gt[:, 1, 3]\n",
    "        zs = handler.gt[:, 2, 3]\n",
    "        ax.set_box_aspect((np.ptp(xs), np.ptp(ys), np.ptp(zs)))\n",
    "        ax.plot(xs, ys, zs, c='k')\n",
    "    # Establish homogeneous transformation matrix. First pose is identity    \n",
    "    T_tot = np.eye(4)\n",
    "    trajectory = np.zeros((num_frames, 3, 4))\n",
    "    trajectory[0] = T_tot[:3, :]\n",
    "    imheight = handler.imheight\n",
    "    imwidth = handler.imwidth\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "    # Decompose left camera projection matrix to get intrinsic k matrix\n",
    "    k_left, r_left, t_left = decompose_projection_matrix(handler.P0)\n",
    "\n",
    "\n",
    "    if handler.low_memory:\n",
    "        handler.reset_frames()\n",
    "        image_plus1 = next(handler.images_left)\n",
    "\n",
    "    # Iterate through all frames of the sequence\n",
    "    for i in range(num_frames - 1):\n",
    "        # Stop if we've reached the second to last frame, since we need two sequential frames\n",
    "        #if i == num_frames - 1:\n",
    "        #    break\n",
    "        # Start timer for frame\n",
    "        start = datetime.datetime.now()\n",
    "        # Get our stereo images for depth estimation\n",
    "        if handler.low_memory:\n",
    "            image_left = image_plus1\n",
    "            image_right = next(handler.images_right)\n",
    "            # Get next frame in the left camera for visual odometry\n",
    "            image_plus1 = next(handler.images_left)\n",
    "        else:\n",
    "            image_left = handler.images_left[i]\n",
    "            image_right = handler.images_right[i]\n",
    "            # Get next frame in the left camera for visual odometry\n",
    "            image_plus1 = handler.images_left[i+1]\n",
    "        \n",
    "\n",
    "        # Estimate depth if using stereo depth estimation (recommended)\n",
    "        if depth_type == 'stereo':\n",
    "            depth = stereo_2_depth(image_left, \n",
    "                                   image_right, \n",
    "                                   P0=handler.P0, \n",
    "                                   P1=handler.P1,\n",
    "                                   matcher=stereo_matcher)\n",
    "            # depth = (handler.first_depth_left)\n",
    "        # Otherwise use Essential Matrix decomposition (ambiguous scale)\n",
    "        else:\n",
    "            depth = None\n",
    "            \n",
    "        # Supercede stereo depth estimations where lidar points are available\n",
    "        if lidar:\n",
    "            if handler.low_memory:\n",
    "                pointcloud = next(handler.pointclouds)\n",
    "            else:\n",
    "                pointcloud = handler.pointclouds[i]\n",
    "            lidar_depth = pointcloud2image(pointcloud, \n",
    "                                           imheight=imheight, \n",
    "                                           imwidth=imwidth, \n",
    "                                           Tr=handler.Tr, \n",
    "                                           P0=handler.P0)\n",
    "            indices = np.where(lidar_depth > 0)\n",
    "            depth[indices] = lidar_depth[indices]\n",
    "\n",
    "        # Get keypoints and descriptors for left camera image of two sequential frames\n",
    "        kp0, des0 = extract_features(image_left, detector, mask)\n",
    "        kp1, des1 = extract_features(image_plus1, detector, mask)\n",
    "        \n",
    "        # Get matches between features detected in the two images\n",
    "        matches_unfilt = match_features(des0, \n",
    "                                        des1, \n",
    "                                        matching=matching, \n",
    "                                        detector=detector, \n",
    "                                        sort=True)\n",
    "        \n",
    "        # Filter matches if a distance threshold is provided by user\n",
    "        if filter_match_distance is not None:\n",
    "            matches = filter_matches_distance(matches_unfilt, filter_match_distance)\n",
    "        else:\n",
    "            matches = matches_unfilt\n",
    "            \n",
    "        # Estimate motion between sequential images of the left camera\n",
    "\n",
    "        rmat, tvec, img1_points, img2_points = estimate_motion(matches, kp0, kp1, k=k_left, depth1=depth)\n",
    "\n",
    "        # Create blank homogeneous transformation matrix\n",
    "        Tmat = np.eye(4)\n",
    "        # Place resulting rotation matrix  and translation vector in their proper locations\n",
    "        # in homogeneous T matrix\n",
    "        Tmat[:3, :3] = rmat\n",
    "        Tmat[:3, 3] = tvec.T\n",
    "\n",
    "        T_tot = T_tot.dot(np.linalg.inv(Tmat))\n",
    "            \n",
    "        # Place pose estimate in i+1 to correspond to the second image, which we estimated for\n",
    "        trajectory[i+1, :, :] = T_tot[:3, :]\n",
    "        # End the timer for the frame and report frame rate to user\n",
    "        end = datetime.datetime.now()\n",
    "        print('Time to compute frame {}:'.format(i+1), end-start)\n",
    "        \n",
    "        if plot:\n",
    "            xs = trajectory[:i+2, 0, 3]\n",
    "            ys = trajectory[:i+2, 1, 3]\n",
    "            zs = trajectory[:i+2, 2, 3]\n",
    "            plt.plot(xs, ys, zs, c='chartreuse')\n",
    "            plt.pause(1e-32)\n",
    "            \n",
    "    if plot:        \n",
    "        plt.close()\n",
    "        \n",
    "    return trajectory"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 93,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Generating disparities with StereoBM\n",
      "Detecting features with SIFT and matching with BF\n",
      "Filtering feature matches at threshold of 0.4*distance\n",
      "Time to compute frame 1: 0:00:00.131964\n",
      "Time to compute frame 2: 0:00:00.120015\n",
      "Time to compute frame 3: 0:00:00.115006\n",
      "Time to compute frame 4: 0:00:00.124001\n",
      "Time to compute frame 5: 0:00:00.115001\n",
      "Time to compute frame 6: 0:00:00.123993\n",
      "Time to compute frame 7: 0:00:00.113998\n",
      "Time to compute frame 8: 0:00:00.115041\n",
      "Time to compute frame 9: 0:00:00.110005\n",
      "Time to compute frame 10: 0:00:00.118999\n",
      "Time to compute frame 11: 0:00:00.118939\n",
      "Time to compute frame 12: 0:00:00.120991\n",
      "Time to compute frame 13: 0:00:00.114034\n",
      "Time to compute frame 14: 0:00:00.116001\n",
      "Time to compute frame 15: 0:00:00.114000\n",
      "Time to compute frame 16: 0:00:00.118031\n",
      "Time to compute frame 17: 0:00:00.110000\n",
      "Time to compute frame 18: 0:00:00.119963\n",
      "Time to compute frame 19: 0:00:00.115973\n",
      "Time to compute frame 20: 0:00:00.113968\n",
      "Time to compute frame 21: 0:00:00.114004\n",
      "Time to compute frame 22: 0:00:00.119000\n",
      "Time to compute frame 23: 0:00:00.116999\n",
      "Time to compute frame 24: 0:00:00.136001\n",
      "Time to compute frame 25: 0:00:00.121013\n",
      "Time to compute frame 26: 0:00:00.123009\n",
      "Time to compute frame 27: 0:00:00.121010\n",
      "Time to compute frame 28: 0:00:00.123034\n",
      "Time to compute frame 29: 0:00:00.117967\n",
      "Time to compute frame 30: 0:00:00.128025\n",
      "Time to compute frame 31: 0:00:00.123001\n",
      "Time to compute frame 32: 0:00:00.129037\n",
      "Time to compute frame 33: 0:00:00.141967\n",
      "Time to compute frame 34: 0:00:00.125028\n",
      "Time to compute frame 35: 0:00:00.131006\n",
      "Time to compute frame 36: 0:00:00.126033\n",
      "Time to compute frame 37: 0:00:00.125016\n",
      "Time to compute frame 38: 0:00:00.126947\n",
      "Time to compute frame 39: 0:00:00.121997\n",
      "Time to compute frame 40: 0:00:00.131032\n",
      "Time to compute frame 41: 0:00:00.147001\n",
      "Time to compute frame 42: 0:00:00.128962\n",
      "Time to compute frame 43: 0:00:00.119038\n",
      "Time to compute frame 44: 0:00:00.115989\n",
      "Time to compute frame 45: 0:00:00.113023\n",
      "Time to compute frame 46: 0:00:00.116998\n",
      "Time to compute frame 47: 0:00:00.138015\n",
      "Time to compute frame 48: 0:00:00.106995\n",
      "Time to compute frame 49: 0:00:00.111965\n",
      "Time to compute frame 50: 0:00:00.117036\n",
      "Time to compute frame 51: 0:00:00.107991\n",
      "Time to compute frame 52: 0:00:00.109007\n",
      "Time to compute frame 53: 0:00:00.117000\n",
      "Time to compute frame 54: 0:00:00.118040\n",
      "Time to compute frame 55: 0:00:00.111968\n",
      "Time to compute frame 56: 0:00:00.112036\n",
      "Time to compute frame 57: 0:00:00.106001\n",
      "Time to compute frame 58: 0:00:00.109965\n",
      "Time to compute frame 59: 0:00:00.134001\n",
      "Time to compute frame 60: 0:00:00.113034\n",
      "Time to compute frame 61: 0:00:00.118003\n",
      "Time to compute frame 62: 0:00:00.118998\n",
      "Time to compute frame 63: 0:00:00.123006\n",
      "Time to compute frame 64: 0:00:00.114037\n",
      "Time to compute frame 65: 0:00:00.140998\n",
      "Time to compute frame 66: 0:00:00.127999\n",
      "Time to compute frame 67: 0:00:00.150001\n",
      "Time to compute frame 68: 0:00:00.132983\n",
      "Time to compute frame 69: 0:00:00.129974\n",
      "Time to compute frame 70: 0:00:00.151035\n",
      "Time to compute frame 71: 0:00:00.134962\n",
      "Time to compute frame 72: 0:00:00.143006\n",
      "Time to compute frame 73: 0:00:00.137999\n",
      "Time to compute frame 74: 0:00:00.140036\n",
      "Time to compute frame 75: 0:00:00.176004\n",
      "Time to compute frame 76: 0:00:00.143966\n",
      "Time to compute frame 77: 0:00:00.155035\n",
      "Time to compute frame 78: 0:00:00.152998\n",
      "Time to compute frame 79: 0:00:00.148000\n",
      "Time to compute frame 80: 0:00:00.152040\n",
      "Time to compute frame 81: 0:00:00.152003\n",
      "Time to compute frame 82: 0:00:00.157999\n",
      "Time to compute frame 83: 0:00:00.150006\n",
      "Time to compute frame 84: 0:00:00.170958\n",
      "Time to compute frame 85: 0:00:00.159026\n",
      "Time to compute frame 86: 0:00:00.159036\n",
      "Time to compute frame 87: 0:00:00.163014\n",
      "Time to compute frame 88: 0:00:00.158008\n",
      "Time to compute frame 89: 0:00:00.175964\n",
      "Time to compute frame 90: 0:00:00.164006\n",
      "Time to compute frame 91: 0:00:00.158977\n",
      "Time to compute frame 92: 0:00:00.154973\n",
      "Time to compute frame 93: 0:00:00.164965\n",
      "Time to compute frame 94: 0:00:00.152998\n",
      "Time to compute frame 95: 0:00:00.153035\n",
      "Time to compute frame 96: 0:00:00.174000\n",
      "Time to compute frame 97: 0:00:00.150000\n",
      "Time to compute frame 98: 0:00:00.176036\n",
      "Time to compute frame 99: 0:00:00.154028\n",
      "Time to perform odometry: 0:00:18.426400\n"
     ]
    }
   ],
   "source": [
    "handler.lidar = False\n",
    "start = datetime.datetime.now()\n",
    "trajectory_nolidar_bm = visual_odometry(handler,\n",
    "                                        filter_match_distance=0.4,\n",
    "                                        detector='sift',\n",
    "                                        # matching='FLANN',\n",
    "                                        stereo_matcher='bm',\n",
    "                                        mask=None,     \n",
    "                                        subset=100,\n",
    "                                        plot=True)\n",
    "end = datetime.datetime.now()\n",
    "print('Time to perform odometry:', end-start)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 88,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Warning: Cannot change to a different GUI toolkit: notebook. Using tk instead.\n"
     ]
    }
   ],
   "source": [
    "%matplotlib notebook"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 89,
   "metadata": {},
   "outputs": [],
   "source": [
    "fig = plt.figure(figsize=(12,8))\n",
    "ax = fig.add_subplot(111, projection='3d')\n",
    "\n",
    "ax.plot(trajectory_nolidar_bm[:, :, 3][:, 0], \n",
    "        trajectory_nolidar_bm[:, :, 3][:, 1], \n",
    "        trajectory_nolidar_bm[:, :, 3][:, 2], label='estimated', color='orange')\n",
    "\n",
    "ax.plot(handler.gt[:, :, 3][:, 0], \n",
    "        handler.gt[:, :, 3][:, 1], \n",
    "        handler.gt[:, :, 3][:, 2], label='ground truth')\n",
    "\n",
    "ax.set_xlabel('x')\n",
    "ax.set_ylabel('y')\n",
    "ax.set_zlabel('z')\n",
    "\n",
    "ax.view_init(elev=-20, azim=270)\n"
   ]
  }
 ],
 "metadata": {
  "interpreter": {
   "hash": "8e498f732d7c2aa228df44a2a1ad0a06b158366b5ada381e7ddd871473ea3a71"
  },
  "kernelspec": {
   "display_name": "Python 3.10.2 64-bit",
   "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.10.2"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}