OpenCV中基本数据类型Mat类使用简析
Mat 類是OpenCV中的一個基本數據類型,它是一個n維密集數組類
Mat 類表示一個 n 維密集數值單通道或多通道數組。它可用于存儲實數或復值向量和矩陣、灰度或彩色圖像、體素體積、向量場、點云、張量、直方圖(不過,非常高維的直方圖可能更好地存儲在 SparseMat 中)。數組M的數據布局由數組M.step[]定義,使得元素 ( i 0 , ? , i M . d i m s ? 1 ) (i_0,\cdots,i_{M.dims?1}) (i0?,?,iM.dims?1?)的地址,其中 0 ≤ i k < M . s i z e [ k ] 0≤i_k<M.size[k] 0≤ik?<M.size[k], 計算為:
a d d r ( M i 0 , ? , i M . d i m s ? 1 ) = M . d a t a + M . s t e p [ 0 ] ? i 0 + M . s t e p [ 1 ] ? i 1 + ? + M . s t e p [ M . d i m s ? 1 ] ? i M . d i m s ? 1 addr(M_{i0},\cdots,i_{M.dims-1})=M.data+M.step[0]*i_0+M.step[1]*i_1+\cdots+M.step[M.dims-1]*i_{M.dims-1} addr(Mi0?,?,iM.dims?1?)=M.data+M.step[0]?i0?+M.step[1]?i1?+?+M.step[M.dims?1]?iM.dims?1?
在二維數組的情況下,上述公式簡化為:
a d d r ( M i , j ) = M . d a t a + M . s t e p [ 0 ] ? i + M . s t e p [ 1 ] ? j addr(M_{i,j})=M.data+M.step[0]*i+M.step[1]*j addr(Mi,j?)=M.data+M.step[0]?i+M.step[1]?j
請注意,M.step[i] >= M.step[i+1] (實際上,M.step[i] >= M.step[i+1]*M.size[i+1] )。 這意味著 2 維矩陣是逐行存儲的,3 維矩陣是逐平面存儲的,依此類推。M.step[M.dims-1] 是最小的并且總是等于元素大小 M.elemSize() 。
因此,Mat 中的數據布局與 OpenCV 1.x 中的 CvMat、IplImage 和 CvMatND 類型完全兼容。它還兼容標準工具包和 SDK 中的大多數密集數組類型,例如 Numpy (ndarray)、Win32(獨立設備位圖),即任何使用步長(或步幅)來計算像素位置的數組。由于這種兼容性,可以為用戶分配的數據創建一個 Mat 標頭并使用 OpenCV 函數就地處理它。
有許多不同的方法可以創建一個 Mat 對象。下面列出了最流行的選擇:
- 使用 create(nrows, ncols, type) 方法或類似的 Mat(nrows, ncols, type[, fillValue]) 構造函數。分配了指定大小和類型的新數組。type 與 cvCreateMat 方法中的含義相同。例如,CV_8UC1 表示 8 位單通道數組,CV_32FC2 表示 2 通道(復數)浮點數組,以此類推。
測試代碼
#include <opencv2/highgui.hpp> #include <opencv2/imgcodecs.hpp> #include <opencv2/imgproc.hpp> #include <iostream>int main() {cv::Mat M(3, 3, CV_32FC2, cv::Scalar(1, 3));// M.create(5, 5, CV_8UC(3));std::cout << "==默認風格==\n" << cv::format(M, cv::Formatter::FMT_DEFAULT) << std::endl;std::cout << "==Python風格==\n" << cv::format(M, cv::Formatter::FMT_PYTHON) << std::endl;std::cout << "==Numpy風格==\n" << cv::format(M, cv::Formatter::FMT_NUMPY) << std::endl;std::cout << "==C風格==\n" << cv::format(M, cv::Formatter::FMT_C) << std::endl;return 0; }輸出如下
==默認風格== [1, 3, 1, 3, 1, 3;1, 3, 1, 3, 1, 3;1, 3, 1, 3, 1, 3] ==Python風格== [[[1, 3], [1, 3], [1, 3]],[[1, 3], [1, 3], [1, 3]],[[1, 3], [1, 3], [1, 3]]] ==Numpy風格== array([[[1, 3], [1, 3], [1, 3]],[[1, 3], [1, 3], [1, 3]],[[1, 3], [1, 3], [1, 3]]], dtype='float32') ==C風格== {1, 3, 1, 3, 1, 3,1, 3, 1, 3, 1, 3,1, 3, 1, 3, 1, 3} ==默認風格== [ 0, 0, 128, 63, 0, 0, 64, 64, 0, 0, 128, 63, 0, 0, 64;64, 0, 0, 128, 63, 0, 0, 64, 64, 0, 0, 128, 63, 0, 0;64, 64, 0, 0, 128, 63, 0, 0, 64, 64, 0, 0, 128, 63, 0;0, 64, 64, 0, 0, 128, 63, 0, 0, 64, 64, 0, 0, 128, 63;0, 0, 64, 64, 0, 0, 128, 63, 0, 0, 64, 64, 160, 63, 25] ==Python風格== [[[ 0, 0, 128], [ 63, 0, 0], [ 64, 64, 0], [ 0, 128, 63], [ 0, 0, 64]],[[ 64, 0, 0], [128, 63, 0], [ 0, 64, 64], [ 0, 0, 128], [ 63, 0, 0]],[[ 64, 64, 0], [ 0, 128, 63], [ 0, 0, 64], [ 64, 0, 0], [128, 63, 0]],[[ 0, 64, 64], [ 0, 0, 128], [ 63, 0, 0], [ 64, 64, 0], [ 0, 128, 63]],[[ 0, 0, 64], [ 64, 0, 0], [128, 63, 0], [ 0, 64, 64], [160, 63, 25]]] ==Numpy風格== array([[[ 0, 0, 128], [ 63, 0, 0], [ 64, 64, 0], [ 0, 128, 63], [ 0, 0, 64]],[[ 64, 0, 0], [128, 63, 0], [ 0, 64, 64], [ 0, 0, 128], [ 63, 0, 0]],[[ 64, 64, 0], [ 0, 128, 63], [ 0, 0, 64], [ 64, 0, 0], [128, 63, 0]],[[ 0, 64, 64], [ 0, 0, 128], [ 63, 0, 0], [ 64, 64, 0], [ 0, 128, 63]],[[ 0, 0, 64], [ 64, 0, 0], [128, 63, 0], [ 0, 64, 64], [160, 63, 25]]], dtype='uint8') ==C風格== { 0, 0, 128, 63, 0, 0, 64, 64, 0, 0, 128, 63, 0, 0, 64,64, 0, 0, 128, 63, 0, 0, 64, 64, 0, 0, 128, 63, 0, 0,64, 64, 0, 0, 128, 63, 0, 0, 64, 64, 0, 0, 128, 63, 0,0, 64, 64, 0, 0, 128, 63, 0, 0, 64, 64, 0, 0, 128, 63,0, 0, 64, 64, 0, 0, 128, 63, 0, 0, 64, 64, 160, 63, 25}由兩者輸出結果得出,create() 僅在當前數組的形狀或類型與指定的不同時分配一個新數組。
- 創建一個多維數組
它將維度數 =1 傳遞給 Mat 構造函數,但創建的數組將是二維的,列數設置為 1。因此,Mat::dims 始終 >= 2(當數組為空時也可以為 0)。
- 在右側可以有數組或表達式的地方使用復制構造函數或賦值運算符(見下文)。如介紹中所述,數組賦值是一個 O(1) 操作,因為它只復制標頭并增加引用計數器。Mat::clone() 方法可用于在需要時獲取數組的完整(深層)副本。
- 為另一個數組的一部分構造一個標頭。它可以是單行、單列、多行、多列、數組中的矩形區域(在代數中稱為小區域)或對角線。此類操作也是 O(1),因為新標頭引用相同的數據。實際上可以使用此功能修改數組的一部分,例如:
由于額外的 datastart 和 dataend 成員,可以使用 locateROI() 計算主容器數組中的相對子數組位置:
Mat A = Mat::eye(10, 10, CV_32S); // extracts A columns, 1 (inclusive) to 3 (exclusive). Mat B = A(Range::all(), Range(1, 3)); // extracts B rows, 5 (inclusive) to 9 (exclusive). // that is, C \~ A(Range(5, 9), Range(1, 3)) Mat C = B(Range(5, 9), Range::all()); Size size; Point ofs; C.locateROI(size, ofs); // size will be (width=10,height=10) and the ofs will be (x=1, y=5)與整個矩陣一樣,如果您需要深度復制,請使用提取的子矩陣的 clone() 方法。
測試代碼
#include <opencv2/highgui.hpp> #include <opencv2/imgcodecs.hpp> #include <opencv2/imgproc.hpp> #include <iostream>int main() {cv::Mat M(6, 6, CV_8UC3, cv::Scalar(23, 24, 25));std::cout << "==默認風格==\n" << cv::format(M, cv::Formatter::FMT_DEFAULT) << std::endl;std::cout << "==Python風格==\n" << cv::format(M, cv::Formatter::FMT_PYTHON) << std::endl;std::cout << "==Numpy風格==\n" << cv::format(M, cv::Formatter::FMT_NUMPY) << std::endl;std::cout << "==C風格==\n" << cv::format(M, cv::Formatter::FMT_C) << std::endl;std::cout << std::endl << std::endl << std::endl;M.row(3) = M.row(3) + M.row(5) * 3;cv::Mat M1;M.col(5).copyTo(M1);std::cout << "==默認風格==\n" << cv::format(M, cv::Formatter::FMT_DEFAULT) << std::endl;std::cout << "==Python風格==\n" << cv::format(M, cv::Formatter::FMT_PYTHON) << std::endl;std::cout << "==Numpy風格==\n" << cv::format(M, cv::Formatter::FMT_NUMPY) << std::endl;std::cout << "==C風格==\n" << cv::format(M, cv::Formatter::FMT_C) << std::endl;std::cout << "==Python風格==\n" << cv::format(M1, cv::Formatter::FMT_PYTHON) << std::endl;std::cout << std::endl << std::endl;cv::Mat img(cv::Size(320, 240), CV_8UC3);cv::Mat roi(img, cv::Rect(10, 10, 100, 100));roi = cv::Scalar(255, 0, 0);cv::imshow("image", img);cv::waitKey(0);cv::Mat A = cv::Mat::eye(10, 10, CV_32S);cv::Mat B = A(cv::Range::all(), cv::Range(1, 3));cv::Mat C = B(cv::Range(5, 9), cv::Range::all());cv::Size size; cv::Point ofs;C.locateROI(size, ofs);std::cout << cv::format(A, cv::Formatter::FMT_PYTHON) << std::endl;std::cout << cv::format(B, cv::Formatter::FMT_PYTHON) << std::endl;std::cout << cv::format(C, cv::Formatter::FMT_PYTHON) << std::endl;std::cout << "size = " << size << ", ofs = " << ofs << std::endl;return 0; }輸出結果
==默認風格== [ 23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25;23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25;23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25;23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25;23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25;23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25] ==Python風格== [[[ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25]],[[ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25]],[[ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25]],[[ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25]],[[ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25]],[[ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25]]] ==Numpy風格== array([[[ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25]],[[ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25]],[[ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25]],[[ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25]],[[ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25]],[[ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25]]], dtype='uint8') ==C風格== { 23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25,23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25,23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25,23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25,23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25,23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25} ==默認風格== [ 23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25;23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25;23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25;92, 96, 100, 92, 96, 100, 92, 96, 100, 92, 96, 100, 92, 96, 100, 92, 96, 100;23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25;23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25] ==Python風格== [[[ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25]],[[ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25]],[[ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25]],[[ 92, 96, 100], [ 92, 96, 100], [ 92, 96, 100], [ 92, 96, 100], [ 92, 96, 100], [ 92, 96, 100]],[[ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25]],[[ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25]]] ==Numpy風格== array([[[ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25]],[[ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25]],[[ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25]],[[ 92, 96, 100], [ 92, 96, 100], [ 92, 96, 100], [ 92, 96, 100], [ 92, 96, 100], [ 92, 96, 100]],[[ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25]],[[ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25], [ 23, 24, 25]]], dtype='uint8') ==C風格== { 23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25,23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25,23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25,92, 96, 100, 92, 96, 100, 92, 96, 100, 92, 96, 100, 92, 96, 100, 92, 96, 100,23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25,23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25, 23, 24, 25} ==Python風格== [[ 23, 24, 25],[ 23, 24, 25],[ 23, 24, 25],[ 92, 96, 100],[ 23, 24, 25],[ 23, 24, 25]] [[1, 0, 0, 0, 0, 0, 0, 0, 0, 0],[0, 1, 0, 0, 0, 0, 0, 0, 0, 0],[0, 0, 1, 0, 0, 0, 0, 0, 0, 0],[0, 0, 0, 1, 0, 0, 0, 0, 0, 0],[0, 0, 0, 0, 1, 0, 0, 0, 0, 0],[0, 0, 0, 0, 0, 1, 0, 0, 0, 0],[0, 0, 0, 0, 0, 0, 1, 0, 0, 0],[0, 0, 0, 0, 0, 0, 0, 1, 0, 0],[0, 0, 0, 0, 0, 0, 0, 0, 1, 0],[0, 0, 0, 0, 0, 0, 0, 0, 0, 1]] [[0, 0],[1, 0],[0, 1],[0, 0],[0, 0],[0, 0],[0, 0],[0, 0],[0, 0],[0, 0]] [[0, 0],[0, 0],[0, 0],[0, 0]] size = [10 x 10], ofs = [1, 5]- 為用戶分配的數據創建一個標頭。 執行以下操作可能很有用:
這種用戶分配數據的部分但非常常見的情況是從 CvMat 和 IplImage 到 Mat 的轉換。為此,函數 cv::cvarrToMat 采用指向 CvMat 或 IplImage 的指針以及指示是否復制數據的可選標志。
Ptr<IplImage> iplimg(cvLoadImage(imagename.c_str())); // Ptr<T> is safe ref-counting pointer class if(!iplimg) {fprintf(stderr, "Can not load image %s\n", imagename.c_str());return -1; } Mat img = cv::cvarrToMat(iplimg); // cv::Mat replaces the CvMat and IplImage, but it's easy to convert // between the old and the new data structures (by default, only the header // is converted, while the data is shared)- 使用 MATLAB 風格的數組初始化器 zeros()、ones()、eye()
- 使用逗號分隔的初始化
使用這種方法,您首先使用適當的參數調用 Mat 類的構造函數,然后只需將 << 運算符放在逗號分隔的值后面,這些值可以是常量、變量、表達式等。另外,請注意避免編譯錯誤所需的額外括號。
測試代碼
#include <opencv2/highgui.hpp> #include <opencv2/imgcodecs.hpp> #include <opencv2/imgproc.hpp> #include <iostream>int main() {cv::Mat M(5, 5, CV_64FC3, cv::Scalar(1, 3, 5));std::cout << cv::format(M, cv::Formatter::FMT_PYTHON) << std::endl;std::cout << std::endl;M += cv::Mat::eye(M.rows, M.cols, CV_64FC3);std::cout << cv::format(M, cv::Formatter::FMT_PYTHON) << std::endl;std::cout << std::endl;cv::Mat M1 = (cv::Mat_<double>(3, 3) << 1, 0, 0, 0, 1, 0, 0, 0, 1);std::cout << cv::format(M1, cv::Formatter::FMT_PYTHON) << std::endl;return 0; }輸出結果
[[[1, 3, 5], [1, 3, 5], [1, 3, 5], [1, 3, 5], [1, 3, 5]],[[1, 3, 5], [1, 3, 5], [1, 3, 5], [1, 3, 5], [1, 3, 5]],[[1, 3, 5], [1, 3, 5], [1, 3, 5], [1, 3, 5], [1, 3, 5]],[[1, 3, 5], [1, 3, 5], [1, 3, 5], [1, 3, 5], [1, 3, 5]],[[1, 3, 5], [1, 3, 5], [1, 3, 5], [1, 3, 5], [1, 3, 5]]][[[2, 3, 5], [1, 3, 5], [1, 3, 5], [1, 3, 5], [1, 3, 5]],[[1, 3, 5], [2, 3, 5], [1, 3, 5], [1, 3, 5], [1, 3, 5]],[[1, 3, 5], [1, 3, 5], [2, 3, 5], [1, 3, 5], [1, 3, 5]],[[1, 3, 5], [1, 3, 5], [1, 3, 5], [2, 3, 5], [1, 3, 5]],[[1, 3, 5], [1, 3, 5], [1, 3, 5], [1, 3, 5], [2, 3, 5]]][[1, 0, 0],[0, 1, 0],[0, 0, 1]]創建數組后,它會通過引用計數機制自動進行管理。如果數組頭建立在用戶分配的數據之上,你應該自己處理數據。 當沒有人指向它時,數組數據被釋放。如果要在調用數組析構函數之前釋放數組頭指向的數據,請使用 Mat::release()。
關于數組類的下一個重要知識是元素訪問。 本手冊已經描述了如何計算每個數組元素的地址。通常,不需要在代碼中直接使用公式。 如果知道數組元素類型(可以使用方法 Mat::type() 檢索),可以訪問二維數組的元素 M i j M_{ij} Mij?,如下所示:
M.at<double>(i,j) += 1.f;假設 M 是一個雙精度浮點數組。 對于不同數量的維度,該方法有幾種變體。如果您需要處理二維數組的一整行,最有效的方法是先獲取指向該行的指針,然后只需使用普通的 C 運算符 [] :
// compute sum of positive matrix elements // (assuming that M is a double-precision matrix) double sum = 0; for(int i = 0; i < M.rows; i++) {const double* Mi = M.ptr<double>(i);for(int j = 0; j < M.cols; j++)sum += std::max(Mi[j], 0.); }某些操作,例如上面的操作,實際上并不依賴于數組形狀。它們只是一個一個地處理一個數組的元素(或來自多個具有相同坐標的數組的元素,例如,數組加法)。這樣的操作被稱為 element-wise。 檢查所有輸入/輸出數組是否連續是有意義的,即在每行的末尾沒有間隙。如果是,則將它們作為長單行處理:
// compute the sum of positive matrix elements, optimized variant double sum=0; int cols = M.cols, rows = M.rows; if(M.isContinuous()) {cols *= rows;rows = 1; } for(int i = 0; i < rows; i++) {const double* Mi = M.ptr<double>(i);for(int j = 0; j < cols; j++)sum += std::max(Mi[j], 0.); }在連續矩陣的情況下,外部循環體只執行一次。 因此,開銷較小,這在小矩陣的情況下尤其明顯。最后,還有 STL 風格的迭代器,它們足夠聰明,可以跳過連續行之間的間隙:
// compute sum of positive matrix elements, iterator-based variant double sum=0; MatConstIterator_<double> it = M.begin<double>(), it_end = M.end<double>(); for(; it != it_end; ++it)sum += std::max(*it, 0.);測試代碼
#include <opencv2/highgui.hpp> #include <opencv2/imgcodecs.hpp> #include <opencv2/imgproc.hpp> #include <iostream>int main() {cv::Mat M = (cv::Mat_<double>(3, 3) << -1, 0, 1, 0, 1, -1, 1, -1, 0);std::cout << cv::format(M, cv::Formatter::FMT_PYTHON) << std::endl;std::cout << std::endl;M.at<double>(2, 1) += 1.f;std::cout << cv::format(M, cv::Formatter::FMT_PYTHON) << std::endl;double sum = 0;int cols = M.cols, rows = M.rows;if (M.isContinuous()){cols *= rows;rows = 1;}for (int i = 0; i < rows; i++){const double* Mi = M.ptr<double>(i);for (int j = 0; j < cols; j++)sum += std::max(Mi[j], 0.);}std::cout << "sum = " << sum << std::endl;double sum1 = 0;cv::MatConstIterator_<double> it = M.begin<double>(), it_end = M.end<double>();for (; it != it_end; ++it)sum1 += (std::max)(*it, 0.);std::cout << "sum1 = " << sum1 << std::endl;return 0; }輸出結果
[[-1, 0, 1],[0, 1, -1],[1, -1, 0]][[-1, 0, 1],[0, 1, -1],[1, 0, 0]] sum = 3 sum1 = 3總結
以上是生活随笔為你收集整理的OpenCV中基本数据类型Mat类使用简析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 第11周【项目5 - 迷宫问题之图深度优
- 下一篇: 救救孩子吧