【问题标题】:How do i get the size of a multi-dimensional cv::Mat? (Mat, or MatND)我如何获得多维 cv::Mat 的大小? (垫子或垫子)
【发布时间】:2013-09-23 19:17:22
【问题描述】:

我正在创建一个多维 MAT 对象,并且想获取对象的大小 - 例如,

const int sz[] = {10,10,9};
Mat temp(3,sz,CV_64F);
std::cout << "temp.dims = " << temp.dims << " temp.size = " << temp.size() << " temp.channels = " << temp.channels() << std::endl;

我相信生成的 MAT 为 10x10x9,我想确认一下,但 COUT 语句给出:

temp.dims = 3 temp.size = [10 x 10] temp.channels = 1

我希望看到:

temp.dims = 3 temp.size = [10 x 10 x 9] temp.channels = 1

或者:

temp.dims = 3 temp.size = [10 x 10] temp.channels = 9

我怎样才能得到这个 Mat 对象的维度?我在 Mat::Mat 或 MatND 中没有看到任何方法

【问题讨论】:

    标签: c++ opencv mat


    【解决方案1】:

    您刚刚发现自己是 OpenCV C++ API 的众多缺陷之一。

    如果你看一下OpenCV 2.4.6.1版本的源代码,你会发现cv::Mat::sizecv::Mat::MSize类型的成员对象,它被定义为

    struct CV_EXPORTS MSize
    {
        MSize(int* _p);
        Size operator()() const;
        const int& operator[](int i) const;
        int& operator[](int i);
        operator const int*() const;
        bool operator == (const MSize& sz) const;
        bool operator != (const MSize& sz) const;
    
        int* p;
    };
    

    因此cv::Mat::size()实际上是指cv::Mat::MSize::operator ()(),其返回类型Size定义为

    typedef Size_<int> Size2i;
    typedef Size2i Size;
    

    引用OpenCV manualSize是一个

    “用于指定图像或矩形大小的模板类。该类包括两个成员,称为宽度和高度。”

    换句话说,Size 只适用于二维矩阵。

    幸运的是,所有希望都没有像you can use cv::Mat::MSize::operator [](int i) to get the size of the matrix along its i-th dimension一样失去。

    const int sz[] = {10,10,9}; 
    cv::Mat temp(3,sz,CV_64F); 
    std::cout << "temp.dims = " << temp.dims << "temp.size = [";
    for(int i = 0; i < temp.dims; ++i) {
        if(i) std::cout << " X ";
        std::cout << temp.size[i];
    }
    std::cout << "] temp.channels = " << temp.channels() << std::endl;
    

    temp.dims = 3 temp.size = [10 x 10 x 9] temp.channels = 1

    【讨论】:

    • 多么彻底而详细的答案!谢谢!事实证明,我发现现在使用 Vector 存储每个切片更容易(我没有做太多的跨切片索引)。接受并投票。
    • @Pete Experience 最终教会我避免cv::Mat 在所有合理的[阅读几乎任何] 成本。作为一个建议,如果你还不知道cv::Mat_&lt;&gt; 的存在,我建议你看看here。它隐藏了cv::Mat API 最令人发指的缺陷,并帮助我忍受 OpenCV 这么久。
    • 好的。很高兴知道!是你喜欢的接入运营商吗?还有其他好处吗?我看到您可以提供向量(例如 Vec3b)作为基本类型;我认为这会破坏 Filter2D 和其他?但我会调查。所有这些的文档似乎......稀疏。
    • @Pete cv::Mat_&lt;&gt; 继承 cv::Mat 并因此可以隐式转换为它,因此它可以在大多数情况下无缝替换 cv::Mat。它的主要好处是静态类型化,从某种意义上说,编译器需要处理底层数据类型的检查(不超过预期,可能会添加)。这意味着不再有诸如断言检查矩阵的底层数据类型、动态函数重载技术等废话。任何已经使用过 OpenCV 的人都可以证明这些是最容易出错的警告。
    • @AdiShavit 它没有,这是对 OP 的建议,他提到他已经开始迁移到类型擦除的 cv::Mat,因此我建议无论何时都应该首选静态类型的 cv::Mat_&lt;&gt;这是有道理的。
    【解决方案2】:

    OpenCV 2.4.9 可以很好地处理多维大小。 struct cv::Mat::MSize 可以存储和返回多个维度。数据成员cv::Mat::size 的类型为cv::Mat::MSize。此代码将为您枚举尺寸:

    const int sz[] = {3, 4, 3, 6};
    cv::Mat bigm(4, sz, CV_8UC1);
    cout << bigm.dims << '\t';
    for (int i=0; i<bigm.dims; ++i)
      cout << bigm.size[i] << ',';
    cout << endl;
    

    输出是:

    4       3,4,3,6,
    

    【讨论】:

    • 我正在阅读 OpenCV2.4.9 文档。它写道: C++: Size Mat::size() const 该方法返回一个矩阵大小: Size(cols, rows) 。当矩阵大于二维时,返回大小为(-1, -1)。
    • 我猜文档还没有跟上 API 的变化。上面的示例代码对你有用吗?
    • 谢谢。 .size() 方法只能用于二维。但是您的示例 .size (成员变量)可以适用于多个维度。
    • 这实际上是一个更好的答案。使用这个MultiDimenonalMatrix.size,然后你得到所有维度的大小!不要使用 .size()!!
    【解决方案3】:
    std::vector<size_t> getMatDims(const cv::Mat& m)
    {
        std::vector<size_t> dims(m.dims);
        std::partial_sum(&m.step[0],&m.step[0]+m.dims,dims.begin(),[](size_t a,size_t b){ return a/b; });
        return dims;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-09-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-09
      • 2021-04-05
      • 2013-05-08
      • 2021-09-10
      相关资源
      最近更新 更多