日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

OpenCV中基本数据类型Mat类使用简析

發布時間:2024/1/18 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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] 0ik?<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 通道(復數)浮點數組,以此類推。
// make a 7x7 complex matrix filled with 1+3j. Mat M(7,7,CV_32FC2,Scalar(1,3)); // and now turn M to a 100x60 15-channel 8-bit matrix. // The old content will be deallocated M.create(100,60,CV_8UC(15));

測試代碼

#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() 在當前數組的形狀或類型與指定的不同時分配一個新數組。

  • 創建一個多維數組
// create a 100x100x100 8-bit array int sz[] = {100, 100, 100}; Mat bigCube(3, sz, CV_8U, Scalar::all(0));

它將維度數 =1 傳遞給 Mat 構造函數,但創建的數組將是二維的,列數設置為 1。因此,Mat::dims 始終 >= 2(當數組為空時也可以為 0)。

  • 在右側可以有數組或表達式的地方使用復制構造函數或賦值運算符(見下文)。如介紹中所述,數組賦值是一個 O(1) 操作,因為它只復制標頭并增加引用計數器。Mat::clone() 方法可用于在需要時獲取數組的完整(深層)副本。
  • 為另一個數組的一部分構造一個標頭。它可以是單行、單列、多行、多列、數組中的矩形區域(在代數中稱為小區域)或對角線。此類操作也是 O(1),因為新標頭引用相同的數據。實際上可以使用此功能修改數組的一部分,例如:
// add the 5-th row, multiplied by 3 to the 3rd row M.row(3) = M.row(3) + M.row(5)*3; // now copy the 7-th column to the 1-st column // M.col(1) = M.col(7); // this will not work Mat M1 = M.col(1); M.col(7).copyTo(M1); // create a new 320x240 image Mat img(Size(320,240),CV_8UC3); // select a ROI Mat roi(img, Rect(10,10,100,100)); // fill the ROI with (0,255,0) (which is green in RGB space); // the original 320x240 image will be modified roi = Scalar(0,255,0);

由于額外的 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]
  • 為用戶分配的數據創建一個標頭。 執行以下操作可能很有用:
  • 使用 OpenCV 處理“外部”數據(例如,當您實現 DirectShow* 過濾器或 gstreamer 的處理模塊等時)
  • void process_video_frame(const unsigned char* pixels,int width, int height, int step) {Mat img(height, width, CV_8UC3, pixels, step);GaussianBlur(img, img, Size(7,7), 1.5, 1.5); }
  • 快速初始化小矩陣 / 獲得超快速元素訪問
  • double m[3][3] = {{a, b, c}, {d, e, f}, {g, h, i}}; Mat M = Mat(3, 3, CV_64F, m).inv();

    這種用戶分配數據的部分但非常常見的情況是從 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()
    // create a double-precision identity matrix and add it to M. M += Mat::eye(M.rows, M.cols, CV_64F);
    • 使用逗號分隔的初始化
    // create a 3x3 double-precision identity matrix Mat M = (Mat_<double>(3,3) << 1, 0, 0, 0, 1, 0, 0, 0, 1);

    使用這種方法,您首先使用適當的參數調用 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类使用简析的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。