简体   繁体   English

在 OpenCV C++ 中访问“Mat”对象(不是 CvMat 对象)中的矩阵元素

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

How to access elements by row, col in OpenCV 2.0's new "Mat" class?如何在 OpenCV 2.0 的新“Mat”类中按行、列访问元素? The documentation is linked below, but I have not been able to make any sense of it.文档链接如下,但我无法理解它。 http://opencv.willowgarage.com/documentation/cpp/basic_structures.html#mat http://opencv.willowgarage.com/documentation/cpp/basic_structures.html#mat

On the documentation:在文档上:

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

It says:它说:

(...) if you know the matrix element type, eg it is float, then you can use at<>() method (...) 如果您知道矩阵元素类型,例如它是浮点数,那么您可以使用 at<>() 方法

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.也许使用Mat_类更容易。 It is a template wrapper for Mat .它是Mat的模板包装器。 Mat_ has the operator() overloaded in order to access the elements. Mat_重载了operator()以访问元素。

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.指针访问比 Mat.at<> 访问快得多。 Hope it helps!希望能帮助到你!

Based on what @J.基于什么@J。 Calleja said, you have two choices Calleja说,你有两个选择

Method 1 - Random access方法 1 - 随机访问

If you want to random access the element of Mat, just simply use如果你想随机访问 Mat 的元素,只需简单地使用

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

Method 2 - Continuous access方法 2 - 连续访问

If you want to continuous access, OpenCV provides Mat iterator compatible with STL iterator and it's more C++ style如果你想连续访问,OpenCV提供了与STL iterator器兼容的Mat迭代STL iterator ,它更像C++风格

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.如果您对方法2的工作方式有任何理解上的困难,我借用C中动态二维数组一文中的博客文章中的图片,它更加直观和易于理解。

See the picture below.见下图。

在此处输入图片说明

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 OCV 竭尽全力确保您在不知道元素类型的情况下无法执行此操作,但是如果您想要一种易于编码但不是非常有效的方式来读取它的类型不可知,您可以使用类似

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. at<> 方法是一种安全的方法,但如果操作正确,直接访问数据指针通常会更快。

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

Accessing elements of a matrix with specified type cv::Mat_< _Tp > is more comfortable, as you can skip the template specification.访问具有指定类型cv::Mat_< _Tp >的矩阵元素更方便,因为您可以跳过模板规范。 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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM