Opencv:如何计算 3d 直方图?

Opencv: how to compute a 3d histogram?

我是 OpenCV 的新手,我将编写以下代码来计算 rgb 图像的量化和加权直方图。

M是一张权重图。这是一个与输入图像具有相同维度的 Mat 对象。 首先,我将所有(双)值放在 [1,8] 范围内。然后,对于 rgb 值的每个三元组 (1,1,1), (1,1,2), .... (8,8,8) 我想求和相应权重的值。因此,当我找到三元组 (1,2,1) 时,我知道它对应于 bin 9(即第 9 个 bin)。所以我尝试将 M(x,y) 的值与当前的 bin 累加器 H 相加,但它不起作用!

注意:在我的 matlab 代码中,我使用 accumarray 但是,我做的时候有问题

H.at<uchar>(idx,1) = H.at<uchar>(idx,1) + M.at<double>(Point(x, y));

if i 运行 M.type() 它returns 值3

Mat H = Mat::zeros(1,512,CV_8UC1);

    for (int y = 0; y < R.rows; ++y) {
        for (int x = 0; x < R.cols; ++x) {

            intensity = R.at<double>(Point(x, y));
            p = intensity[0];
            r = 1 + floor(p * 7.9999);
            cout << "R index = " << r << endl << endl;


            intensity = G.at<double>(Point(x, y));
            p = intensity[0];
            g = 1 + floor(p * 7.9999);
            cout << "G index = " << g << endl << endl;


            intensity = B.at<double>(Point(x, y));
            p = intensity[0];
            b = 1 + floor(p * 7.9999);
            cout << "B index = " << b << endl << endl;

            C.at<cv::Vec3b>(x, y)[0] = r;
            C.at<cv::Vec3b>(x, y)[1] = g;
            C.at<cv::Vec3b>(x, y)[2] = b;

            //idx = 1 +((r-1)*64  +  (g-1)*8  +  (b-1)*1 )
            //Here i don't sum 1 because in C the indices starts from 0
            idx =  (r - 1) * 64 + (g - 1) * 8 + (b - 1) * 1;

            H.at<uchar>(idx,1) = H.at<uchar>(idx,1) + M.at<double>(Point(x, y));
            cout << endl << idx;

        }
    }

编辑 好的,我说一下根据你的建议做的一些修改,这些是C和H的初始化

cv::Mat C(doubleRed.rows, doubleRed.cols, CV_8UC3);
Mat H = Mat::zeros(1, 512, CV_16UC1);

我解决了

中发生的错误
C.at<cv::Vec3b>(x, y)[0] = r;
C.at<cv::Vec3b>(x, y)[1] = g;
C.at<cv::Vec3b>(x, y)[2] = b;

反转 x 和 y 它会起作用...但我希望理解为什么我必须这样做...但是当我尝试使用 H 的 at() 函数时代码仍然崩溃:

H.at<uchar>(idx, 1) = H.at<uchar>(idx, 1) + M.at<double>(Point(x, y));

我注意到的一些可能有帮助的事情:

您声明H如下:

Mat H = Mat::zeros(1,512,CV_8UC1);

然后你像这样访问它:

H.at<uchar>(idx,1) = ...

所以您正在使用 1 row512 columns 创建一个矩阵,然后访问 row idxcolumn 1。您需要交换 at:

中的索引
H.at<uchar>(1,idx) = ...

编辑: 索引看起来倒退的原因是 at() 对参数进行排序,例如:

H.at<uchar>(row,column) ... or
H.at<uchar>(y, x) ...

这与 Point 相反,它将参数排序为:

Point2f P(column, row); or
Point2f P(x, y);

http://docs.opencv.org/modules/core/doc/basic_structures.html#mat-at

此外,我不知道您打算在每个垃圾箱中放置多少件物品,但除非少于 256 件,否则 CV_8UC1 太小了。

最后,OpenCV 中的图像通常按 BGR 顺序排列,因此您的

        C.at<cv::Vec3b>(x, y)[0] = r;
        C.at<cv::Vec3b>(x, y)[1] = g;
        C.at<cv::Vec3b>(x, y)[2] = b;

大概是倒退了。为了提高速度,您可能还想只调用一次 at 并将值存储在 Vec3b 中,然后再访问各个元素。