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的定如下:
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++):

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
作者:深夜孤灯