opencv的基础结构在cxcore文件中,主要结构有:
opencv主要结构
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的定如下:
1.类型的初始化话方法:
ipl数据结构
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;
opencv主要结构
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++):
3.矩阵类型CvMat
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操作
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提供的函数,更为快捷一些:
CvMat访问函数
//获取单个元素的值,注意后面的数据是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
ipl数据结构
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的整倍数
图像的基本操作
ipl数据结构
/*载入图像,从本地文件中,需要注意的是,这个函数返回的指针可以不用事先开启空间,他会自己创建空间,如果你要连续载入图像,在注意及时释放空间*/
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 坐标
对于子图像的操作,一方面可以讲图像装换为矩阵,然后通过矩阵的相关函数来操作,转换可以这样做:
ipl数据结构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来进行操作:
ipl数据结构
/*下面代码用于子图像复制或者子图像处理,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
作者:深夜孤灯