Accessing a matrix element in the “Mat” object (not the CvMat object) in OpenCV C++

前端 未结 5 1004
有刺的猬
有刺的猬 2020-12-08 06:50

How to access elements by row, col in OpenCV 2.0\'s new \"Mat\" class? The documentation is linked below, but I have not been able to make any sense of it. http://opencv.wi

相关标签:
5条回答
  • 2020-12-08 07:27

    The ideas provided above are good. For fast access (in case you would like to make a real time application) you could try the following:

    //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
        }
    }
    

    Pointer access is much faster than the Mat.at<> accessing. Hope it helps!

    0 讨论(0)
  • 2020-12-08 07:28

    OCV goes out of its way to make sure you can't do this without knowing the element type, but if you want an easily codable but not-very-efficient way to read it type-agnostically, you can use something like

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

    To do it well, you do have to know the type though. The at<> method is the safe way, but direct access to the data pointer is generally faster if you do it correctly.

    0 讨论(0)
  • 2020-12-08 07:39

    Based on what @J. Calleja said, you have two choices

    Method 1 - Random access

    If you want to random access the element of Mat, just simply use

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

    Method 2 - Continuous access

    If you want to continuous access, OpenCV provides Mat iterator compatible with STL iterator and it's more C++ style

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

    or

    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
        }
    }
    

    If you have any difficulty to understand how Method 2 works, I borrow the picture from a blog post in the article Dynamic Two-dimensioned Arrays in C, which is much more intuitive and comprehensible.

    See the picture below.

    0 讨论(0)
  • 2020-12-08 07:39

    For cv::Mat_<T> mat just use mat(row, col)

    Accessing elements of a matrix with specified type cv::Mat_< _Tp > is more comfortable, as you can skip the template specification. This is pointed out in the documentation as well.

    code:

    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;
    

    output:

    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
    
    0 讨论(0)
  • 2020-12-08 07:40

    On the documentation:

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

    It says:

    (...) if you know the matrix element type, e.g. it is float, then you can use at<>() method

    That is, you can use:

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

    Maybe it is easier to use the Mat_ class. It is a template wrapper for Mat. Mat_ has the operator() overloaded in order to access the elements.

    0 讨论(0)
提交回复
热议问题