OpenCV中的数据结构

来源:互联网 发布:mac三维建模软件 编辑:程序博客网 时间:2024/05/11 19:33

  图像的存储方式

在之前的程序中,我们已经使用过IplImage这个数据类型,IplImage是OpenCV1.0中图像的基本数据结构,也是OpenCV1.0最常用的数据类型。下图为我们展示了三种数据结构之间的继承或派生关系:

                                                 

虽然,OpenCV1.0是用C语言实现的,但我们仍然可以在此运用面向对象的思想。

CvArr , CvMat , IplImage 均为结构体,IplImage由CvMat派生,而CvMat由CvArr派生。先查看CvArr 的定义:



可以看到CvArr 并没有具体数据类型的定义,由注释可知,CvArr仅作为函数中接收结构体数据的形参来使用,可视为CvMat和CvArr 的抽象父类。实际上,在OpenCV1.0的库函数中,有大量的函数原型的形参都是CvArr* 类型的,可 用来接收CvMat*和IplImage*数据类型 。

继续看CvMat 的定义:

typedef structCvMat

{

    int type;

    int step;

 

    /* for internal use only */

    int* refcount;

    int hdr_refcount;

 

    union

    {

        uchar* ptr;

        short* s;

        int* i;

        float* fl;

        double* db;

    } data;

 

#ifdef __cplusplus

    union

    {

        int rows;

        int height;

    };

 

    union

    {

        int cols;

        int width;

    };

#else

    int rows;

    int cols;

#endif

 

}

CvMat;

由源代码可知,CvMat数据类型包括行(高度),列(宽度),类型(type),行数据长度(step),和指向数据的指针(data),所以CvMat实际上是一个矩阵头,存储了矩阵数据的描述信息。包括IplImage和Mat在内的图像容器,都是这种将矩阵头和数据体分开的形式,通过矩阵头的数据指针指向数据体的内存位置。

创建CvMat数据

