OpenCV(1)——基礎數據結構CvMat


在OpenCV中,矩陣是一個基礎的數據結構,在CvCore中。在較早版本里面,使用的是C語言實現的struct,較新的版本里面有C++實現的class。下面分別介紹一下這兩種使用方法。

CvMat

參考http://www.opencv.org.cn/index.php/Cxcore%E5%9F%BA%E7%A1%80%E7%BB%93%E6%9E%84

在OpenCV的中文首頁上,文檔里面給的還是C實現的結構體。如下,

typedef struct CvMat
 {
  int type; /* CvMat 標識 (CV_MAT_MAGIC_VAL), 元素類型和標記 */
  int step; /* 以字節為單位的行數據長度*/
  int* refcount; /* 數據引用計數 */
  union
   {
    uchar* ptr;
    short* s;
    int* i;
    float* fl;
    double* db;
   } data; /* data 指針 */
  #ifdef __cplusplus
  union
   {
     int rows;
     int height;
   };
  union
   {
     int cols;
     int width;
   };
  #else
   int rows; /* 行數 */
   int cols; /* 列數*/
  #endif
 } CvMat;

對矩陣的操作,參考,http://blog.csdn.net/schoolers/article/details/4758838

對矩陣的操作,

//創建矩陣,分配矩陣空間,
  CvMat* cvCreateMat(int rows, int cols, int type);
// type: 矩陣元素類型. 格式為CV_<bit_depth>(S|U|F)C<number_of_channels>.  
// 例如: CV_8UC1 表示8位無符號單通道矩陣, CV_32SC2表示32位有符號雙通道矩陣.
//釋放矩陣空間,
    CvMat* M = cvCreateMat(4,4,CV_32FC1);  
    cvReleaseMat(&M);  
//可以從數組創建矩陣,
    double a[] = { 1,   2,   3,   4,   5,   6,   7,   8, 9, 10, 11, 12 };  
    CvMat Ma=cvMat(3, 4, CV_64FC1, a);   

//存取矩陣元素,
//二維浮點數矩陣,
//間接存取
    cvmSet(M,i,j,2.0); // Set M(i,j)  
    t = cvmGet(M,i,j); // Get M(i,j)  
//直接存取,
    CvMat* M     = cvCreateMat(4,4,CV_32FC1);  
    int n  = M->cols;  
    float *data = M->data.fl;  
    data[i*n+j] = 3.0;  
//用數組初始化矩陣的時候,可以直接操作數組,
    double a[16];  
    CvMat Ma = cvMat(3, 4, CV_64FC1, a);  
    a[i*4+j] = 2.0; // Ma(i,j)=2.0;  

對於矩陣的其它操作,比如加減乘除,SVD分解等,這里略去。

 

下面是使用C++的接口,參考http://opencv.willowgarage.com/documentation/cpp/core_basic_structures.html

View Code
class CV_EXPORTS Mat
{
public:
    // ... a lot of methods ...
    ...

    /*! includes several bit-fields:
         - the magic signature
         - continuity flag
         - depth
         - number of channels
     */
    int flags;
    //! the array dimensionality, >= 2
    int dims;
    //! the number of rows and columns or (-1, -1) when the array has more than 2 dimensions
    int rows, cols;
    //! pointer to the data
    uchar* data;

    //! pointer to the reference counter;
    // when array points to user-allocated data, the pointer is NULL
    int* refcount;

    // other members
    ...
};
//創建矩陣,可以使用構造函數,如下,
    Mat::Mat()
    Mat::Mat(int rows, int cols, int type)
//如果初始化的時候沒有傳入size的參數,或者后面需要改變size的參數,可以使用create來調整。
    create(nrows, ncols, type)
//如下,
// make 7x7 complex matrix filled with 1+3j.
    cv::Mat M(7,7,CV_32FC2,Scalar(1,3));
// and now turn M to 100x60 15-channel 8-bit matrix.
// The old content will be deallocated
    M.create(100,60,CV_8UC(15));

//釋放資源,可以使用 release()成員函數。

//也可以使用一維或多維數組來初始化矩陣,
    double m[3][3] = {{a, b, c}, {d, e, f}, {g, h, i}};
    cv::Mat M = cv::Mat(3, 3, CV_64F, m);

//元素的訪問,
    template<typename T> T& Mat::at(int i, int j)
    template<typename T> const T& Mat::at(int i, int j) const
    template<typename T> T& Mat::at(int i, int j, int k)
    template<typename T> const T& Mat::at(int i, int j, int k) const
//    i, j, k – Indices along the dimensions 0, 1 and 2, respectively
//在矩陣是行向量或列向量的時候,也可以只用一個參數來訪問元素。

//類似於C++里面的迭代器,Mat也可以使用iterator。

另外有兩個問題稍作討論,

cvCreateMat的使用,

void Create(CvMat*& mat,int rows,int cols)
//void Create(CvMat* mat,int rows,int cols)
{    
    mat = cvCreateMat(rows,cols,CV_32FC1);
}

一開始使用的是注釋掉的那一行,在調用這個函數之后,mat本應該被初始化的,但在后面的訪問中會出現問題,后來將參數改為指針引用,才解決錯誤。

另一個問題是C++里面矩陣的定義是cv::mat,但在很多舊的函數里面,要求傳入的參數是CvMat*,如何進行轉換呢?

 

這里很多都只適用於2維矩陣,對於多維的矩陣,OpenCV也是支持的。OpenCV里面矩陣的大小為rows*cols,但在每個位置,由channel控制這個點的維數。比如復數矩陣,這個點可以用2個channels來表示一個復數。元素訪問的時候可以使用i,j,k三個參數。
參考,http://stackoverflow.com/questions/1824787/opencv-multi-channel-element-access
或者在定義數據類型的時候,不是使用CV_32FC3之類的,而是自定義類型,比如

struct elem{
    double f1;
    doubel f2;
}

那么就可以先訪問到elem,然后再通過elem訪問f1和f2.

就這么多吧,隨便整理的一些,沒有辦法靜下來好好整理。
一個簡單的實例程序如下,

// test for cvCreateMat

#include "cxcore.h"

#include <cstdio>

//void Create(CvMat*& mat,int rows,int cols)
void Create(CvMat*& mat,int rows,int cols)
{    
    mat = cvCreateMat(rows,cols,CV_32FC1);
}

void Init(CvMat* mat)
{
    int i=0,j=0,k=0;
    int rows = mat->rows;
    int cols = mat->cols;
    for(i=0;i<rows;i++)
    {
        for(j=0;j<cols;j++)
        {
            cvmSet(mat,i,j,i+1.0*j/10);
        }
    }
}

void Print(CvMat* mat)
{
    int i=0,j=0,k=0;
    int rows = mat->rows;
    int cols = mat->cols;
    float tm = 0;
    for(i=0;i<rows;i++)
    {
        for(j=0;j<cols;j++)
        {
            tm = cvmGet(mat,i,j);
            printf("%4g ",tm);
        }
        printf("\n");
    }
}

int main()
{
    CvMat* mat;
    Create(mat,4,5);
    Init(mat);
    Print(mat);
    return 0;
}

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM