• Opencv 的数据结构


    opencv的基本数据结构

    结构 成员 意义
    CvPoint int x,y 图像中的点
    CvPoint2D32f float x,y 二维空间中的点
    CvPoint3D32f float x,y,z 三维空间中的点
    CvSize int width,height 图像的尺寸
    CvRect int x,y,width,height 图像的部分区域
    CvScalar double val[4] RGBA值

    Mat 数据结构

    1. Mat类型侧重于计算,数学性较高,openCV对Mat类型的计算也进行了优化。而CvMat和IplImage类型更侧重于“图像”,opencv对其中的图像操作(缩放、单通道提取、图像阈值操作等)进行了优化。在opencv2.0之前,opencv是完全用C实现的,但是,IplImage类型与CvMat类型的关系类似于面向对象中的继承关系。实际上,CvMat之上还有一个更抽象的基类----CvArr,这在源代码中会常见。
    2. Mat是opencv2.0推出的处理图像的新的数据结构,现在越来越有趋势取代之前的cvMat和lplImage,相比之下Mat最大的好处就是能够更加方便的进行内存管理,不再需要程序员手动管理内存的释放
    3. IplImage,CvMat,Mat的关系参考

    Mat的结构,是一个类,本身就带有很多的函数,成员,重载

    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也是一个矩阵头,,由两个数据部分组成:矩阵头(包含矩阵尺寸,存储方法,存储地址等信息)和一个指向存储所有像素值的矩阵(根据所选存储方法的不同矩阵可以是不同的维数)的指针。默认不分配内存,只是指向一块内存(注意读写保护)。
    但矩阵本身的尺寸会依图像的不同而不同,通常比矩阵头的尺寸大数个数量级。因此,当在程序中传递图像并创建拷贝时,大的开销是由矩阵造成的,而不是信息头。
    为了搞定这个问题,OpenCV使用引用计数机制。其思路是让每个 Mat 对象有自己的信息头,但共享同一个矩阵。这通过让矩阵指针指向同一地址而实现。而拷贝构造函数则 只拷贝信息头和矩阵指针 ,而不拷贝矩阵。

    初始化使用create函数或者Mat构造函数

    但某些时候你仍会想拷贝矩阵本身(不只是信息头和矩阵指针),这时可以使用函数 clone() 或者 copyTo()

    /*CV_32FC2的定义:*/
    CV_[The number of bits per item][Signed or Unsigned][Type Prefix]C[The channel number]
    
    

    初始化例子

    Mat(nrows, ncols, type, fillValue); 
    M.create(nrows, ncols, type);
    
    初始化:
    Mat M(7,7,CV_32FC2,Scalar(1,3)); /*创建复数矩阵1+3j*/
    M.create(100, 60, CV_8UC(15)); /*创建15个通道的8bit的矩阵*/
    
    /*创建100*100*100的8位数组*/
    int sz[] = {100, 100, 100}; 
    Mat bigCube(3, sz, CV_8U, Scalar:all(0));
    
    /*现成数组*/
    double m[3][3] = {{a, b, c}, {d, e, f}, {g, h, i}};
    Mat M = Mat(3, 3, CV_64F, m).inv();
    
    /*图像数据*/
    Mat img(Size(320,240),CV_8UC3); 
    Mat img(height, width, CV_8UC3, pixels, step); /*const unsigned char* pixels,int width, int height, int step*/
    
    /*使用现成图像初始化Mat*/
    IplImage* img = cvLoadImage("greatwave.jpg", 1);
    Mat mtx(img); // convert IplImage* -> Mat; /*不复制数据,只创建一个数据头*/
    

    CvMat的结构 ,只是一个数据结构,很多的实现要借助与其他的函数

    typedef struct CvMat{
      int type;
      int step;
      int* refcount;
      union{
      uchar* ptr;
      short* s;
      int* i;
      float *f1;
      double* db;
      } data;
         union{
      int rows;
      int height;
      };
         union{
      int cols;
      int width;
      };
    }CvMat;
    

    矩阵的创建和释放

    CvMat* cvCreateMat( int rows, int cols, int type );  //创建一个矩阵
    CvMat* cvCreateMatHeader( int rows, int cols, int type ); //创建一个矩阵结构,不分配空间
    CvMat* cvInitMatHeader(CvMat* mat,int rows,int cols,int type,void* data = NULL,int step = CV_AUTOSTEP);//用一个现有矩阵初始化矩阵
    CvMat cvMat(int rows,int cols,int type,void* data = NULL);//初始化矩阵结构,不分配空间
    CvMat* cvCloneMat( const cvMat* mat );//复制一个mat副本
    void cvReleaseMat( CvMat** mat ); //释放矩阵
    

    CvMat, Mat, IplImage之间的互相转换

    IpIImage -> CvMat
    /*cvGetMat*/
    CvMat matheader;
    CvMat * mat = cvGetMat(img, &matheader);
    /*cvConvert*/
    CvMat * mat = cvCreateMat(img->height, img->width, CV_64FC3);
    cvConvert(img, mat)
    
    
    IplImage -> Mat
    Mat::Mat(const IplImage* img, bool copyData=false);/*default copyData=false,与原来的IplImage共享数据,只是创建一个矩阵头*/
    例子:
    IplImage* iplImg = cvLoadImage("greatwave.jpg", 1);
    Mat mtx(iplImg); /* IplImage * -> Mat,共享数据; or : Mat mtx = iplImg;*/
    
     
    
    Mat -> IplImage
    Mat M
    IplImage iplimage = M; /*只创建图像头,不复制数据*/
    
    CvMat -> Mat
    Mat::Mat(const CvMat* m, bool copyData=false); /*类似IplImage -> Mat,可选择是否复制数据*/
    
    Mat -> CvMat
    例子(假设Mat类型的imgMat图像数据存在):
    CvMat cvMat = imgMat;/*Mat -> CvMat, 类似转换到IplImage,不复制数据只创建矩阵头
    
  • 相关阅读:
    获取class
    domReady
    JS原型
    JavaScript继承
    LeetCode 46. Permutations
    LinkCode 第k个排列
    接口测试基础——第5篇xlrd模块
    接口测试基础——第4篇logging模块
    接口测试基础——第3篇smtplib发送带图片的邮件
    接口测试基础——第2篇smtplib发送带附件的邮件
  • 原文地址:https://www.cnblogs.com/shhu1993/p/4897406.html
Copyright © 2020-2023  润新知