如何使用OpenCV在C++中访问3D直方图值?

9
我正在尝试访问RGB图像的三维直方图。但是,直方图矩阵返回的行数和列数均为-1。我想要遍历直方图并检查三维矩阵中的单个值。但是,当我检查矩阵中的行数和列数时,如下所示,我得到-1。 代码:
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;
}

输出

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

我犯了什么错误?我怎样才能访问单个矩阵值?

相关链接:https://dev59.com/cm_Xa4cB1Zd3GeqPyjU3 - Unapiedra
你提到的链接是关于1D直方图的,我正在询问3D直方图。 - bikz05
1个回答

11

来自Mat的文档:

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

但是您有三个维度。

您可以使用 hist.at<T>(i,j,k) 访问直方图的各个值。

或者您可以使用文档中描述的迭代器,详情请参见此处

代码

    // 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;
    }

遍历每个值:

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

使用索引遍历每个值:

        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;

感谢您编辑的答案。我之前阅读了文档,但是无法弄清如何迭代它。我该如何使用for循环迭代来访问直方图的单个值? - bikz05
1
我已经添加了那个信息。 - Unapiedra
@Unipiedra谢谢您。我已接受这个答案,但是否有一种方法也可以使用当前索引值即i,j,k来访问该值? - bikz05
那么像cv::normalize这样的函数(例如normalize(hist,hist,0,255,NORM_MINMAX,-1,Mat());)就不能使用吗? - mrgloom
问题是关于访问单个元素的。我不明白 normalize 如何有帮助。 - Unapiedra
normalize() 对于 3D 直方图无效。函数 minMaxLoc 也是如此。 - Yonatan Simson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接