opencv的基础结构在cxcore文件中,主要结构有:

1 CvPoint 2 CvPoint2D32f 3 CvPoint3D32f 4 CvSize 5 CvSize2D32f 6 CvRect 7 CvScalar 8 CvTermCriteria 9 CvMat 10 CvMatND 11 CvSparseMat 12 IplImage 13 CvArr
1~7的定如下:
opencv(2)数据结构 

 

 

 

 

 

 

1.类型的初始化话方法:

CvSize mSize = cvSize(320,240); //宽高 CRect mRect = cvRect(100,100,10,10); //左右,宽高 CvPoint mPoint = cvPoint(100,100); CvPoint3D32f mPt3d = cvPoint2D32f(1.0,2.0,3.0); CvScalar Scalar1=cvScalar(0,1,2,3);//初始化个参数 CvScalar Scalar2=cvRealScalar(10); //初始化第一个VAL[0] CvScalar Scalar3=cvScalarAll(20); //VAL的所有值设置为一个值

 

CvScalar,他的结构如下:CvScalar;
typedef struct CvScalar { double val[4]; } CvScalar;

可以用于多通道矩阵,如果使用的图像是1通道的,则pt.val[0]中存储数据 ,如果使用的图像是3通道的,则pt.val[0],pt.val[1],pt.val[2]中存储数据。

2.

CvArr,它只是一个Interface,在"cxtype.h"被定义为 typedef void CvArr;用于指示函数接收的数组类型可以不止一个,如 IplImage*, CvMat* 甚至 CvSeq*. 最终的数组类型是在运行时通过分析数组头的前4 个字节判断。 opencv数据类型的继承关系(很类似C++):

opencv(2)数据结构

3.矩阵类型CvMat

typedef struct CvMat { int type; int step; /*用字节表示行数据长度*/ int* refcount; /*内部访问*/ union { uchar* ptr; short* s; int* i; float* fl; double* db; } data; /*数据指针*/ union { int rows; int height; }; union { int cols; int width; }; } CvMat; /*矩阵结构头*/

内部使用了union的共用体,也就是说访问的时候可以使用里面的任何一种,尤其是data分为不同的数据类型,访问的时候是需要注意的。

矩阵操作

