創建Mat類的幾種常見方法

There are many different ways to create a Mat object. The most popular options are listed below:

有許多不同的方法可以創建一個Mat對象,下面列出幾個最常用的方法。

  • Use the create(nrows, ncols, type) method or the similar Mat(nrows, ncols, type, fillValue) constructor. A new array of the specified size and type is allocated. type has the same meaning as in the cvCreateMat method. For example, CV_8UC1 means a 8-bit single-channel array, CV_32FC2 means a 2-channel (complex) floating-point array, and so on.

    使用create(nrows, ncols, type)的方法或是類似的Mat(nrows, ncols, type, fillValue)的這種構造。一個新的確定大小和類型的數組就被分配好了。type與cvCreateMat方法中具有相似的意義,指定的是數組的類型(例如CV_8UC1,CV_32FC2等等)。

    // 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 、、、這裏是說,當使用create()時,原來7*7的M數組將被釋放了,重新分配了一個100*60的15通道的8位數組
    M.create(100,60,CV_8UC(15));
    

    As noted in the introduction to this chapter, create() allocates only a new array when the shape or type of the current array are different from the specified ones.

    create()函數會分配一個新的數組,當目前數組的形狀或類型與指定的(或之前的)不同時。

  • Create a multi-dimensional array:創建一個多維的數組

    // create a 100x100x100 8-bit array
    int sz[] = {100, 100, 100};
    Mat bigCube(3, sz, CV_8U, Scalar::all(0));
    

    It passes the number of dimensions =1 to the Mat constructor but the created array will be 2-dimensional with the number of columns set to 1. So, Mat::dims is always >= 2 (can also be 0 when the array is empty).

    它將維度數(= 1)傳遞給Mat的構造函數,但列數設置爲 1時,創建數組將是 2 維的。因此,Mat::dims 始終是>=2的(該數組爲空時,也可以是 0)。(也不是很懂啥意思)

  • Use a copy constructor or assignment operator where there can be an array or expression on the right side (see below). As noted in the introduction, the array assignment is an O(1) operation because it only copies the header and increases the reference counter. The Mat::clone() method can be used to get a full (deep) copy of the array when you need it.

    使用一個複製構造函數或者賦值操作運算符,可以生成一個數組或是表達式。數組賦值運算的複雜度是O(1),因爲它僅複製數組頭和增加引用計數。而Mat::clone()的方法可以獲得一個全(深)的副本數組。

  • Construct a header for a part of another array. It can be a single row, single column, several rows, several columns, rectangular region in the array (called a minor in algebra) or a diagonal. Such operations are also O(1) because the new header references the same data. You can actually modify a part of the array using this feature, for example:

    構造數組中部分成分的頭。它可以使一行,一列,幾行,幾列,一個數組中的矩形區域,或者是一個對角線。這樣的操作的複雜度也是o(1),因爲新構造的頭指向的是相同的數據。可以使用該方法修改數組中的指定部分,例如:

    // add the 5-th row, multiplied by 3 to the 3rd row、、將第5行乘以3,加到第3行
    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先構造了一個M1的Mat頭,指向M的第一列,然後將M的第7列複製給M1
    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)); //這個還是比較實用的,指定一幅圖像的ROI區域
    // 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);
    

    Due to the additional datastart and dataend members, it is possible to compute a relative sub-array position in the main container array using locateROI():

    由於額外的 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)
    

    As in case of whole matrices, if you need a deep copy, use the clone() method of the extracted sub-matrices.

  • Make a header for user-allocated data. It can be useful to do the following:

    1. Process “foreign” data using OpenCV (for example, when you implement a DirectShow* filter or a processing module for gstreamer, and so on). For example:

      OpenCV處理外來數據。

      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);
      }
      
    2. Quickly initialize small matrices and/or get a super-fast element access.

      快速初始化小尺寸矩陣,或者獲得一個超速的元素通道。

      double m[3][3] = {{a, b, c}, {d, e, f}, {g, h, i}};
      Mat M = Mat(3, 3, CV_64F, m).inv();
      

    Partial yet very common cases of this user-allocated data case are conversions from CvMat and IplImage to Mat. For this purpose, there are special constructors taking pointers to CvMat or IplImage and the optional flag indicating whether to copy the data or not.

    講述Mat 與 CvMat和IplImage之間的轉換。

    Backward conversion from Mat to CvMat or IplImage is provided via cast operators Mat::operator CvMat()const and Mat::operator IplImage(). The operators do NOT copy the data.

    IplImage* -> Mat-> CvMat,然後比較 IplImage 與 CvMat
    IplImage* img = cvLoadImage("greatwave.jpg", 1);
    Mat mtx(img); // convert IplImage* -> Mat
    CvMat oldmat = mtx; // convert Mat -> CvMat
    CV_Assert(oldmat.cols == img->width && oldmat.rows == img->height &&
        oldmat.data.ptr == (uchar*)img->imageData && oldmat.step == img->widthStep);
    
  • Use MATLAB-style array initializers, zeros(), ones(), eye(), for example:

    // create a double-precision identity martix and add it to M.
    M += Mat::eye(M.rows, M.cols, CV_64F);//  xxx(nrows, ncols, style)
    
  • Use a comma-separated initializer:  使用逗號分隔的初始化

    // create a 3x3 double-precision identity matrix
    Mat M = (Mat_<double>(3,3) << 1, 0, 0, 0, 1, 0, 0, 0, 1);
    

    With this approach, you first call a constructor of the Mat_ class with the proper parameters, and then you just put << operator followed by comma-separated values that can be constants, variables, expressions, and so on. Also, note the extra parentheses required to avoid compilation errors.

    使用Mat_類,然後設置類型<xxx>,之後用<<符號輸入數值,每個數值之間用逗號隔開,這種方法適合於小尺寸的初始化,同時需要注意的是書寫時不要忽略最外層的圓括號。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章