Opencv:如何计算 3D 直方图

Opencv: how to compute a 3d histogram?

本文关键字:计算 3D 直方图 何计算 Opencv      更新时间:2023-10-16

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

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

注意:在我的 matlab 代码中,我使用 accumarray 来做到这一点但是,当我这样做时有些不对劲

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

如果我运行 M.type(),它返回值 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() 的函数时,代码仍然崩溃:

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中。