title: Fast calculation of v-disparity with OpenCV-Function calcHist
body: <p>Based on a disparity matrix from a passive stereo-camera system i need to calculate a v-disparity representation for obstacle detection with OpenCV.</p>
  
  <p>A working implementation is <strong>not</strong> the problem. The problem is to do it fast...</p>
  
  <p>(One) Reference for v-Disparity: Labayrade, R. and Aubert, D. and Tarel, J.P. Real time obstacle detection in stereovision on non flat road geometry through v-disparity representation</p>
  
  <p>The basic in short, to get the v-disparity (figure <a href="https://i.stack.imgur.com/fPvsg.png" rel="nofollow noreferrer">1</a>), is to analyze the rows of the disparity-matrix (figure <a href="https://i.stack.imgur.com/YXYvf.png" rel="nofollow noreferrer">2</a>) an represent the result as a histogram for each row over the disparity values. u-disparity (figure <a href="https://i.stack.imgur.com/R0qSt.png" rel="nofollow noreferrer">3</a>) is the same on the columns of the disparity-matrix. (All figures are false-colored.)</p>
  
  <p>I have implement the "same" in Python and C++. The speed in Python is acceptable but in C++ i get for the u- and v-disparity a time round about a half second (0.5 s). </p>
  
  <p><em>(1. edit: due to the separate time measurement, only the calculation of the u-histogram takes a big amount of time...)</em></p>
  
  <p>This leads me to following questions:</p>
  
  <ol>
  <li><p>Is it possible to avoid the loops for the line-wise calculation of the histogram? Is there a "trick" to do it with one call of <code>calcHist</code>-Function from OpenCV? Perhaps with the dimensions?</p></li>
  <li><p>Is it in C++ just bad-coded and the runtime-issue are not related to the loops used for calculation?</p></li>
  </ol>
  
  <p>Thanks, all</p>
  
  <hr>
  
  <p>Working implementation in Python:</p>
  
  <pre><code>#!/usr/bin/env python2
  #-*- coding: utf-8 -*-
  #
  # THIS SOURCE-CODE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  # IMPLIED. IN NO  EVENT WILL THE AUTHOR BE HELD LIABLE FOR ANY DAMAGES ARISING FROM
  # THE USE OF THIS SOURCE-CODE. USE AT YOUR OWN RISK.
  
  import cv2
  import numpy as np
  import time
  
  def draw_object(image, x, y, width=50, height=100):
      color = image[y, x]
      image[y-height:y, x-width//2:x+width//2] = color
  
  
  IMAGE_HEIGHT = 600
  IMAGE_WIDTH = 800
  
  while True:
  
      max_disp = 200
  
      # create fake disparity
      image = np.zeros((IMAGE_HEIGHT, IMAGE_WIDTH), np.uint8)
  
      for c in range(IMAGE_HEIGHT)[::-1]:
          image[c, ...] = int(float(c) / IMAGE_HEIGHT * max_disp)
  
      draw_object(image, 275, 175)
      draw_object(image, 300, 200)
      draw_object(image, 100, 350)
  
      # calculate v-disparity
      vhist_vis = np.zeros((IMAGE_HEIGHT, max_disp), np.float)
      for i in range(IMAGE_HEIGHT):
          vhist_vis[i, ...] = cv2.calcHist(images=[image[i, ...]], channels=[0], mask=None, histSize=[max_disp],
                                           ranges=[0, max_disp]).flatten() / float(IMAGE_HEIGHT)
  
  
      vhist_vis = np.array(vhist_vis * 255, np.uint8)
      vblack_mask = vhist_vis &lt; 5
      vhist_vis = cv2.applyColorMap(vhist_vis, cv2.COLORMAP_JET)
      vhist_vis[vblack_mask] = 0
  
      # calculate u-disparity
      uhist_vis = np.zeros((max_disp, IMAGE_WIDTH), np.float)
      for i in range(IMAGE_WIDTH):
          uhist_vis[..., i] = cv2.calcHist(images=[image[..., i]], channels=[0], mask=None, histSize=[max_disp],
                                           ranges=[0, max_disp]).flatten() / float(IMAGE_WIDTH)
  
      uhist_vis = np.array(uhist_vis * 255, np.uint8)
      ublack_mask = uhist_vis &lt; 5
      uhist_vis = cv2.applyColorMap(uhist_vis, cv2.COLORMAP_JET)
      uhist_vis[ublack_mask] = 0
  
  
      image = cv2.applyColorMap(image, cv2.COLORMAP_JET)
  
  
      cv2.imshow('image', image)
  
      cv2.imshow('vhist_vis', vhist_vis)
      cv2.imshow('uhist_vis', uhist_vis)
  
      cv2.imwrite('disparity_image.png', image)
      cv2.imwrite('v-disparity.png', vhist_vis)
      cv2.imwrite('u-disparity.png', uhist_vis)
  
  
      if chr(cv2.waitKey(0)&amp;255) == 'q':
          break
  </code></pre>
  
  <hr>
  
  <p>Working implementation in C++:</p>
  
  <pre><code>#include &lt;iostream&gt;
  #include &lt;stdlib.h&gt;
  
  #include &lt;ctime&gt;
  
  #include &lt;opencv2/opencv.hpp&gt;
  
  
  using namespace std;
  
  void draw_object(cv::Mat image, unsigned int x, unsigned int y, unsigned int width=50, unsigned int height=100)
  {
      image(cv::Range(y-height, y), cv::Range(x-width/2, x+width/2)) = image.at&lt;unsigned char&gt;(y, x);
  }
  
  
  int main()
  {
      unsigned int IMAGE_HEIGHT = 600;
      unsigned int IMAGE_WIDTH = 800;
      unsigned int MAX_DISP = 250;
      unsigned int CYCLE = 0;
  
      //setenv("QT_GRAPHICSSYSTEM", "native", 1);
  
  
      // === PREPERATIONS ==
      cv::Mat image = cv::Mat::zeros(IMAGE_HEIGHT, IMAGE_WIDTH, CV_8U);
      cv::Mat uhist = cv::Mat::zeros(IMAGE_HEIGHT, MAX_DISP, CV_32F);
      cv::Mat vhist = cv::Mat::zeros(MAX_DISP, IMAGE_WIDTH, CV_32F);
  
      cv::Mat tmpImageMat, tmpHistMat;
  
      float value_ranges[] = {(float)0, (float)MAX_DISP};
      const float* hist_ranges[] = {value_ranges};
      int channels[] = {0};
      int histSize[] = {MAX_DISP};
  
  
      struct timespec start, finish;
      double elapsed;
  
      while(1)
      {
          CYCLE++;
  
          // === CLEANUP ==
          image = cv::Mat::zeros(IMAGE_HEIGHT, IMAGE_WIDTH, CV_8U);
          uhist = cv::Mat::zeros(IMAGE_HEIGHT, MAX_DISP, CV_32F);
          vhist = cv::Mat::zeros(MAX_DISP, IMAGE_WIDTH, CV_32F);
  
          // === CREATE FAKE DISPARITY WITH OBJECTS ===
          for(int i = 0; i &lt; IMAGE_HEIGHT; i++)
              image.row(i) = ((float)i / IMAGE_HEIGHT * MAX_DISP);
  
          draw_object(image, 200, 500);
          draw_object(image, 525 + CYCLE%100, 275);
          draw_object(image, 500, 300 + CYCLE%100);
  
          clock_gettime(CLOCK_MONOTONIC, &amp;start);
  
          // === CALCULATE V-HIST ===
          for(int i = 0; i &lt; IMAGE_HEIGHT; i++)
          {
              tmpImageMat = image.row(i);
              vhist.row(i).copyTo(tmpHistMat);
  
              cv::calcHist(&amp;tmpImageMat, 1, channels, cv::Mat(), tmpHistMat, 1, histSize, hist_ranges, true, false);
  
              vhist.row(i) = tmpHistMat.t() / (float) IMAGE_HEIGHT;
          }
  
          clock_gettime(CLOCK_MONOTONIC, &amp;finish);
          elapsed = (finish.tv_sec - start.tv_sec);
          elapsed += (finish.tv_nsec - start.tv_nsec) * 1e-9;
          cout &lt;&lt; "V-HIST-TIME: " &lt;&lt; elapsed &lt;&lt; endl;
  
          clock_gettime(CLOCK_MONOTONIC, &amp;start);
  
          // === CALCULATE U-HIST ===
          for(int i = 0; i &lt; IMAGE_WIDTH; i++)
          {
              tmpImageMat = image.col(i);
              uhist.col(i).copyTo(tmpHistMat);
  
              cv::calcHist(&amp;tmpImageMat, 1, channels, cv::Mat(), tmpHistMat, 1, histSize, hist_ranges, true, false);
  
              uhist.col(i) = tmpHistMat / (float) IMAGE_WIDTH;
          }
  
          clock_gettime(CLOCK_MONOTONIC, &amp;finish);
          elapsed = (finish.tv_sec - start.tv_sec);
          elapsed += (finish.tv_nsec - start.tv_nsec) * 1e-9;
          cout &lt;&lt; "U-HIST-TIME: " &lt;&lt; elapsed &lt;&lt; endl;
  
          // === PREPARE AND SHOW RESULTS ===
  
          uhist.convertTo(uhist, CV_8U, 255);
          cv::applyColorMap(uhist, uhist, cv::COLORMAP_JET);
  
          vhist.convertTo(vhist, CV_8U, 255);
          cv::applyColorMap(vhist, vhist, cv::COLORMAP_JET);
  
          cv::imshow("image", image);
          cv::imshow("uhist", uhist);
          cv::imshow("vhist", vhist);
  
  
  
          if ((cv::waitKey(1)&amp;255) == 'q')
              break;
      }
  
      return 0;
  }
  </code></pre>
  
  <hr>
  
  <p><a href="https://i.stack.imgur.com/fPvsg.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/fPvsg.png" alt="enter image description here"></a>
  Figure 1: v-disparity</p>
  
  <p><a href="https://i.stack.imgur.com/YXYvf.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/YXYvf.png" alt="fake disparity matrix"></a>
  Figure 2: Fake disparity matrix</p>
  
  <p><a href="https://i.stack.imgur.com/R0qSt.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/R0qSt.png" alt="enter image description here"></a>
  Figure 3: u-disparity</p>
  
  <hr>
  
  <ol>
  <li>edit:
  
  <ul>
  <li>correct name for u- and v-disparity and separate time measurement in c++ example</li>
  <li>small typo</li>
  </ul></li>
  </ol>