【问题标题】:Accessing a matrix element in the "Mat" object (not the CvMat object) in OpenCV C++在 OpenCV C++ 中访问“Mat”对象(不是 CvMat 对象)中的矩阵元素
【发布时间】:2010-12-23 02:49:21
【问题描述】:

如何在 OpenCV 2.0 的新“Mat”类中按行访问元素?该文档在下面链接,但我无法理解它。 http://opencv.willowgarage.com/documentation/cpp/basic_structures.html#mat

【问题讨论】:

    标签: c++ matrix opencv


    【解决方案1】:

    对于cv::Mat_<T> mat,只需使用mat(row, col)

    访问具有指定类型cv::Mat_< _Tp > 的矩阵元素更舒适,因为您可以跳过模板规范。 documentation 中也指出了这一点。

    代码:

    cv::Mat1d mat0 = cv::Mat1d::zeros(3, 4);
    std::cout << "mat0:\n" << mat0 << std::endl;
    std::cout << "element: " << mat0(2, 0) << std::endl;
    std::cout << std::endl;
    
    cv::Mat1d mat1 = (cv::Mat1d(3, 4) <<
        1, NAN, 10.5, NAN,
        NAN, -99, .5, NAN,
        -70, NAN, -2, NAN);
    std::cout << "mat1:\n" << mat1 << std::endl;
    std::cout << "element: " << mat1(0, 2) << std::endl;
    std::cout << std::endl;
    
    cv::Mat mat2 = cv::Mat(3, 4, CV_32F, 0.0);
    std::cout << "mat2:\n" << mat2 << std::endl;
    std::cout << "element: " << mat2.at<float>(2, 0) << std::endl;
    std::cout << std::endl;
    

    输出:

    mat0:
    [0, 0, 0, 0;
     0, 0, 0, 0;
     0, 0, 0, 0]
    element: 0
    
    mat1:
    [1, nan, 10.5, nan;
     nan, -99, 0.5, nan;
     -70, nan, -2, nan]
    element: 10.5
    
    mat2:
    [0, 0, 0, 0;
     0, 0, 0, 0;
     0, 0, 0, 0]
    element: 0
    

    【讨论】:

      【解决方案2】:

      基于@J. Calleja说,你有两个选择

      方法 1 - 随机访问

      如果你想随机访问Mat的元素,只需简单地使用

      Mat.at<data_Type>(row_num, col_num) = value;
      

      方法 2 - 连续访问

      如果你想连续访问,OpenCV提供了兼容STL iterator的Mat迭代器,它更像C++风格

      MatIterator_<double> it, end;
      for( it = I.begin<double>(), end = I.end<double>(); it != end; ++it)
      {
          //do something here
      }
      

      for(int row = 0; row < mat.rows; ++row) {
          float* p = mat.ptr(row); //pointer p points to the first place of each row
          for(int col = 0; col < mat.cols; ++col) {
               *p++;  // operation here
          }
      }
      

      如果你对方法2的工作原理有任何困难,我借用Dynamic Two-dimensioned Arrays in C文章中的一篇博文中的图片,更直观易懂。

      见下图。

      【讨论】:

        【解决方案3】:

        关于文档:

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

        上面写着:

        (...) 如果你知道矩阵元素 类型,例如它是浮动的,那么你可以 使用 at() 方法

        也就是说,你可以使用:

        Mat M(100, 100, CV_64F);
        cout << M.at<double>(0,0);
        

        也许使用Mat_ 类更容易。它是Mat 的模板包装器。 Mat_ 重载了 operator() 以便访问元素。

        【讨论】:

        • @sumit at() 方法返回对元素的引用。您可以使用:M.at(0, 0) = value;
        • 我很确定这个例子是这个答案有缺陷。我相信 at 在内部进行了不安全的强制转换,因此在 uint 矩阵上使用 at 和 double 会产生不希望的/损坏的结果。建议更正。
        • @Catskul 你是对的。文本很好,但示例应该是 CV_64F。我已经更正了。
        • 如果我不知道 Mat 的类型怎么办?
        • @nn0p 您可以使用 Mat::type() 方法来获取类型。
        【解决方案4】:

        上面提供的想法很好。为了快速访问(如果您想制作实时应用程序),您可以尝试以下操作:

        //suppose you read an image from a file that is gray scale
        Mat image = imread("Your path", CV_8UC1);
        //...do some processing
        uint8_t *myData = image.data;
        int width = image.cols;
        int height = image.rows;
        int _stride = image.step;//in case cols != strides
        for(int i = 0; i < height; i++)
        {
            for(int j = 0; j < width; j++)
            {
                uint8_t val = myData[ i * _stride + j];
                //do whatever you want with your value
            }
        }
        

        指针访问比 Mat.at 访问快得多。希望对您有所帮助!

        【讨论】:

        • 指针访问成本与 Mat.at 完全相同(在发行版中编译时)。唯一的区别是断言,除非代码在调试模式下编译,否则断言是活动的。
        • 为什么指针访问会比Mat.at版本快很多?
        【解决方案5】:

        OCV 竭尽全力确保您在不知道元素类型的情况下无法执行此操作,但是如果您想要一种易于编码但效率不高的方式来与类型无关地读取它,您可以使用类似

        double val=mean(someMat(Rect(x,y,1,1)))[channel];
        

        要做好它,你必须知道类型。 at 方法是安全的方法,但如果操作正确,直接访问数据指针通常会更快。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-09-17
          • 1970-01-01
          • 2023-04-05
          • 2012-09-04
          • 1970-01-01
          • 2014-05-03
          • 1970-01-01
          • 2023-03-25
          相关资源
          最近更新 更多