Histogram: OpenCV vs Numpy. Does OpenCV works properly?

I’m doing a very simple test to compare histograms generated by OpenCv and Numpy. The expectation is the two are identical, but actually the one created with OpenCV seems wrong.
Probably I’m doing something wrong but I don’t know what.

Here it is the code:

import numpy as np
import cv2

# simple 16x16 grayscale image filled with values from 0 to 255
img = np.arange(0, 256, dtype="uint8")
img = np.reshape(img, (16, 16))

# histogram generated with Numpy
hist_np, _ = np.histogram(img.flatten(), 256, [0, 256])

# histogram generated with OpenCV
hist_cv = cv2.calcHist(img, [0], mask=None, histSize=[256], ranges=[0, 256])

Now, my expectation is that on both cases the resulting histogram is a vector (256,1) of ones.
Numpy returns the expected result (reshaped for reading):

print(hist_np.reshape(16,16))

returns:

[[1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]
 [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]
 [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]
 [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]
 [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]
 [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]
 [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]
 [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]
 [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]
 [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]
 [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]
 [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]
 [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]
 [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]
 [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]
 [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]]

but OpenCV doesn’t:

print(hist_cv.reshape(16,16).astype("uint8"))

returns:

[[1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]]

Any idea ?

256 you mean? buckets for values 0 and 255 need to exist :smiley: I’m still reading the post but wanted to remark on that right now.

opencv’s calcHist is a weird function. IIRC it might calculate row-wise or column-wise histograms, for whatever reason. I think that might be happening here, and you accidentally only selected the first row of your 16x16 picture.

Yes, 256 not 255. It was a typo. Fixed.

I think I see the issue now…

the first parameter is called “images”. you’ll have to pass [img] (1-element list).

if you didn’t do that, it would take each row of your img and consider that one image… and you’d have to specify multiple ranges (or something) so that it works on “all images”.

You are right, what a fool! Thanks for your help.