CvMat* cvCreateMat(introws, int cols, int type); /*创建矩阵头并分配内存*/
CV_INLine CvMat cvMat((introws, int cols, int type, void*data CV_DEFAULT); /*用已有数据data初始化矩阵*/
CvMat * cvInitMatHeader(CvMat * mat, int rows, intcols, int type, void * data CV_DEFAULT(NULL), int step CV_DEFAULT(CV_AUTOSTEP));/*(用已有数据data创建矩阵头)*/

 

对于矩阵数据的访问,OpenCV提供了一些宏和库函数来实现,如:

CV_MAT_ELEM();

cvPtr1D(),cvPtr2D(),cvPtr3D(),cvPtrND()

但存取数据最有效和便捷的办法应该是通过CVMat数据结构里的data成员直接访问,示例代码如下:

         introws = mat->rows;

         intcols = mat->cols;

         cout<<rows<<endl;

         cout<<cols<<endl;

 

         for(int i = 0;i<rows;i++)

         {

                   for(int j=0;j<cols;j++)

                   {

                            cout<<(int)*(mat->data.ptr + j +i*mat->step)<<'\t';

                   }

                   cout<<endl;

         }

 

 

 

 

IplImage的定义:

 

typedef struct_IplImage

{

    int  nSize;             /* sizeof(IplImage) */

    int  ID;                /* version (=0)*/

    int  nChannels;         /* Most of OpenCV functionssupport 1,2,3 or 4 channels */

    int  alphaChannel;      /* Ignored by OpenCV */

    int  depth;             /* Pixel depth in bits:IPL_DEPTH_8U, IPL_DEPTH_8S, IPL_DEPTH_16S,

                               IPL_DEPTH_32S,IPL_DEPTH_32F and IPL_DEPTH_64F are supported. */

    char colorModel[4];     /* Ignored by OpenCV*/

    char channelSeq[4];     /* ditto */

    int  dataOrder;         /* 0 - interleaved colorchannels, 1 - separate color channels.

                               cvCreateImagecan only create interleaved images */

    int  origin;            /* 0 - top-left origin,

                               1 - bottom-leftorigin (Windows bitmaps style).  */

    int  align;             /* Alignment of image rows (4or 8).

                               OpenCV ignoresit and uses widthStep instead.    */

    int  width;             /* Image width inpixels.                           */

    int  height;            /* Image height inpixels.                          */

    struct _IplROI *roi;    /* Image ROI. IfNULL, the whole image is selected. */

    struct _IplImage *maskROI;      /* Must be NULL. */

    void  *imageId;                 /* "           " */

    struct _IplTileInfo *tileInfo;  /* "           " */

    int  imageSize;         /* Image data size in bytes

                              (==image->height*image->widthStep

                               in case ofinterleaved data)*/

    char *imageData;        /* Pointer to alignedimage data.         */

    int  widthStep;         /* Size of aligned image rowin bytes.    */

    int BorderMode[4];     /* Ignored byOpenCV.                     */

    int BorderConst[4];    /* Ditto.                                 */

    char *imageDataOrigin;  /* Pointer to veryorigin of image data

                               (not necessarilyaligned) -

                               needed forcorrect deallocation */

}

IplImage;

 

相比于CVMat,IplImage增加了一些成员变量使之可被解释为图像。一些重要的成员变量如下:

int width:图像宽度(列)

 int height:图像高度(行)

int  widthStep:矩阵中每一行数据所占的内存大小

int imageSize:图像在所占内存空间大小,单位为字节(注意:与成员变量nSize区别开,nSize 返回的是sizeof(IplImage),即矩阵头的大小,   

imageSize==image->height*image->widthStep,即数据矩阵所占空间大小)

int nChannels: 通道数

 

相应输出:


 

char*imageData :指向图像数据的指针,CVMat中的data

代码(按行遍历输出数据):


输出结果:


 

关于通道的概念:

比较通俗易懂的解释是:灰度图的通道数为1,彩色图的通道为3。基本上,描述一个像素点,如果是灰度,那么只需要一个数值来描述它,就是单通道。如果一个像素点,有RGB三种颜色来描述它,就是三通道。

实际上,通道数可取的值是1,2,3和4.

灰度图(单通道):


RGB图(三通道):


现在考虑之前的代码,采用彩色图的读取方式,通道值为3,从之前的输出可以看到成员width和widthStep正好是1:3的关系;

将图像的读取方式改为灰度图,再进行输出如下:


此时width和widthStep正好相等,imageSize也缩小为原来的1/3,读者可自行检测。

 

Mat数据类型:

Mat是opencv2.0推出的新的数据结构,基本可以取代之前的cvMat和lplImage,相比之下Mat最大的好处就是能够更加方便的进行内存管理,不再需要程序员手动管理内存的释放。

源文件中的定义:

。。。

太长了。。。

OpenCV2.0之后采用C++实现,真正引入了面向对象的思想,Mat是一个类,同样有矩阵头和数据体两部分,部分定义如下:

class CV_EXPORTS Mat{ public: /*..很多方法..*//*............*/ int flags;(Note :目前还不知道flags做什么用的)int dims;  /*数据的维数*/int rows,cols; /*行和列的数量;数组超过2维时为(-1,-1)*/uchar *data;   /*指向数据*/int * refcount;   /*指针的引用计数器; 阵列指向用户分配的数据时,指针为 NULL /* 其他成员 */ ... };
重要成员变量:

rows,cols:  行和列,等同于lplImage中的width和height

data:指向存储像素值的矩阵的指针,等同于lplImage中的imageData

refcount:OpenCV是用了引用计数机制,每个Mat对象都有自己的信息头,但可以共享同一个矩阵,通过data指针指向同一地址来实现。当进行复制的时候,只复制信息头,而不进行矩阵的复制。

在理解CVMat和lplImage之后,再来看Mat数据类型就不难了,可以自行阅读Mat类定义的源代码,以获得更深层次 的理解。


  OpenCV中其他基本数据类型

结构

成员

意义

Point或point2i(f)

 x,y

二维点

Point3i(f)

 x,y,z

三维点

Size

width,height

图像尺寸

Rect

x,y,width,height

矩形

Scalar

double val[4]

颜色的表示

 

OPenCV1.0中的版本:

结构

成员

意义

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]

颜色的表示



0 0
原创粉丝点击