【发布时间】:2010-12-23 02:49:21
【问题描述】:
如何在 OpenCV 2.0 的新“Mat”类中按行访问元素?该文档在下面链接,但我无法理解它。 http://opencv.willowgarage.com/documentation/cpp/basic_structures.html#mat
【问题讨论】:
如何在 OpenCV 2.0 的新“Mat”类中按行访问元素?该文档在下面链接,但我无法理解它。 http://opencv.willowgarage.com/documentation/cpp/basic_structures.html#mat
【问题讨论】:
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
【讨论】:
基于@J. Calleja说,你有两个选择
如果你想随机访问Mat的元素,只需简单地使用
Mat.at<data_Type>(row_num, col_num) = value;
如果你想连续访问,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文章中的一篇博文中的图片,更直观易懂。
见下图。
【讨论】:
关于文档:
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() 以便访问元素。
【讨论】:
Mat 的类型怎么办?
上面提供的想法很好。为了快速访问(如果您想制作实时应用程序),您可以尝试以下操作:
//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版本快很多?
OCV 竭尽全力确保您在不知道元素类型的情况下无法执行此操作,但是如果您想要一种易于编码但效率不高的方式来与类型无关地读取它,您可以使用类似
double val=mean(someMat(Rect(x,y,1,1)))[channel];
要做好它,你必须知道类型。 at 方法是安全的方法,但如果操作正确,直接访问数据指针通常会更快。
【讨论】: