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;