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;
}

 

 

 

 

posted @ 2012-10-28 18:15  Frandy.CH  阅读(4993)  评论(0编辑  收藏  举报