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圖像處理】直方圖反向投影