CvMat * cvCreateMat(int rows, int cols, int type); /*创建矩阵头并分配内存*/ CV_INLine CvMat cvMat((int rows, int cols, int type, void* data CV_DEFAULT); /*用已有数据data初始化矩阵*/ CvMat * cvInitMatHeader(CvMat * mat, int rows, int cols, int type, void * data CV_DEFAULT(NULL), int step CV_DEFAULT(CV_AUTOSTEP)); /*(用已有数据data创建矩阵头)*/ CvMat *CvCloneMat(const CvMat *mat); /*复制矩阵,注意的是,复制的时候不仅创建了矩阵头,也开辟了响应的空间,使用这个函数,要注意释放数据*/ cvReleaseMat(CvMat **Mat); /*释放矩阵*/

矩阵访问(链接可以参考更全的),如果对于单个元素的访问,使用指针式最好的办法,如果是访问整行或者整列,或者是多通道数据的访问,使用opencv提供的函数,更为快捷一些:

//获取单个元素的值,注意后面的数据是CvScalar 类型 void cvSet1D( CvArr* arr, int idx0, CvScalar value ); void cvSet2D( CvArr* arr, int idx0, int idx1, CvScalar value ); void cvSet3D( CvArr* arr, int idx0, int idx1, int idx2, CvScalar value ); void cvSetND( CvArr* arr, int* idx, CvScalar value ); //设置单个元素,,注意返回的数据是CvScalar 类型 CvScalar cvGet1D( const CvArr* arr, int idx0 ); CvScalar cvGet2D( const CvArr* arr, int idx0, int idx1 ); CvScalar cvGet3D( const CvArr* arr, int idx0, int idx1, int idx2 ); CvScalar cvGetND( const CvArr* arr, int* idx ); //上面的访问可以处理多通道数据,访问速度会有点慢可能,更快的办法: //只处理单通道数据,输入的类型是double void cvSetReal1D( CvArr* arr, int idx0, double value ); void cvSetReal2D( CvArr* arr, int idx0, int idx1, double value ); void cvSetReal3D( CvArr* arr, int idx0, int idx1, int idx2, double value ); void cvSetRealND( CvArr* arr, int* idx, double value ); double cvGetReal1D( const CvArr* arr, int idx0 ); double cvGetReal2D( const CvArr* arr, int idx0, int idx1 ); double cvGetReal3D( const CvArr* arr, int idx0, int idx1, int idx2 ); double cvGetRealND( const CvArr* arr, int* idx ); //更快的办法,opencv也提供,使用内联办法 void cvmSet( CvMat* mat, int row, int col, double value ); double cvmGet( const CvMat* mat, int row, int col ); //访问整行整列,正行,使用矩阵的形式返回,注意空间开辟和释放 CvMat* cvGetRow( const CvArr* arr, CvMat* submat, int row ); CvMat* cvGetRows( const CvArr* arr, CvMat* submat, int start_row, int end_row, int delta_row=1 ); CvMat* cvGetCol( const CvArr* arr, CvMat* submat, int col ); CvMat* cvGetCols( const CvArr* arr, CvMat* submat, int start_col, int end_col );

对于特殊矩阵的访问,这里没做介绍,我本人用的比较少

3.图像类型 IplImage

typedef struct _IplImage { int nSize; /* IplImage大小 */ int ID; /* 版本 (=0)*/ int nChannels; /* 大多数OPENCV函数支持1,2,3 或 4 个通道 */ int alphaChannel; /* 被OpenCV忽略 */ int depth; /* 像素的位深度: IPL_DEPTH_8U, IPL_DEPTH_8S, IPL_DEPTH_16U, IPL_DEPTH_16S, IPL_DEPTH_32S, IPL_DEPTH_32F and IPL_DEPTH_64F 可支持 */ char colorModel[4]; /* 被OpenCV忽略 */ char channelSeq[4]; /* 同上 */ int dataOrder; /* 0 - 交叉存取颜色通道, 1 - 分开的颜色通道. cvCreateImage只能创建交叉存取图像 */ int origin; /* 0 - 顶—左结构, 1 - 底—左结构 (Windows bitmaps 风格) */ int align; /* 图像行排列 (4 or 8). OpenCV 忽略它,使用 widthStep 代替 */ int width; /* 图像宽像素数 */ int height; /* 图像高像素数*/ struct _IplROI *roi;/* 图像感兴趣区域. 当该值非空只对该区域进行处理 */ struct _IplImage *maskROI; /* 在 OpenCV中必须置NULL */ void *imageId; /* 同上*/ struct _IplTileInfo *tileInfo; /*同上*/ int imageSize; /* 图像数据大小(在交叉存取格式下imageSize=image->height*image->widthStep),单位字节*/ char *imageData; /* 指向排列的图像数据 */ int widthStep; /* 排列的图像行大小,以字节为单位 */ int BorderMode[4]; /* 边际结束模式, 被OpenCV忽略 */ int BorderConst[4]; /* 同上 */ char *imageDataOrigin; /* 指针指向一个不同的图像数据结构(不是必须排列的),是为了纠正图像内存分配准备的 */ } IplImage;

里面比较关键的变量:

nChannels: 1 2 3,黑白为1通道,24位彩色图像为3通道
depth:一般是IPL_DEPTH_8U,如果需要做精确处理,可以将图像转换为浮点矩阵,处理完在转换回来
origin (只控制显示的方式,并不改变里面数据的保存方式)
width,height
roi:需要使用ROI是使用
imageData:需要注意的是char类型指针,在访问的时候要注意转换为uchar类型
widthStep  也就是行对齐后的量,比如说bmp图像,行必须是4的整倍数
图像的基本操作
/*载入图像,从本地文件中,需要注意的是,这个函数返回的指针可以不用事先开启空间,他会自己创建空间,如果你要连续载入图像,在注意及时释放空间*/ IplImage * cvLoadImage(const char * filename, int iscolor CV_DEFAULT(CV_LOAD_IMAGE_COLOR)); /*创建释放图像*/ IplImage * cvCreateImage(CvSize size, int depth, int channels); void cvReleaseImage( IplImage** image ); /*复制图像,注意空间释放,复制的时候重新开辟了空间*/ IplImage* cvCloneImage( const IplImage* image ); //ROI void cvSetImageROI( IplImage* image, CvRect rect );//基于给定的矩形设置感兴趣区域 void cvResetImageROI( IplImage* image );//释放图像的ROI CvRect cvGetImageROI( const IplImage* image );//返回图像的 ROI 坐标

对于子图像的操作,一方面可以讲图像装换为矩阵,然后通过矩阵的相关函数来操作,转换可以这样做:
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,不复制数据只创建矩阵头


也可以通过ROI来进行操作:

/*下面代码用于子图像复制或者子图像处理,opencv大部分图像处理函数支持ROI,设置完ROI,如果自己去访问像素,注意结构体里面的变量变化*/ IplImage *result; cvSetImageROI(image,roi);// 设置 ROI //下面是对子图像进行处理 result = cvCreateImage( cvSize(roi.width, roi.height), image->depth, image->nChannels );/创建子图像 cvCopy(image,result); //复制子图像或者直接对子图像进行处理 // cvResetImageROI(image);

 

 先说这么多吧,虽然话费这么长时间来整理,也蛮好费时间的,不过收获有的,后面主要对图像处理的过程进行说明先说这么多吧,虽然话费这么长时间来整理,也蛮好费时间的,不过收获有的,后面主要对图像处理的过程进行说明

 

转载请注明地址:http://www.cnblogs.com/zsb517/admin/EditPosts.aspx?postid=2533546
作者:深夜孤灯


相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2021-08-15
  • 2021-11-03
  • 2022-01-19
  • 2022-02-28
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2022-02-11
  • 2022-12-23
  • 2021-07-21
  • 2021-11-28
  • 2021-05-25
相关资源
相似解决方案