mat.at<int>( i ); 整型数组问中的元素 i
mat.at<float>( i,j ); 浮点型数组附中的元素(i, j)
mat.at<int>( pt ) 整型矩阵问中处于 (pt.x,pt.y) 的元素
mat.at<float>( i,j,k ); 三维浮点型矩阵M 中处于 (1,j,k) 位置的元素
mat.at<uchar>( idx ); 无符号字符数组问中位于idx[ ]所索引的n维位置的元素
为了访问二维数组,你可以使用 C风格的指针来指定某行 。这个工作由cv::Mat类的成员函数 ptr<>()完成(再次强调,数组中的数据是按行连续组织的,因此不可以通过这种方式访问一个指定的列),由于at<>(),ptr<>() 都是模板函数,所以需要一个类型名来进行实例化。函数接收一个整型参数来指示希望指针指向的行,函数将返回一个和矩阵原始数据类型相同的数据指针(比如说,如果数组类型是CV_32FC3,它会返回一个float* 。因此,给定一个类型为float三通道的矩阵mtx,结构体mtx.ptr<VeC3f>(3)将会返回mtx的第三行指向第一个元素第一个(浮点)通道的指针,这通常是访问数组最快的方式,因为一旦你拥有指针,就可以向指定的位置写入数据。
使用at<>和利用指针访问的差距取决于编译器的优化程度。使用at<>进行存储性能更接近于好的优化器所能够达到的效果(尽管稍微慢一些)但是如果优化器被关闭了,其性能相较于没有优化器优化会有一个数量级的提升。 而通过迭代器的访问几乎总是比这两种方法都要慢,然而在几乎所 有情况下,使用内置的opencv函数都比你写的所有通过循环来控制直接访问的方法快,所以在任何情况下,都要避免通过循环来大量访问矩阵内部结构。
有两种方式可以获得一个指向矩阵的数据区域的指针。一种是使用ptr<>()成员函数,另一种是直接使用数据指针data,然后使用成员数组step来计算地址,后者更接近于C语言操作。但是一般来说,由于at<>()和ptr<>()以及迭代器的存在,这种方式已经不再推荐了。
直接计算地址始终是最有效率的做法,尤其是要处理多于二维的数组时!
1 int sz[3] = { 4, 4, 4 };
2 cv::Mat m(3, sz, CV_32FC3); // A three-dimensional array of size 4-bY-4-bY-4
3 cv::randu(m, -1.0f, 1.0f); // fill with random numbers from -1.0 to 1.0
4
5 for (int i = 0; i < 4; i++)
6 {
7 for (int j = 0; j < 4; j++)
8 {
9 for (int k = 0; k < 4; k++)
10 {
11 cout << m.at<float>(i, j, k) << " ";
12 }
13 cout << "\n";
14 }
15 cout << "\n";
16 }
17
18 float max = 0.0f;
19 //cv::MatConstIterator<Vec3f> it = m.begin();
20 //cv::MatConstIterator it = m.begin();
21 for (int i = 0; i < 4; i++)
22 {
23 for (int j = 0; j < 4; j++)
24 {
25 float *data = m.ptr<float>(i, j);
26 for (int k = 0; k < 4; k++)
27 {
28 float len2;
29 len2 = *data + *(data + 1) + *(data + 2) + *(data + 3);
30 if ( len2 > max )
31 max = len2;
32 }
33 }
34 }
35
36 cout << "max = " << max << endl;