# Is the OpenCV 3d Histogram 3 axis histogram?

What exactly is the 3d histogram returned from OpenCV's calcHist()?

For a 1d histogram I know that:
- the x axis represents my desired bins (for simplicity lets say 0-255 - grayscale colour values).
- the y axis represents the number of pixels that have that bin/colour value.

For a 3d histogram...am I correct that:
- There are 3 x axis arrays? One for each colour channel (in my case b,g,r)?
- There are 3 y axis arrays? One for each of the above?

OR

• There are still only 1 x and y axis. But the x axis represents a concatenation(?) of b*g*r and the y axis tells me how many pixels have the colour b*g*r?

If its the first scenario, does OpenCV have a way to:
- Produce a unique number to represent a colour (hexadecimal? or combine b*g*r)?
- Produce a histogram of a 3 channel image where the x axis bins represent the unique colour number above and y axis tells me how many pixels have that colour?
- Presumably this is alot more computationally efficient than having a 3d histogram with 255 bins?

edit retag close merge delete

Sort by » oldest newest most voted

I think everything is in doc here (see detailed description)

n-dimensional dense array class

The class Mat represents an n-dimensional dense numerical single-channel or multi-channel array. It can be used to store real or complex-valued vectors and matrices, grayscale or color images, voxel volumes, vector fields, point clouds, tensors, histograms (though, very high-dimensional histograms may be better stored in a SparseMat ). The data layout of the array M is defined by the array M.step[], so that the address of element (i0,...,iM.dims−1), where 0≤ik<m.size[k], is="" computed="" as:<="" p="">

In case of a 2-dimensional array, the above formula is reduced to:

Note that M.step[i] >= M.step[i+1] (in fact, M.step[i] >= M.step[i+1]*M.size[i+1] ). This means that 2-dimensional matrices are stored row-by-row, 3-dimensional matrices are stored plane-by-plane, and so on. M.step[M.dims-1] is minimal and always equal to the element size M.elemSize() .

Now if you want to use calhist for 3d histogram (calcbackproject for example with dim=3 it is a 3d histogram) you can do like this :

    Mat m = imread("f:/lib/opencv/samples/data/baboon.jpg", CV_LOAD_IMAGE_ANYCOLOR);
Rect rZone(Point(220, 330), Point(260, 360));

float hRange[] = { 0, 255 };
const float* etendu[] = { hRange, hRange,hRange };
int hBins = 30;
int tailleHist[] = { hBins, hBins+5, hBins+10 };
int canaux[] = { 2, 1,0 };
double hMin, hMax;
cv::Mat histogramme;
cv::Mat resultMap;
cv::Mat backproj1d;
for (int dim = 1; dim <= 3; dim++)
{
cv::calcHist(&m, 1, canaux, mask, histogramme, dim, tailleHist, etendu, true, false);
minMaxIdx(histogramme, &hMin, &hMax);
cout << "Hist extremum = " << hMin << "\t" << hMax << "\n";
cout << "Pixel in Mat = " <<histogramme.total()<<endl;
for (int j=0;j<dim;j++)
{
cout <<"dimension " << j <<" : " << tailleHist[j]<<endl;
if (j<dim-1)
cout << "offset in dimension "<<j<<" -> "<<histogramme.step[j]<<endl;
}
normalize(histogramme, histogramme, 0, 255, cv::NormTypes::NORM_MINMAX, -1, cv::Mat());

minMaxIdx(histogramme, &hMin, &hMax);
cout << "after normalize Hist extremum = " << hMin << "\t" << hMax << "\n";
cv::calcBackProject(&m, 1, canaux, histogramme, backproj1d, etendu, 1, true);
applyColorMap(backproj1d, resultMap, cv::COLORMAP_JET);
imshow(format("backproject %dD", dim), resultMap);
waitKey();
}

more

Official site

GitHub

Wiki

Documentation