OpenCV数据结构和绘图函数


1.        Mat数据结构详解

1.1.       Mat结构组成和适用方法

l  Mat由两个数据部分组成 : 即矩阵头 + 指向矩阵的指针。

矩阵头 = 矩阵尺寸 + 存储方法 + 储存地址等

OpenCV 每个Mat对象有属于自己的信息头,但是共享同一个矩阵,它通过矩阵指针指向同一个矩阵的地址实现。

Mat A,C;  //仅创建信息头部分

A = imread(“1.jpg”,CV_LOAD_IMAGE_COLOR); //这里为就诊开辟内存空间

Mat B(A); //拷贝构造函数

C = A; // 复制运算符

l  创建包含边界信息的信息头的方法:

Mat  D(A,Rect(10,10,100,100)); //用矩形界定

Mat  E(Range:all(),Range(1,3));//用行和列来界定

l  Mat 的引用计数概念:

每当复制一个Mat对象的信息头时,增加引用计数,

每当一个信息头被释放的时候,减小引用计数。

l  通过copyTo或clone复制矩阵

Mat F = A.clone();

Mat G;

A.copyTo(G);

l  获取图像的长和宽

Ip1Image* img = cvLoadImage(“1,jpg”,1);

Mat mtx(img);

img.width(),img.Heihgt()

1.2.       像素值的存储方法

存储像素需要指定颜色空间和数据类型。

颜色空间概念:针对一个给定的颜色,如何组合颜色元素以对其编码。

如灰度级空间,只处理黑色和白色。

彩色的颜色空间: RGB  + 透明颜色 四个元素。

颜色系统种类:

1)  RGB 显示设备所采用

2)  HSV和HLS把颜色分解成色调、饱和度和亮度透明度

3)  YCrCb在JPEG图像格式中广泛使用

4)  ClE L*a*b 是一种感知上均匀的颜色空间,他适合用来度量两个颜色之间的距离。

1.3.       创建Mat对象的方法

1)  使用Mat 构造函数

Mat M(2,2,CV_8UC3,Scalar(0,0.255));

参数1

参数2

参数3

参数4

数据类型

通道数

 

数据类型结构:

CV

位数

带符号与否

类型前缀

C

通道数

 

2)  C\C++中通过构造函数进行初始化

Int sz[3] = {2,2,2};

Mat L(3,sz,CV_8UC,Scalar::all(0));

 

3)  为已存在的Ip1Image指针创建信息头

Ip1Image* img = cvLoadImage(“1,jpg”,1);

Mat mtx(img);

 

4)  利用Create()函数

M.creat(4,4,CV_8UC(2));

Cout <<”M=”<<” ”<<M<<endl;

1.4.       OpenCV格式化输出

1.5.       常用数据结构输出

l  定义输出二维点

       Point2fp(6, 2); 

       cout<< "【?2维?点Ì?】?p = " << p << ";\n" << endl;

l  定义输出三维点

       Point3fp3f(8, 2, 0);

       cout<< "【?3维?点Ì?】?p3f = " << p3f << ";\n" << endl;

l  定义输出基于Mat的std::vector

       vector<float>v;

       v.push_back(3);

       v.push_back(5);

       v.push_back(7);

       cout<< "【?基¨´于®¨²Mat的Ì?vector】?shortvec = " << Mat(v) <<";\n"<<endl;

l  定义输出Mat的std::vector

       vector<Point2f>points(20);

       for(size_t i = 0; i < points.size(); ++i)

                 points[i]= Point2f((float)(i * 5), (float)(i % 7));

       cout<< "【?二t维?点Ì?向¨°量¢?】?points = " << points<<";";

2.        IplImage 数据结构详解

2.1.       IplImage与Mat的关系

OpenCV最初是C语言编写的一个图形库,其中IplImage是表示一个图像的结构体,也是从OpenCV1.0到目前最为重要的一个结构;

Mat是后来OpenCV封装的一个C++类,用来表示一个图像,和IplImage表示基本一致,但是Mat还添加了一些图像函数;

2.2.       IplImage与Mat 创建图像数据的不同

2.2.1.       IplImage创建图像数据

IplImage ,通过以下三个函数之一创建:

/*Allocates and initializes IplImage header */
CVAPI(IplImage*)  cvCreateImageHeader( CvSize size, int depth, intchannels );
/*Inializes IplImage header */
CVAPI(IplImage*)cvInitImageHeader( IplImage* image, CvSize size, intdepth,
                                   int channels, intorigin CV_DEFAULT(0),
                                   int align CV_DEFAULT(4));
/*Creates IPL image (header and data) */
CVAPI(IplImage*)  cvCreateImage( CvSize size, int depth, intchannels );

2.2.2.       Mat 创建图像数据

