title: What is the type of parameter ranges for calcHist()?
body: <p>In the (C++) description of the function <a href="https://docs.opencv.org/3.4/d6/dc7/group__imgproc__hist.html#ga4b2b5fd75503ff9e6844cc4dcdaed35d" rel="nofollow noreferrer">cv2.calcHist()</a>, ranges is said to be an array of arrays, each element being <code>[low, high]</code> histogram boundaries for the dimension considered in case of <code>uniform</code> histogram:</p>
  <blockquote>
  <p><strong>ranges</strong>: Array of the dims arrays of the histogram bin boundaries in
  each dimension. When the histogram is uniform (<code>uniform=true</code>), then
  for each dimension i it is enough to specify the lower (inclusive)
  boundary <code>L0</code> of the 0-th histogram bin and the upper (exclusive)
  boundary <code>UhistSize[i]−1</code> for the last histogram bin <code>histSize[i]-1</code>.
  That is, in case of a uniform histogram each of <code>ranges[i]</code> is an array
  of 2 elements. When the histogram is not uniform (<code>uniform=false</code>),
  then each of <code>ranges[i]</code> contains <code>histSize[i]+1</code> elements:
  <code>L0,U0=L1,U1=L2,...,UhistSize[i]−2=LhistSize[i]−1,UhistSize[i]−1</code> . The
  array elements, that are not between <code>L0</code> and <code>UhistSize[i]−1</code>, are not
  counted in the histogram.</p>
  </blockquote>
  <p>The Python binding description is just:</p>
  <blockquote>
  <p><code>hist = cv.calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate]])</code></p>
  </blockquote>
  <p>without indication of types. In most bindings C++ arrays can be replaced by lists, so <code>ranges</code> would be a list of lists.</p>
  <p>Actually passing a list of lists triggers the cryptic error:</p>
  <blockquote>
  <p><code>&lt;built-in function calcHist&gt; returned NULL without setting an error</code></p>
  </blockquote>
  <p>Code to generate this error, with two cases: single and multiple channel(s):</p>
  <pre><code>import cv2    
  src = cv2.imread ('sample.jpg')
  hsv = cv2.cvtColor(src, cv2.COLOR_BGR2HSV)
  images = [hsv]    
  h_nbins = 255; s_nbins = 255
  h_range = [0, 180]; s_range = [0, 256]        
  # Single histogram: H
  channels = [0]
  nbins = [h_nbins]
  
  ranges = [h_range] #### &lt; -- doesn't work
  
  hist = cv2.calcHist(hsv, channels, None, nbins, ranges)
  print(hist.shape)    
  # Two histograms: H x S
  channels = [0, 1]
  nbins = [h_nbins, s_nbins]
  
  ranges = [h_range, s_range] #### &lt; -- doesn't work
  
  hist = cv2.calcHist(hsv, channels, None, nbins, ranges)
  print(hist.shape)
  </code></pre>
  <p>What works is passing a flat list, which contains a sequence of pairs (low, high). E.g:</p>
  <pre><code>h_range = [0, 180]; s_range = [0, 256]
  ranges = h_range # &lt;-- for a single channel -- or
  ranges = h_range + s_range # &lt;-- for two channels
  hist = cv2.calcHist(hsv, channels, None, nbins, ranges)
  </code></pre>
  <p>These types are used in this <a href="https://www.pyimagesearch.com/2014/01/22/clever-girl-a-guide-to-utilizing-color-histograms-for-computer-vision-and-image-search-engines/" rel="nofollow noreferrer">tutorial</a> (other tutorials I found are related to single channel cases, generally using a tuple for the <code>(low, high)</code> boundaries, which I assume is converted by OpenCV into an array.</p>
  <p>Question: Can someone confirm this, possibly linking to a better description of the Python binding. Is there a rational for <code>ranges</code> not following the general rule to use arrays/lists, with element related to channel <code>i</code> found at position <code>i</code>? For example here I was expecting a list of tuples. Or maybe I'm missing something and this question is silly.</p>