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,不复制数据只创建矩阵头
原文地址:https://www.cnblogs.com/shhu1993/p/4897406.html