cv::Mat,直接可以通过构造函数Mat(int _rows, int _cols, int _type, void*_data, size_t _step=AUTO_STEP); 直接创建;

示例:

cv::Mat * pMat = new cv::Mat( 288, 352, CV_8UC3, imagebufdata );
IplImage IplImagetmp = IplImage(*pMat);

注意:前两个参数是图像的height和width,不是width和height;

2.2.3.      IplImage和Mat 创建图像的比较

创建内存数据图像,直接通过 cv::Mat类比较简单,然后可以通过Mat获取IplImage,通过cvCreateImage等函数创建内存图像,比较麻烦,而且创建后,还要通过cvReleaseImage等函数释放内存,所以这里建议用cv::Mat创建;

2.3.       IplImage和Mat的互相转换

l  IplImage  转  Mat: 

// extern  IplImage * plpliamge; //假设 IplImage 已经创建;

 Mat * pmatImage = new Mat( IplImage,0  ): //第二个参数表示不进行像素数据copy;

 

l  Mat 转 IplImage:

//extern Mat  matImage; //假设已经创建cv:Mat;

IplImage limage = IplImage ( matImage );//不进行数据copy;

 

通常情况对于图像的读取,IplImage 通过 cvLoadImage,   cv:Mat通过 cv::imread;

2.4.       IplImage 结构体详解 – 源代码

typedef struct _IplImage
{
    int  nSize;             /*sizeof(IplImage) */
    int  ID;                /*version (=0)*/
    int  nChannels;         /* Most ofOpenCV functions support 1,2,3 or 4 channels */
    int  alphaChannel;      /* Ignored byOpenCV */
    int  depth;             /* Pixeldepth in bits: IPL_DEPTH_8U, IPL_DEPTH_8S, IPL_DEPTH_16S,
                               IPL_DEPTH_32S,IPL_DEPTH_32F and IPL_DEPTH_64F are supported. */
    charcolorModel[4];     /* Ignored by OpenCV */
    charchannelSeq[4];     /* ditto */
    int  dataOrder;         /* 0 -interleaved color channels, 1 - separate color channels.
                               cvCreateImage can only createinterleaved images */
    int  origin;            /* 0 -top-left origin,
                               1 - bottom-leftorigin (Windows bitmaps style).  */
    int  align;             /*Alignment of image rows (4 or 8).
                               OpenCV ignoresit and uses widthStep instead.    */
    int  width;             /* Imagewidth in pixels.                          */
    int  height;            /* Imageheight in pixels.                         */
    struct_IplROI *roi;    /*Image ROI. If NULL, the whole image is selected. */
    struct_IplImage *maskROI;      /* Must be NULL. */
    void  *imageId;                 /*"           " */
    struct_IplTileInfo *tileInfo;  /* "          " */
    int  imageSize;         /* Imagedata size in bytes
                              (==image->height*image->widthStep
                               in case ofinterleaved data)*/
    char*imageData;        /* Pointer toaligned image data.         */
    int  widthStep;         /* Size ofaligned image row in bytes.    */
    int  BorderMode[4];     /* Ignored byOpenCV.                     */
    int  BorderConst[4];    /* Ditto.                                 */
    char*imageDataOrigin;  /* Pointer to very origin of image data
                               (not necessarilyaligned) -
                               needed forcorrect deallocation */
}
IplImage;




 

3.        OpenCV常用类和数据结构

3.1.       Point类 – 点

Point point;

Point.x = 10;

Point.y = 8;

或者 Point point = point(10,8);

另外Point_<int> ;Point2i; Point 互相等价,Point_<float>; Point2f

3.2.       Scalar类 – 颜色

Scalar(a,b,c) ; abc 即RGB; 用于传递像素值,还有第四个元素是透明,可以不写出来。

3.3.       Size 类 – 尺寸

Size_类模板提供了一些构造函数,具体可以查看D:\Program Files (x86)\opencv\sources\modules\core\include\opencv2\core.cpp;

template<typename_Tp> class Size_
{
public:
    typedef _Tpvalue_type;
 
    //! variousconstructors
    Size_();
    Size_(_Tp _width, _Tp _height);
    Size_(constSize_& sz);
    Size_(constCvSize& sz);
    Size_(constCvSize2D32f& sz);
    Size_(constPoint_<_Tp>& pt);
 
    Size_& operator= (const Size_& sz);
    //! the area(width*height)
    _Tp area() const;
 
    //! conversion ofanother data type.
    template<typename _Tp2> operatorSize_<_Tp2>() const;
 
    //! conversion tothe old-style OpenCV types
    operatorCvSize() const;
    operatorCvSize2D32f() const;
 
    _Tp width, height; //the width and the height
};

