OpenCV學習筆記(2):Mat矩陣的初始化和元素訪問

在研究Mat矩陣的初始化的時候,發現其不能像Matx輕量級矩陣那樣,直接利用數組來進行初始化,而是利用一個內部的變數類型:Scalar來進行初始化的。參考手冊中的構造函數如下所示:

(1) Mat::Mat()
(2) Mat::Mat(int rows, int cols, int type)
(3) Mat::Mat(Size size, int type)
(4) Mat::Mat(int rows, int cols, int type, constScalar& s)
(5) Mat::Mat(Size size, int type, constScalar& s)
(6) Mat::Mat(const Mat& m)
(7) Mat::Mat(int rows, int cols, int type, void* data, size_t step=AUTO_STEP)
(8) Mat::Mat(Size size, int type, void* data, size_t step=AUTO_STEP)
(9) Mat::Mat(const Mat& m, const Range& rowRange, const Range& colRange)
(10) Mat::Mat(const Mat& m, const Rect& roi)
(11) Mat::Mat(const CvMat* m, bool copyData=false)
(12) Mat::Mat(const IplImage* img, bool copyData=false)
(13) template<typename T, int n> explicit Mat::Mat(const Vec<T, n>& vec, bool copyData=true)
(14) template<typename T, int m, int n> explicit Mat::Mat(const Matx<T, m, n>& vec, bool copyData=true)
(15) template<typename T> explicit Mat::Mat(const vector<T>& vec, bool copyData=false)
(16) Mat::Mat(const MatExpr& expr)
(17) Mat::Mat(int ndims, const int* sizes, int type)
(18) Mat::Mat(int ndims, const int* sizes, int type, constScalar& s)
(19) Mat::Mat(int ndims, const int* sizes, int type, void* data, const size_t* steps=0)
(20) Mat::Mat(const Mat& m, const Range* ranges)

似乎這樣的矩陣讓我們用起來感覺很不順手,不過接著往下讀參考手冊,你會發現這樣一個例子:

Mat H(100, 100, CV_64F); for(int i = 0; i < H.rows; i++) for(int j = 0; j < H.cols; j++) H.at<double>(i,j)=1./(i+j+1);

通過這個例子,我們嘗試來給Mat類型初始化。

第一種改進:(直接由以上例子仿製而來)

//用一個常數來初始化矩陣

void InitMat(Mat& m,float t){for(int i=0;i<m.rows;i++)for(int j=0;j<m.cols;j++)m.at<float>(i,j)=t;}

主程序:

int _tmain(int argc, _TCHAR* argv[]){//Mat矩陣中的初始化,可以利用Mat::at()來完成Mat M0(3,3,CV_32F);InitMat(M0,3);}

第二種改進:

//用一個一維數組來初始化矩陣

void InitMat(Mat& m,float* num){for(int i=0;i<m.rows;i++)for(int j=0;j<m.cols;j++)m.at<float>(i,j)=*(num+i*m.rows+j);}

主程序:

int _tmain(int argc, _TCHAR* argv[]){//Mat矩陣中的初始化,可以利用Mat::at()來完成float m0[]={1,2,3,6,5,4,7,8,9};

Mat M0(3,3,CV_32F);InitMat(M0,m0);}

第三種改進:

//希望利用二維數組來初始化

void InitMat(Mat& m,float(*p)[3]){for(int i=0;i<m.rows;i++)for(int j=0;j<m.cols;j++)m.at<float>(i,j)=*(*(p+i)+j);}

主程序:

int _tmain(int argc, _TCHAR* argv[]){//Mat矩陣中的初始化,可以利用Mat::at()來完成float m[][3]={1,2,3,6,5,4,7,8,9};

Mat M0(3,3,CV_32F);InitMat(M0,m);}

然而,注意在傳遞二維數組的時候,第三種方法的局限性在於必須要知道每一維度的元素個數,其實可以將二維數組,例如a[2][3]的數組名稱a直接轉換成一個float指針傳遞進去,當成一位數組使用。即,

主程序:

int _tmain(int argc, _TCHAR* argv[]){//Mat矩陣中的初始化,可以利用Mat::at()來完成float m[][3]={1,2,3,6,5,4,7,8,9};

Mat M0(3,3,CV_32F);InitMat(M0,(float*)m);}

註:

數組和指針在參數傳遞時的對應關係: 實參形參數組的數組: char a[8][10] char(*p)[10]指針的數組: char *a[10] char **p數組指針(行指針):char(*a)[8] char(a)[8]指針的指針:char **a char**a

結果運行截圖如下:

附註:有關多維數組的參數傳遞問題,詳細參見《C專家編程,Page225》


推薦閱讀:

OPENCV3.1(含Contribute)配置教程(WIN7+VS2015/Codeblocks)--簡單易懂
如何進行模糊檢測
OpenCV之像素操作
如何學習C++圖像處理?
1.25【OpenCV圖像處理】直方圖反向投影

TAG:學習 | 矩陣 | 筆記 | OpenCV | 訪問 |