9

I am trying to access an 3D histogram of a RGB image. But the histogram matrix returns the number of rows and columns equal to -1. I want to iterate through the histogram and check the individual values in the 3D matrix. But, when I check the number of rows and columns in the matrix, I get -1 as shown below.

CODE

int main( int argc, const char** argv ) {
    Mat image = imread("fl.png");
    int histSize[3] = {8, 8, 8};
    float range[2] = {0, 256};
    const float * ranges[3] = {range, range, range};
    int channels[3] = {0, 1, 2};
    Mat hist;
    calcHist(&image, 1, channels, Mat(), hist, 3, histSize, ranges);
    cout << "Hist.rows = "<< hist.rows << endl;
    cout << "Hist.cols = "<< hist.cols << endl;
    return 0;
}

OUTPUT

Hist.rows = -1
Hist.cols = -1

What mistake am I making? How can I access the individual matrix values.

2
  • Related: stackoverflow.com/questions/15211387/… Commented Oct 17, 2014 at 9:48
  • The link you mentioned is for 1D histogram, I am asking for 3D histogram. Commented Oct 17, 2014 at 10:01

1 Answer 1

11

From the documentation of Mat:

//! the number of rows and columns or (-1, -1) when the array has more than 2 dimensions

But you have 3 dimensions.

You can access individual values of your histogram using hist.at<T>(i,j,k).

Or you can use iterators as described in the documentation here.

Code

    // Build with gcc main.cpp  -lopencv_highgui -lopencv_core -lopencv_imgproc
    #include <iostream>
    #include <opencv2/core/core.hpp>
    #include <opencv2/highgui.hpp>
    #include <opencv2/imgproc.hpp>

    using std::cout;
    using std::endl;
    using namespace cv; # Please, don't include whole namespaces!

    int main( int argc, const char** argv ) {
        Mat image = imread("good.jpg");
        int histSize[3] = {8, 8, 8};
        float range[2] = {0, 256};
        const float * ranges[3] = {range, range, range};
        int channels[3] = {0, 1, 2};
        Mat hist;
        calcHist(&image, 1, channels, Mat(), hist, 3, histSize, ranges);
        cout << "Hist.dims = " << hist.dims << endl;
        cout << "Value: " << hist.at<double>(0,0, 0) << endl;
        cout << "Hist.rows = "<< hist.rows << endl;
        cout << "Hist.cols = "<< hist.cols << endl;
        return 0;
    }

Iterate through every value:

        for (MatConstIterator_<double> it = hist.begin<double>(); it != hist.end<double>(); it++) {
            cout << "Value: " << *it << "\n";
        }
        cout << std::flush;

Iterate through every value using indices:

        for (int i=0; i<histSize[0]; i++) {
            for (int j=0; j<histSize[1]; j++) {
                for (int k=0; k<histSize[2]; k++) {
                    cout << "Value(" << i << ", " << j << ", " << k <<"): " << hist.at<double>(i, j, k) << "\n";
                }
            }
        }
        cout << std::flush;
Sign up to request clarification or add additional context in comments.

6 Comments

Thanks for the edited answer. I read the documentation earlier, but could not figure it out, how to iterate through the it. How can I iterate using for loops to access single value of histogram?
I've added that info.
@Unipiedra Thank You. I have accepted the answer, but is there a way to also access the value using the current index values i.e. i,j,k.
So function like cv::normalize (like normalize(hist, hist, 0, 255, NORM_MINMAX, -1, Mat()); ) will not work?
The question was about accessing individual elements. I don't see how ` normalize ` would help.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.