最常用的是   Size_(_Tp _width, _Tp _height);

定义模板类型的宽度和高度。

3.4.       Rect 类 – 矩形

Rect_类,成员变量x、y、width、height,分别为左上角点的坐标和矩形的宽和高。常用的成员函数有Size()返回值为一个Size,area()返回矩形的面积,contains(Point)用来判断点是否在矩形内,inside(Rect)函数判断矩形是否在该矩形内,tl()返回左上角点坐标,br()返回右下角点坐标。值得注意的是,如果想求两个矩形的交集,并集,可以用如下格式

l  求两个矩形的交集和并集

Rect rect = rect1 & rect2;

Rect rect = rect1 | rect2;

l  矩形的平移和缩放

Rect RectShift = rect1 + point;

Rect RectScale = rect1 + size;

l  返回矩形的面积

AreaRect = area();

l  判断点是否在矩形内

bPointInRect = Contains(Point);

l  判断矩形是否在矩形内

bRectInRect = Inside(Rect);

3.5.       CvtColor 类 – 颜色空间

CvtColor() 是OpenCV里颜色空间转换函数,实现RGB、HSV HIS 空间的转换

也可转化为灰度图像。

函数原型:

void cv::cvtColor( InputArray _src, OutputArray _dst,int code, intdcn )

 

参数1

输入图像

参数2

输出图像

参数3

颜色空间转换标识符

参数4

目标图像通道数

 

颜色空间的转换标识符类型

enum
{
    CV_BGR2BGRA    =0,
    CV_RGB2RGBA    =CV_BGR2BGRA,
 
    CV_BGRA2BGR    =1,
    CV_RGBA2RGB    =CV_BGRA2BGR,
 
    CV_BGR2RGBA    =2,
    CV_RGB2BGRA    =CV_BGR2RGBA,
 
    CV_RGBA2BGR    =3,
    CV_BGRA2RGB    =CV_RGBA2BGR,
 
    CV_BGR2RGB     =4,
    CV_RGB2BGR     =CV_BGR2RGB,
 
    CV_BGRA2RGBA   =5,
    CV_RGBA2BGRA   =CV_BGRA2RGBA,
 
    CV_BGR2GRAY    =6,
    CV_RGB2GRAY    =7,
    CV_GRAY2BGR    =8,
    CV_GRAY2RGB    =CV_GRAY2BGR,
    CV_GRAY2BGRA   =9,
    CV_GRAY2RGBA   =CV_GRAY2BGRA,
    CV_BGRA2GRAY   =10,
    CV_RGBA2GRAY   =11,
 
…
 
    CV_RGBA2YUV_I420 = 129,
    CV_BGRA2YUV_I420 = 130,
    CV_RGBA2YUV_IYUV = CV_RGBA2YUV_I420,
    CV_BGRA2YUV_IYUV = CV_BGRA2YUV_I420,
    CV_RGB2YUV_YV12  = 131,
    CV_BGR2YUV_YV12  = 132,
    CV_RGBA2YUV_YV12 = 133,
    CV_BGRA2YUV_YV12 = 134,
 
    CV_COLORCVT_MAX  = 135
};

3.6.       一些常用的知识点

Matx类

轻量级的Mat 使用前规定好大小,如Mat23f 即是定义一个2*3的float型的Mat

Vec类

Matx 的派生类,一维的Matx

Range类

Range::all() 是matlab符号,Range(a,b) 是Matlab中的a:b

防溢出函数

AlignPtr(), alignSize(), allocate(), deallocate(), fastMalloc(), fastFree()

数学库函数

FastAtan2

计算向量角度的函数

cubeRoot

计算立方根的函数

cvCeil

向上取整函数

cvFloor

向下取整函数

cvRound

四舍五入函数

cvIsInf

MatLab函数,判断自变量是否无求大

cvIsNaN

MatLab函数,判断自变量是否不是一个数

显示文字的函数

getTextSize, cvInitFont, putText

作图函数

Circle, clipLine,ellipse,ellipse2Poly,line,rectangle,polylines,类LineIterator

填充函数

fillCibvexPoly, fillPoly

随机数

RNG()

 

4.        OpenCV基本图形绘制

4.1.       基本的绘图函数

绘制直线

