• 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;
    }
  • 相关阅读:
    Mybaits 的优点
    mybatis中#{}和${}的区别
    springmvc工作流程
    request对象的主要方法有哪些
    如何决定选用HashMap还是TreeMap?
    队列和栈是什么,列出它们的区别?
    fail-fast与fail-safe有什么区别?
    Collections类是什么?
    哪些集合类提供对元素的随机访问?
    可以作为GC Roots的对象包括哪些
  • 原文地址:https://www.cnblogs.com/Frandy/p/opencv_cvmat_mat.html
Copyright © 2020-2023  润新知