【问题标题】:Opencv: how to compute a 3d histogram?Opencv:如何计算 3d 直方图?
【发布时间】:2015-01-19 15:54:21
【问题描述】:

我是 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));

如果我运行 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 的函数 at() 时代码仍然崩溃:

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

【问题讨论】:

    标签: c++ opencv image-processing histogram


    【解决方案1】:

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

    您声明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 中,然后再访问各个元素。

    【讨论】:

    • 感谢您的回复。我只是总结了 M 中具有相同 r、g、b 组合的值。实际上,我计划将 C 用作索引映射而不是图像,因此在这种情况下 r g 和 b 的顺序并不重要。您建议 H 使用哪种数据类型?为什么不是一个简单的 int H[512] ?
    • @user2614596 您使用的类型取决于您将在H 中存储的值的大小。您当前正在使用CV_8UC1,它是一个 8 位无符号整数,仅存储来自[0..255] 的值。如果您期望值超出此范围,则应使用 CV_16UC1CV_32SC1(没有 CV_32U 类型)。
    • 这仍然行不通...我已经编辑了问题以添加详细信息,但对 H 的访问不明确。 M 的值是“大”无符号整数。
    • @user2614596 我添加了一个更新。您似乎仍在使用不正确的参数顺序来访问 H
    • 是的..对不起你是对的...我已经解决了在 H 声明中使用 CV_16UC1 和 来访问 H 值
    猜你喜欢
    • 2014-01-31
    • 1970-01-01
    • 1970-01-01
    • 2018-06-02
    • 2021-08-12
    • 1970-01-01
    • 2013-03-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多