void line( Mat& img, Point pt1, Point pt2, const

int thickness, int line_type, int

绘制椭圆

void

double angle, double start_angle, double

const Scalar& color, int thickness, int line_type, int

绘制矩形

void

const Scalar& color, int

int lineType, int

绘制圆形

void circle( Mat& img, Point center, int

const Scalar& color, int thickness, int line_type, int

 

绘制填充

void fillPoly( Mat& img, const Point** pts, const int* npts, int

const Scalar& color, int

int

 

4.2.       DrawEillpse函数的写法

OpenCV 官方例子:

绘制不同角度,尺寸相同的椭圆。

void DrawEllipse( Mat img, doubleangle )
{
         intthickness = 2;
         intlineType = 8;
 
         ellipse( img,
                   Point( WINDOW_WIDTH/2,WINDOW_WIDTH/2 ),//中心点
                   Size( WINDOW_WIDTH/4,WINDOW_WIDTH/16 ),//位于矩形范围内
                   angle,//椭圆旋转角度
                   0,   //画椭圆的起始弧度
                   360,// 椭圆的终止弧度
                   Scalar( 255, 129, 0 ),// 图形的颜色BGR,此为蓝色
                   thickness,// 线宽为2
                   lineType );// 线型为8 即8联通线型
}

4.3.       DrawFilledCircle的写法

 实现实心圆绘制:

void DrawFilledCircle( Mat img, Point center )
{
         intthickness = -1;
         intlineType = 8;
 
         circle( img,
                   center, //圆心
                   WINDOW_WIDTH/32, //圆的半径
                   Scalar( 0, 0, 255 ), //图形的颜色BGR,此为红色
                   thickness, //线宽为2
                   lineType ); //线型为8 即8联通线型
 
}

4.4.       DrawPolygon的写法

  实现凹多边形的绘制:

void DrawPolygon( Mat img )
{
         intlineType = 8;
 
         //创ä¡ä建¡§一°?些?点Ì?
         Point rookPoints[1][20];
         rookPoints[0][0]  = Point(   WINDOW_WIDTH/4,   7*WINDOW_WIDTH/8);
         rookPoints[0][1]  = Point( 3*WINDOW_WIDTH/4,  7*WINDOW_WIDTH/8 );
         rookPoints[0][2]  = Point( 3*WINDOW_WIDTH/4, 13*WINDOW_WIDTH/16 );
         rookPoints[0][3]  = Point( 11*WINDOW_WIDTH/16,13*WINDOW_WIDTH/16 );
         rookPoints[0][4]  = Point( 19*WINDOW_WIDTH/32,  3*WINDOW_WIDTH/8 );
         rookPoints[0][5]  = Point( 3*WINDOW_WIDTH/4,  3*WINDOW_WIDTH/8 );
         rookPoints[0][6]  = Point( 3*WINDOW_WIDTH/4,    WINDOW_WIDTH/8 );
         rookPoints[0][7]  = Point( 26*WINDOW_WIDTH/40,    WINDOW_WIDTH/8 );
         rookPoints[0][8]  = Point( 26*WINDOW_WIDTH/40,    WINDOW_WIDTH/4 );
         rookPoints[0][9]  = Point( 22*WINDOW_WIDTH/40,    WINDOW_WIDTH/4 );
         rookPoints[0][10] = Point(22*WINDOW_WIDTH/40,    WINDOW_WIDTH/8 );
         rookPoints[0][11] = Point(18*WINDOW_WIDTH/40,    WINDOW_WIDTH/8 );
         rookPoints[0][12] = Point(18*WINDOW_WIDTH/40,    WINDOW_WIDTH/4 );
         rookPoints[0][13] = Point(14*WINDOW_WIDTH/40,    WINDOW_WIDTH/4 );
         rookPoints[0][14] = Point( 14*WINDOW_WIDTH/40,    WINDOW_WIDTH/8 );
         rookPoints[0][15] = Point(    WINDOW_WIDTH/4,     WINDOW_WIDTH/8 );
         rookPoints[0][16] = Point(    WINDOW_WIDTH/4,   3*WINDOW_WIDTH/8 );
         rookPoints[0][17] = Point(13*WINDOW_WIDTH/32,  3*WINDOW_WIDTH/8 );
         rookPoints[0][18] = Point(  5*WINDOW_WIDTH/16, 13*WINDOW_WIDTH/16 );
         rookPoints[0][19] = Point(    WINDOW_WIDTH/4,  13*WINDOW_WIDTH/16 );
 
         constPoint* ppt[1] = { rookPoints[0] };
         intnpt[] = { 20 };
 
         fillPoly( img,
                   ppt, //多边形的顶点集
                   npt, //多边形的顶点数目
                   1, // 多边形的数量仅为1
                   Scalar( 255, 255, 255 ), //图形的颜色BGR,此为白色
                   lineType ); //线型为8 即8联通线型
}

4.5.        DrawLine的写法

 实现了线的绘制:

void DrawLine( Mat img, Point start, Point end )
{
         intthickness = 2;
         intlineType = 8;
         line( img,
                   start,
                   end,
                   Scalar( 0, 0, 0 ), // 图形的颜色BGR,此为黑色
                  thickness,线宽为2
                   lineType ); //线型为8 即8联通线型
}