转自http://blog.csdn.net/wangjie0377/article/details/6629293
OpenCV学习笔记之CXCORE篇
为使得OpenCV的整个库便于管理和扩充,将整个库分成若干子库,CxCore是最重要的一个子库,从“core"名字可以看出,该库提供了所有OpenCV运行时的一些最基本的数据结构,包括矩阵,数组的基本运算,包括出错处理的一些基本函数。具体分为下面若干部分。
基础结构:
二维坐标系下的点,类型为整型
typedef struct CvPoint { int x; int y; } CvPoint;
inline CvPoint cvPoint( int x, int y );
inline CvPoint cvPointFrom32f( CvPoint2D32f point )
二维坐标下的点,类型为浮点
typedef struct CvPoint2D32f { float x; float y; } CvPoint2D32f;
inline CvPoint2D32f cvPoint2D32f( double x, double y );
inline CvPoint2D32f cvPointTo32f( CvPoint point );
三维坐标下的点,类型为浮点
typedef struct CvPoint3D32f { float x; float y; float z; } CvPoint3D32f;
inline CvPoint3D32f cvPoint3D32f( double x, double y, double z );
矩形框大小,以像素为精度
typedef struct CvSize { int width; int height; } CvSize;
inline CvSize cvSize( int width, int height );
注意:构造函数的cv是小写!
以亚像素精度标量矩形框大小
typedef struct CvSize2D32f { float width; float height; } CvSize2D32f;
inline CvSize2D32f cvSize2D32f( double width, double height ); { CvSize2D32f s; s.width = (float)width; s.height = (float)height; return s; }
矩形框的偏移和大小
typedef struct CvRect { int x; int y; int width; int height; } CvRect;
inline CvRect cvRect( int x, int y, int width, int height ); { CvRect os; os.x = x; os.y = y; os.width = width; os.height = heigth; reture os;}
CvScalar
可存放在1-,2-,3-,4-TUPLE类型的捆绑数据的容器
typedef struct CvScalar { double val[4] } CvScalar;
inline CvScalar cvScalar( double val0, double val1, double val2, double val3); { CvScalar arr; arr.val[4] = {val0,val1,val2,val3}; reture arr;}
inline CvScalar cvScalarAll( double val0123 ); { CvScalar arr; arr.val[4] = {val0123,val0123,val0123,val0123,}; reture arr;}
inline CvScalar cvRealScalar( double val0 ); { CvScalar arr; arr.val[4] = {val0}; reture arr;}
迭代算法的终止准则
#define CV_TERMCRIT_ITER 1 #define CV_TERMCRIT_NUMBER CV_TERMCRIT_ITER #define CV_TERMCRIT_EPS 2 typedef struct CvTermCriteria { int type; int max_iter; double epsilon; } CvTermCriteria;
inline CvTermCriteria cvTermCriteria( int type, int max_iter, double epsilon );
CvTermCriteria cvCheckTermCriteria( CvTermCriteria criteria, double default_eps, int default_max_iters );
多通道矩阵
typedef struct CvMat { int type; int step; int* 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;
多维、多通道密集数组
typedef struct CvMatND { int type; int dims; int* refcount; union { uchar* ptr; short* s; int* i; float* fl; double* db; } data; struct { int size; int step; } dim[CV_MAX_DIM]; } CvMatND;
多维、多通道稀疏数组
typedef struct CvSparseMat { int type; int dims; int* refcount; struct CvSet* heap; void** hashtable; int hashsize; int total; int valoffset; int idxoffset; int size[CV_MAX_DIM]; } CvSparseMat;
IPL 图像头
typedef struct _IplImage { int nSize; int ID; int nChannels; int alphaChannel; int depth; char colorModel[4]; char channelSeq[4]; int dataOrder; int origin; int align; int width; int height; struct _IplROI *roi; struct _IplImage *maskROI; void *imageId; struct _IplTileInfo *tileInfo; int imageSize; char *imageData; int widthStep; int BorderMode[4]; int BorderConst[4]; char *imageDataOrigin; } IplImage;
IplImage结构来自于 Intel Image Processing Library(是其本身所具有的)。OpenCV 只支持其中的一个子集:
除了上述限制,OpenCV处理ROI有不同的要求。要求原图像和目标图像的尺寸或 ROI的尺寸必须(根据不同的操作,例如cvPyrDown 目标图像的宽(高)必须等于原图像的宽(高)除以2 ±1)精确匹配,而IPL处理交叉区域,如图像的大小或ROI大小可能是完全独立的。
CvArr
不确定数组
typedef void CvArr;
CvArr* 仅仅是被用于作函数的参数,用于指示函数接收的数组类型可以不止一个,如 IplImage*, CvMat* 甚至 CvSeq*. 最终的数组类型是在运行时通过分析数组头的前4 个字节判断。
数组操作
初始化
CreateImage
创建头并分配数据
IplImage* cvCreateImage( CvSize size, int depth, int channels );
size
图像宽、高.
depth
图像元素的位深度,可以是下面的其中之一:
IPL_DEPTH_8U - 无符号8位整型
IPL_DEPTH_8S - 有符号8位整型
IPL_DEPTH_16U - 无符号16位整型
IPL_DEPTH_16S - 有符号16位整型
IPL_DEPTH_32S - 有符号32位整型
IPL_DEPTH_32F - 单精度浮点数
IPL_DEPTH_64F - 双精度浮点数
channels
每个元素(像素)的颜色通道数量.可以是 1, 2, 3 或 4.通道是交叉存取的,例如通常的彩色图像数据排列是:
b0 g0 r0 b1 g1 r1 ...
虽然通常 IPL 图象格式可以存贮非交叉存取的图像,并且一些OpenCV 也能处理他, 但是这个函数只能创建交叉存取图像.
函数 cvCreateImage 创建头并分配数据,这个函数是下列的缩写型式
header = cvCreateImageHeader(size,depth,channels);
cvCreateData(header); //只是创建空间,并不会初始化空间内的数据
CreateImageHeader
分配,初始化,并且返回 IplImage结构
IplImage* cvCreateImageHeader( CvSize size, int depth, int channels );
size
图像宽、高.
depth
像深 (见 CreateImage).
channels
通道数 (见 CreateImage).
函数 cvCreateImageHeader 分配, 初始化, 并且返回 IplImage结构. 这个函数相似于:
iplCreateImageHeader( channels, 0, depth,
channels == 1 ? "GRAY" : "RGB",
channels == 1 ? "GRAY" : channels == 3 ? "BGR" :
channels == 4 ? "BGRA" : "",
IPL_DATA_ORDER_PIXEL, IPL_ORIGIN_TL, 4,
size.width, size.height,
0,0,0,0);
然而IPL函数不是作为默认的 (见 CV_TURN_ON_IPL_COMPATIBILITY 宏)
ReleaseImageHeader
释放头
void cvReleaseImageHeader( IplImage** image );
image
双指针指向头内存分配单元.
函数 cvReleaseImageHeader 释放头. 相似于
if( image )
{
iplDeallocate( *image, IPL_IMAGE_HEADER | IPL_IMAGE_ROI );
*image = 0;
}
然而IPL函数不是作为默认的 (见 CV_TURN_ON_IPL_COMPATIBILITY 宏)
ReleaseImage
释放头和图像数据
void cvReleaseImage( IplImage** image );
image
双指针指向图像内存分配单元。
函数 cvReleaseImage 释放头和图像数据,相似于:
if( *image )
{
cvReleaseData( *image );
cvReleaseImageHeader( image );
}
InitImageHeader
初始化被用图分配的图像头
IplImage* cvInitImageHeader( IplImage* image, CvSize size, int depth,
int channels, int origin=0, int align=4 );
image
被初始化的图像头.
size
图像的宽高.
depth
像深(见 CreateImage).
channels
通道数(见 CreateImage).
origin
IPL_ORIGIN_TL 或 IPL_ORIGIN_BL.
align
图像行排列, 典型的 4 或 8 字节.
函数 cvInitImageHeader 初始化图像头结构, 指向用户指定的图像并且返回这个指针。
CloneImage
制作图像的完整拷贝
IplImage* cvCloneImage( const IplImage* image );
image
原图像.
函数 cvCloneImage 制作图像的完整拷贝包括头、ROI和数据
SetImageCOI
基于给定的值设置感兴趣通道
void cvSetImageCOI( IplImage* image, int coi );
image
图像头.
coi
感兴趣通道.
函数 cvSetImageCOI 基于给定的值设置感兴趣的通道。值 0 意味着所有的通道都被选定, 1 意味着第一个通道被选定等等。如果 ROI 是 NULL 并且COI!= 0, ROI 被分配. 然而大多数的 OpenCV 函数不支持 COI, 对于这种状况当处理分离图像/矩阵通道时,可以拷贝(通过 cvCopy 或cvSplit) 通道来分离图像/矩阵,处理后如果需要可再拷贝(通过cvCopy 或 cvCvtPlaneToPix)回来.
GetImageCOI
返回感兴趣通道号
int cvGetImageCOI( const IplImage* image );
image
图像头.
函数cvGetImageCOI 返回图像的感兴趣通道(当所有的通道都被选中返回值是0).
SetImageROI
基于给定的矩形设置'感兴趣'区域
void cvSetImageROI( IplImage* image, CvRect rect );
image
图像.
rect
ROI 矩形.
函数 cvSetImageROI 基于给定的矩形设置图像的 ROI(感兴趣区域) . 如果ROI是NULL 并且参数RECT的值不等于整个图像, ROI被分配. 不像 COI, 大多数的 OpenCV 函数支持 ROI 并且处理它就像它是一个分离的图像 (例如, 所有的像素坐标从ROI的左上角或左下角(基于图像的结构)计算。
ResetImageROI
释放图像的ROI
void cvResetImageROI( IplImage* image );
image
图像头.
函数 cvResetImageROI 释放图像 ROI. 释放之后整个图像被认为是全部被选中的。相似的结果可以通过下述办法
cvSetImageROI( image, cvRect( 0, 0, image->width, image->height ));
cvSetImageCOI( image, 0 );
但是后者的变量不分配 image->roi.
GetImageROI
返回图像的 ROI 坐标
CvRect cvGetImageROI( const IplImage* image );
image
图像头.
函数 cvGetImageROI 返回图像ROI 坐标. 如果没有ROI则返回矩形值为 cvRect(0,0,image->width,image->height)
CreateMat
创建矩阵
CvMat* cvCreateMat( int rows, int cols, int type );
rows
矩阵行数。
cols
矩阵列数。
type
矩阵元素类型。 通常以 CV_<比特数>(S|U|F)C<通道数>型式描述,例如:
CV_8UC1 意思是一个8-bit 无符号单通道矩阵, CV_32SC2 意思是一个32-bit 有符号二个通道的矩阵。
函数 cvCreateMat 为新的矩阵分配头和下面的数据,并且返回一个指向新创建的矩阵的指针。是下列操作的缩写型式:
CvMat* mat = cvCreateMatHeader( rows, cols, type );
cvCreateData( mat );
矩阵按行存贮。所有的行以4个字节对齐。
CreateMatHeader
创建新的矩阵头
CvMat* cvCreateMatHeader( int rows, int cols, int type );
rows
矩阵行数.
cols
矩阵列数.
type
矩阵元素类型(见 cvCreateMat).
函数 cvCreateMatHeader 分配新的矩阵头并且返回指向它的指针. 矩阵数据可被进一步的分配,使用cvCreateData 或通过 cvSetData明确的分配数据.
ReleaseMat
删除矩阵
void cvReleaseMat( CvMat** mat );
mat
双指针指向矩阵.
函数cvReleaseMat 缩减矩阵数据参考计数并且释放矩阵头 :
if( *mat )
cvDecRefData( *mat );
cvFree( (void**)mat );
InitMatHeader
初始化矩阵头
CvMat* cvInitMatHeader( CvMat* mat, int rows, int cols, int type,
void* data=NULL, int step=CV_AUTOSTEP );
mat
指针指向要被初始化的矩阵头.
rows
矩阵的行数.
cols
矩阵的列数.
type
矩阵元素类型.
data
可选的,将指向数据指针分配给矩阵头.
step
排列后的数据的整个行宽,默认状态下,使用STEP的最小可能值。也就是说默认情况下假定矩阵的行与行之间无隙.
函数 cvInitMatHeader 初始化已经分配了的 CvMat 结构. 它可以被OpenCV矩阵函数用于处理原始数据。
例如, 下面的代码计算通用数组格式存贮的数据的矩阵乘积.
计算两个矩阵的积
double a[] = { 1, 2, 3, 4,
5, 6, 7, 8,
9, 10, 11, 12 };
double b[] = { 1, 5, 9,
2, 6, 10,
3, 7, 11,
4, 8, 12 };
double c[9];
CvMat Ma, Mb, Mc ;
cvInitMatHeader( &Ma, 3, 4, CV_64FC1, a );
cvInitMatHeader( &Mb, 4, 3, CV_64FC1, b );
cvInitMatHeader( &Mc, 3, 3, CV_64FC1, c );
cvMatMulAdd( &Ma, &Mb, 0, &Mc );
// c 数组存贮 a(3x4) 和 b(4x3) 矩阵的积
Mat
初始化矩阵的头(轻磅变量)
CvMat cvMat( int rows, int cols, int type, void* data=NULL );
rows
矩阵行数
cols
列数.
type
元素类型(见CreateMat).
data
可选的分配给矩阵头的数据指针 .
函数 cvMat 是个一快速内连函数,替代函数 cvInitMatHeader. 也就是说它相当于:
CvMat mat;
cvInitMatHeader( &mat, rows, cols, type, data, CV_AUTOSTEP );
CloneMat
创建矩阵拷贝
CvMat* cvCloneMat( const CvMat* mat );
mat
输入矩阵.
函数 cvCloneMat 创建输入矩阵的一个拷贝并且返回 该矩阵的指针.
CreateMatND
创建多维密集数组
CvMatND* cvCreateMatND( int dims, const int* sizes, int type );
dims
数组维数. 但不许超过 CV_MAX_DIM (默认=32,但这个默认值可能在编译时被改变 )的定义
sizes
数组的维大小.
type
数组元素类型. 与 CvMat相同
函数cvCreateMatND 分配头给多维密集数组并且分配下面的数据,返回指向被创建数组的指针 . 是下列的缩减形式:
CvMatND* mat = cvCreateMatNDHeader( dims, sizes, type );
cvCreateData( mat );
矩阵按行存贮. 所有的行以4个字节排列。.
CreateMatNDHeader
创建新的数组头
CvMatND* cvCreateMatNDHeader( int dims, const int* sizes, int type );
dims
数组维数.
sizes
维大小.
type
数组元素类型. 与 CvMat相同
函数cvCreateMatND 分配头给多维密集数组。数组数据可以用 cvCreateData 进一步的被分配或利用cvSetData由用户明确指定.
ReleaseMatND
删除多维数组
void cvReleaseMatND( CvMatND** mat );
mat
指向数组的双指针.
函数 cvReleaseMatND 缩减数组参考计数并释放数组头:
if( *mat )
cvDecRefData( *mat );
cvFree( (void**)mat );
InitMatNDHeader
初始化多维数组头
CvMatND* cvInitMatNDHeader( CvMatND* mat, int dims, const int* sizes, int type, void* data=NULL );
mat
指向要被出初始化的数组头指针.
dims
数组维数.
sizes
维大小.
type
数组元素类型. 与 CvMat相同
data
可选的分配给矩阵头的数据指针.
函数 cvInitMatNDHeader 初始化 用户指派的CvMatND 结构.
CloneMatND
创建多维数组的完整拷贝
CvMatND* cvCloneMatND( const CvMatND* mat );
mat
输入数组
函数 cvCloneMatND 创建输入数组的拷贝并返回指针.
DecRefData
缩减数组数据的引用计数
void cvDecRefData( CvArr* arr );
arr
数组头.
如果引用计数指针非NULL,函数 cvDecRefData 缩减CvMat 或CvMatND 数据的引用计数,如果计数到0就删除数据。在当前的版本中只有当数据是用cvCreateData 分配的引用计数才会是非NULL。在其他的情况下比如:
· 使用cvSetData指派外部数据给矩阵头;
· 代表部分大的矩阵或图像的矩阵头;
· 是从图像头或N维矩阵头转换过来的矩阵头,
在这些情况下引用计数被设置成NULL因此不会被缩减。无论数据是否被删除,数据指针和引用计数指针都将被这个函数清空。
IncRefData
增加数组数据的引用计数
int cvIncRefData( CvArr* arr );
arr
数组头.
函数 cvIncRefData 增加 CvMat 或 CvMatND 数据引用计数,如果引用计数非空返回新的计数值 否则返回0。
CreateData
分配数组数据
void cvCreateData( CvArr* arr );
arr
数组头.
函数 cvCreateData 分配图像,矩阵或多维数组数据. 对于矩阵类型使用OpenCV的分配函数,对于 IplImage类型如果CV_TURN_ON_IPL_COMPATIBILITY没有被调用也是可以使用这种方法的反之使用 IPL 函数分配数据
ReleaseData
释放数组数据
void cvReleaseData( CvArr* arr );
arr
数组头
函数cvReleaseData 释放数组数据. 对于 CvMat 或 CvMatND 结构只需调用 cvDecRefData(), 也就是说这个函数不能删除外部数据。见 cvCreateData.
SetData
指派用户数据给数组头
void cvSetData( CvArr* arr, void* data, int step );
arr
数组头.
data
用户数据.
step
整行字节长.
函数cvSetData 指派用户数据给数组头. 头应该已经使用 cvCreate*Header, cvInit*Header 或 cvMat (对于矩阵)初始化过.
GetRawData
返回数组的底层信息
void cvGetRawData( const CvArr* arr, uchar** data,
int* step=NULL, CvSize* roi_size=NULL );
arr
数组头.
data
输出指针,指针指向整个图像的结构或ROI
step
输出行字节长
roi_size
输出ROI尺寸
函数 cvGetRawData 添充给输出变量数组的底层信息。所有的输出参数是可选的, 因此这些指针可设为NULL。如果数组是设置了ROI的 IplImage 结构, ROI参数被返回。
注意:输出指针指向数组头的对应的内存,不能释放。建议用memcpy。
接下来的例子展示怎样利用这个函数去访问数组元素。
使用 GetRawData 计算单通道浮点数组的元素绝对值。
float* data;
int step;
CvSize size;
int x, y;
cvGetRawData( array, (uchar**)&data, &step, &size );
step /= sizeof(data[0]);
for( y = 0; y < size.height; y++, data += step )
for( x = 0; x < size.width; x++ )
data[x] = (float)fabs(data[x]);
GetMat
从不确定数组返回矩阵头
CvMat* cvGetMat( const CvArr* arr, CvMat* header, int* coi=NULL, int allowND=0 );
arr
输入数组.
header
指向 CvMat结构的指针,作为临时缓存 .
coi
可选的输出参数,用于输出COI.
allowND
如果非0,函数就接收多维密集数组 (CvMatND*)并且返回 2D (如果 CvMatND 是二维的)或 1D 矩阵(当 CvMatND 是一维或多于二维). 数组必须是连续的.
函数 cvGetMat从输入的数组生成矩阵头,输入的数组可以是 - CvMat结构, IplImage结构 或多维密集数组 CvMatND* (后者只有当 allowND != 0时才可以使用) . 如果是矩阵函数只是返回指向矩阵的指针.如果是 IplImage* 或 CvMatND* 函数用当前图像的ROI初始化头结构并且返回指向这个临时结构的指针。因为CvMat不支持COI,所以他们的返回结果是不同的.
这个函数提供了一个简单的方法,用同一代码处理 IplImage 和 CvMat二种数据类型。这个函数的反向转换可以用 cvGetImage将 CvMat 转换成 IplImage .
输入的数组必须有已分配好的底层数据或附加的数据,否则该函数将调用失败如果输入的数组是IplImage 格式,使用平面式数据编排并设置了COI,函数返回的指针指向被选定的平面并设置COI=0.利用OPENCV函数对于多通道平面编排图像可以处理每个平面。
GetImage
从不确定数组返回图像头
IplImage* cvGetImage( const CvArr* arr, IplImage* image_header );
arr
输入数组.
image_header
指向IplImage结构的指针,该结构存贮在一个临时缓存 .
函数 cvGetImage 从输出数组获得图头,该数组可以是矩阵- CvMat*, 或图像 - IplImage*。如果是图像的话函数只是返回输入参数的指针,如果是 CvMat* 的话函数用输入参数矩阵初始化图像头。因此如果我们把 IplImage 转换成 CvMat 然后再转换 CvMat 回 IplImage,如果ROI被设置过了我们可能会获得不同的头,这样一些计算图像跨度的IPL函数就会失败。
CreateSparseMat
创建稀疏数组
CvSparseMat* cvCreateSparseMat( int dims, const int* sizes, int type );
dims
数组维数。相对于密集型矩阵,稀疏数组的维数是不受限制的(最多可达 216)。
sizes
数组的维大小。
type
数组元素类型,见 CvMat。
函数 cvCreateSparseMat 分配多维稀疏数组。刚初始化的数组不含元素,因此cvGet*D 或 cvGetReal*D函数对所有索引都返回0。
ReleaseSparseMat
删除稀疏数组
void cvReleaseSparseMat( CvSparseMat** mat );
mat
双指针指向数组。
函数 cvReleaseSparseMat释放稀疏数组并清空数组指针
CloneSparseMat
创建稀疏数组的拷贝
CvSparseMat* cvCloneSparseMat( const CvSparseMat* mat );
mat
输入数组。
函数 cvCloneSparseMat 创建输入数组的拷贝并返回指向这个拷贝的指针。
获取元素和数组子集
GetSubRect
返回输入的图像或矩阵的矩形数组子集的矩阵头
CvMat* cvGetSubRect( const CvArr* arr, CvMat* submat, CvRect rect );
arr
输入数组。
submat
指向矩形数组子集矩阵头的指针。
rect
以0坐标为基准的ROI。
函数 cvGetSubRect 根据指定的数组矩形返回矩阵头,换句话说,函数允许像处理一个独立数组一样处理输入数组的一个指定子矩形。函数在处理时要考虑进输入数组的ROI,因此数组的ROI是实际上被提取的。
GetRow, GetRows
返回数组的一行或在一定跨度内的行
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 );
arr
输入数组。
submat
指向返回的子数组头的指针。
row
被选定行的索引下标,索引下标从0开始。
start_row
跨度的开始行(包括此行)索引下标,索引下标从0开始。
end_row
跨度的结束行(不包括此行)索引下标,索引下标从0开始。
delta_row
在跨度内的索引下标跨步,从开始行到结束行每隔delta_row行提取一行。
函数GetRow 和 GetRows 返回输入数组中指定的一行或在一定跨度内的行对应的数组头。 注意GetRow 实际上是以下cvGetRows调用的简写:
cvGetRow( arr, submat, row ) ~ cvGetRows( arr, submat, row, row + 1, 1 );
GetCol, GetCols
返回数组的一列或一定跨度内的列
CvMat* cvGetCol( const CvArr* arr, CvMat* submat, int col );
CvMat* cvGetCols( const CvArr* arr, CvMat* submat, int start_col, int end_col );
arr
输入数组。
submat
指向结果子数组头的指针。
col
被选定列的索引下标,索引下标从0开始。
start_col
跨度的开始列(包括该列)索引下标,索引下标从0开始。
end_col
跨度的结束列(不包括该列)索引下标,索引下标从0开始。
函数 GetCol 和 GetCols 根据指定的列/列跨度返回对应的数组头。注意GetCol 实际上是以下 cvGetCols调用的简写形式:
cvGetCol( arr, submat, col ); // ~ cvGetCols( arr, submat, col, col + 1 );
GetDiag
返回一个数组对角线
CvMat* cvGetDiag( const CvArr* arr, CvMat* submat, int diag=0 );
arr
输入数组.
submat
指向结果子集的头指针.
diag
数组对角线。0是主对角线,-1是主对角线上面对角线,1是主对角线下对角线,以此类推。
函数 cvGetDiag 根据指定的diag参数返回数组的对角线头。
GetSize
返回矩阵或图像ROI的大小
CvSize cvGetSize( const CvArr* arr );
arr
数组头。
函数 cvGetSize 返回图像或矩阵的行数和列数,如果是图像就返回ROI的大小。
InitSparseMatIterator
初始化稀疏数组元素迭代器
CvSparseNode* cvInitSparseMatIterator( const CvSparseMat* mat,
CvSparseMatIterator* mat_iterator );
mat
输入的数组.
mat_iterator
被初始化的迭代器.
函数 cvInitSparseMatIterator 初始化稀疏数组元素的迭代器并且返回指向第一个元素的指针,如果数组为空则返回NULL。
GetNextSparseNode
初始化稀疏数组元素迭代器
CvSparseNode* cvGetNextSparseNode( CvSparseMatIterator* mat_iterator );
mat_iterator
稀疏数组的迭代器
函数cvGetNextSparseNode 移动迭代器到下一个稀疏矩阵元素并返回指向他的指针。在当前的版本不存在任何元素的特殊顺序,因为元素是按HASH表存贮的下面的列子描述怎样在稀疏矩阵上迭代 :
利用cvInitSparseMatIterator 和cvGetNextSparseNode 计算浮点稀疏数组的和。
double sum;
int i, dims = cvGetDims( array );
CvSparseMatIterator mat_iterator;
CvSparseNode* node = cvInitSparseMatIterator( array, &mat_iterator );
for( ; node != 0; node = cvGetNextSparseNode( &mat_iterator ))
{
int* idx = CV_NODE_IDX( array, node );
float val = *(float*)CV_NODE_VAL( array, node );
printf( "(" );
for( i = 0; i < dims; i++ )
printf( "M%s", idx[i], i < dims - 1 ? "," : "): " );
printf( "%g\n", val );
sum += val;
printf( "\nTotal sum = %g\n", sum );
GetElemType
返回数组元素类型
int cvGetElemType( const CvArr* arr );
arr
输入数组.
函数 GetElemType 返回数组元素类型就像在cvCreateMat 中讨论的一样:
CV_8UC1 ... CV_64FC4
GetDims, GetDimSize
返回数组维数和他们的大小或者特殊维的大小
int cvGetDims( const CvArr* arr, int* sizes=NULL );
int cvGetDimSize( const CvArr* arr, int index );
arr
输入数组.
sizes
可选的输出数组维尺寸向量,对于2D数组第一位是数组行数(高),第二位是数组列数(宽)
index
以0为基准的维索引下标(对于矩阵0意味着行数,1意味着列数,对于图象0意味着高,1意味着宽。
函数 cvGetDims 返回维数和他们的大小。如果是 IplImage 或 CvMat 总是返回2,不管图像/矩阵行数。函数 cvGetDimSize 返回特定的维大小(每维的元素数)。例如,接下来的代码使用二种方法计算数组元素总数。
// via cvGetDims()
int sizes[CV_MAX_DIM];
int i, total = 1;
int dims = cvGetDims( arr, size );
for( i = 0; i < dims; i++ )
total *= sizes[i];
// via cvGetDims() and cvGetDimSize()
int i, total = 1;
int dims = cvGetDims( arr );
for( i = 0; i < dims; i++ )
total *= cvGetDimsSize( arr, i );
Ptr*D
返回指向特殊数组元素的指针
uchar* cvPtr1D( const CvArr* arr, int idx0, int* type=NULL );
uchar* cvPtr2D( const CvArr* arr, int idx0, int idx1, int* type=NULL );
uchar* cvPtr3D( const CvArr* arr, int idx0, int idx1, int idx2, int* type=NULL );
uchar* cvPtrND( const CvArr* arr, int* idx, int* type=NULL, int create_node=1, unsigned* precalc_hashval=NULL );
arr
输入数组.
idx0
元素下标的第一个以0为基准的成员
idx1
元素下标的第二个以0为基准的成员
idx2
元素下标的第三个以0为基准的成员
idx
数组元素下标
type
可选的,矩阵元素类型输出参数
create_node
可选的,为稀疏矩阵输入的参数。如果这个参数非零就意味着被需要的元素如果不存在就会被创建。
precalc_hashval
可选的,为稀疏矩阵设置的输入参数。如果这个指针非NULL,函数不会重新计算节点的HASH值,而是从指定位置获取。这种方法有利于提高智能组合数据的操作(TODO: 提供了一个例子)
函数cvPtr*D 返回指向特殊数组元素的指针。数组维数应该与转递给函数物下标数相匹配,除了 cvPtr1D 函数,它可以被用于顺序存取的1D,2D或nD密集数组
函数也可以用于稀疏数组,并且如果被需要的节点不存在函数可以创建这个节点并设置为0
就像其它获取数组元素的函数 (cvGet[Real]*D, cvSet[Real]*D)如果元素的下标超出了范围就会产生错误
Get*D
返回特殊的数组元素
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 );
arr
输入数组.
idx0
元素下标第一个以0为基准的成员
idx1
元素下标第二个以0为基准的成员
idx2
元素下标第三个以0为基准的成员
idx
元素下标数组
函数cvGet*D 返回指定的数组元素。对于稀疏数组如果需要的节点不存在函数返回0 (不会创建新的节点)
GetReal*D
返回单通道数组的指定元素
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 );
arr
输入数组,必须是单通道.
idx0
元素下标的第一个成员,以0为基准
idx1
元素下标的第二个成员,以0为基准
idx2
元素下标的第三个成员,以0为基准
idx
元素下标数组
函数cvGetReal*D 返回单通道数组的指定元素,如果数组是多通道的,就会产生运行时错误,而 cvGet*D 函数可以安全的被用于单通道和多通道数组,但他们运行时会有点慢
如果指定的点不存在对于稀疏数组点会返回0(不会创建新的节点)。
mGet
返回单通道浮点矩阵指定元素
double cvmGet( const CvMat* mat, int row, int col );
mat
输入矩阵.
row
行下标,以0为基点.
col
列下标,以0为基点
函数 cvmGet 是 cvGetReal2D对于单通道浮点矩阵的快速替代函数,函数运行比较快速因为它是内连函数,这个函数对于数组类型、数组元素类型的检查作的很少,并且仅在调式模式下检查数的行和列范围。
Set*D
修改指定的数组
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 );
arr
输入数组
idx0
元素下标的第一个成员,以0为基点
idx1
元素下标的第二个成员,以0为基点
idx2
元素下标的第三个成员,以0为基点
idx
元素下标数组
value
指派的值
函数 cvSet*D 指定新的值给指定的数组元素。对于稀疏矩阵如果指定节点不存在函数创建新的节点
SetReal*D
修改指定数组元素值
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 );
arr
输入数组.
idx0
元素下标的第一个成员,以0为基点
idx1
元素下标的第二个成员,以0为基点
idx2
元素下标的第三个成员,以0为基点
idx
元素下标数组
value
指派的值
函数 cvSetReal*D 分配新的值给单通道数组的指定元素,如果数组是多通道就会产生运行时错误。然而cvSet*D 可以安全的被用于多通道和单通道数组,只是稍微有点慢。
对于稀疏数组如果指定的节点不存在函数会创建该节点。
mSet
为单通道浮点矩阵的指定元素赋值。
void cvmSet( CvMat* mat, int row, int col, double value );
mat
矩阵.
row
行下标,以0为基点.
col
列下标,以0为基点.
value
矩阵元素的新值
函数cvmSet 是cvSetReal2D 快速替代,对于单通道浮点矩阵因为这个函数是内连的所以比较快,函数对于数组类型、数组元素类型的检查作的很少,并且仅在调式模式下检查数的行和列范围。
ClearND
清除指定数组元素
void cvClearND( CvArr* arr, int* idx );
arr
输入数组.
idx
数组元素下标
函数cvClearND 清除指定密集型数组的元素(置0)或删除稀疏数组的元素 ,如果元素不存在函数不作任何事
拷贝和添加
Copy
拷贝一个数组给另一个数组
void cvCopy( const CvArr* src, CvArr* dst, const CvArr* mask=NULL );
src
输入数组。
dst
输出数组。
mask
操作掩码是8比特单通道的数组,它指定了输出数组中被改变的元素。
函数cvCopy从输入数组中复制选定的成分到输出数组:
如果mask(I)!=0,则dst(I)=src(I)。
如果输入输出数组中的一个是IplImage类型的话,其ROI和COI将被使用。输入输出数组必须是同样的类型、维数和大小。函数也可以用来复制散列数组(这种情况下不支持mask)。
Set
设置数组所有元素为指定值
void cvSet( CvArr* arr, CvScalar value, const CvArr* mask=NULL );
arr
输出数组。
value
填充值。
mask
操作掩码是8比特单通道的数组,它指定了输出数组中被改变的元素。
函数 cvSet 拷贝数量值到输出数组的每一个被除数选定的元素:
arr(I)=value if mask(I)!=0
如果数组 arr 是 IplImage 类型, 那么就会使用ROI,但COI不能设置。
SetZero
清空数组
void cvSetZero( CvArr* arr );
#define cvZero cvSetZero
arr
要被清空数组.
函数 cvSetZero 清空数组. 对于密集型号数组(CvMat, CvMatND or IplImage) cvZero(array) 就相当于 cvSet(array,cvScalarAll(0),0), 对于稀疏数组所有的元素都将被删除.
SetIdentity
初始化带尺度的单位矩阵
void cvSetIdentity( CvArr* mat, CvScalar value=cvRealScalar(1) );
mat
待初始化的矩阵 (不一定是方阵)。
value
赋值给对角线元素的值。
函数 cvSetIdentity 初始化带尺度的单位矩阵:
arr(i,j)=value 如果 i=j,
否则为 0
Range
用指定范围的数来填充矩阵.
void cvRange( CvArr* mat, double start, double end );
mat
即将被初始化的矩阵,必须是指向单通道的32位(整型或浮点型)的矩阵的指针.
start
指定范围的最小边界
end
指定范围的最大边界
该函数按以下方式初始化矩阵:
arr(i,j)=(end-start)*(i*cols(arr)+j)/(cols(arr)*rows(arr))
例如:以下的代码将按相应的整型数初始化一维向量:
CvMat* A = cvCreateMat( 1, 10, CV_32S ); cvRange( A, 0, A->cols ); //A将被初始化为[0,1,2,3,4,5,6,7,8,9]
转自 http://blog.csdn.net/wangjie0377/article/details/6629293
集合
CvSet
Collection of nodes
typedef struct CvSetElem
{
int flags;
struct CvSetElem* next_free;
}
CvSetElem;
#define CV_SET_FIELDS() \
CV_SEQUENCE_FIELDS() \
struct CvSetElem* free_elems;
typedef struct CvSet
{
CV_SET_FIELDS()
} CvSet;
在 OpenCV 的稀疏数据结构中, CvSet 是一基本结构。
从上面的声明中可知:CvSet 继承自 CvSeq, 并在此基础上增加了个 free_elems 域,该域是空节点组成的列表。集合中的每一个节点,无论空否,都是线性表中的一个元素。尽管对于稠密的表中的元素没有限制,集合(派生的结构)元素必须起始于整数域,并与结构 CvSetElem 相吻合,因为这两个域对于(由空节点组成)集合的组织是必要的。如果节点为空,flags 为负,next_free 指向下一个空节点。如果节点已被占据空间,flags 为正, flags 包含节点索引值(使用表达式 set_elem->flags & CV_SET_ELEM_IDX_MASKH 获取), flags 的剩馀内容由用户决定。宏 CV_IS_SET_ELEM(set_elem.ptr)用来识别特定的节点是否为空。
起初,集合 set 同表 list 都为空。当需要一个来自集合中的新节点时,就从表 list 中去获取,然后表进行了更新。如果表 list 碰巧为空,于是就分配一内存块,块中的所有节点与表 list 相连。结果,集合的 total 域被设置为空节点和非空节点的和。当非空节点别释放后,就将它加到空节点列表中。最先被释放的节点也就是最先被占用空间的节点
在 OpenCV 中, CvSet 用来代表图形(CvGraph), 稀疏多维数组(CvSparseMat), 平面子划分(planner subdivisions)等
CreateSet
创建空的数据集
CvSet* cvCreateSet( int set_flags, int header_size,
int elem_size, CvMemStorage* storage );
set_flags
集合的类型
header_size
头节点的大小;应该等于 sizeof(CvSet)
elem_size
元素的大小;不能小8
storage
相关容器
函数 CvCreateSet 创建一具有特定头部节点大小和元素类型的空集。并返回指向该集合的指针。
SetAdd
占用集合中的一个节点
int cvSetAdd( CvSet* set_header, CvSetElem* elem=NULL, CvSetElem** inserted_elem=NULL );
set_header
集合
elem
可选的输入参数,被插入的元素。如果不为 NULL, 函数就将数据拷贝到新分配的节点。(拷贝后,清空第一个域的 MSB)
函数 cvSetAdd 分配一新的节点,将输入数据拷贝给它(可选),并且返回指向该节点的指针和节点的索引值。索引值可通过节点的flags域的低位中获得。函数的时间复杂度为 O(1), 不过,存在着一个函数可快速的分配内存。(见 cvSetNew)
SetRemove
从点集中删除元素
void cvSetRemove( CvSet* set_header, int index );
set_header
集合
index
被删元素的索引值
函数 cvSetRemove 从点集中删除一具有特定索引值的元素。如果指定位置的节点为空,函数将什么都不做。函数的时间复杂度为 O(1), 不过,存在一函数可更快速的完成该操作,该函数就是 cvSetRemoveByPtr
SetNew
添加元素到点集中
CvSetElem* cvSetNew( CvSet* set_header );
set_header
集合
函数 cvSetNew 是 cvSetAdd 的变体,内联函数。它占用一新节点,并返回指向该节点的指针而不是索引。
SetRemoveByPtr
删除指针指向的集合元素
void cvSetRemoveByPtr( CvSet* set_header, void* elem );
set_header
集合
elem
被删除的元素
函数 cvSetRemoveByPtr 是一内联函数,是函数 cvSetRemove 轻微变化而来的。该函数并不会检查节点是否为空 -- 用户负责这一检查。
GetSetElem
通过索引值查找相应的集合元素
CvSetElem* cvGetSetElem( const CvSet* set_header, int index );
set_header
集合
index
索引值
函数 cvGetSetElem 通过索引值查找相应的元素。函数返回指向该元素的指针,如果索引值无效或相应的节点为空,则返回 0。 若函数使用 cvGetSeqElem 去查找节点,则函数支持负的索引值。
ClearSet
清空点集
void cvClearSet( CvSet* set_header );
set_header
待清空的点集
函数 cvClearSet 删除集合中的所有元素。时间复杂度为 O(1).
图
CvGraph
有向权图和无向权图
#define CV_GRAPH_VERTEX_FIELDS() \
int flags; \
struct CvGraphEdge* first;
typedef struct CvGraphVtx
{
CV_GRAPH_VERTEX_FIELDS()
}
CvGraphVtx;
#define CV_GRAPH_EDGE_FIELDS() \
int flags; \
float weight; \
struct CvGraphEdge* next[2]; \
\
struct CvGraphVtx* vtx[2];
typedef struct CvGraphEdge
{
CV_GRAPH_EDGE_FIELDS()
}
CvGraphEdge;
#define CV_GRAPH_FIELDS() \
CV_SET_FIELDS() \
CvSet* edges;
typedef struct CvGraph
{
CV_GRAPH_FIELDS()
}
CvGraph;
在 OpenCV 图形结构中,CvGraph 是一基本结构。
图形结构继承自 CvSet -- 该部分描绘了普通图的属性和图的顶点,也包含了一个点集作为其成员 -- 该点集描述了图的边缘。利用宏(可以简化结构扩展和定制)使用与其它OpenCV可扩展结构一样的方法和技巧,同样的方法和技巧,我们声明了定点,边和头部结构。虽然顶点结构和边结构无法从CvSetElem 显式地继承时,但它们满足点集元素的两个条件(在开始是有一个整数域和满足 CvSetElem 结构)。 flags 域用来标记顶点和边是否已被占用或者处于其他目的,如:遍历图时(见:cvStartScanGraph 等),因此最好不要去直接使用它们。图代表的就是边的集合。存在有向和无向的区别。对于后者(无向图),在连接顶点 A 到 顶点 B 的边同连接顶点 B 到 顶点 A的边是没什么区别的,在某一时刻,只可能存在一个,即:要么是<A, B>要么是<B, A>.
CreateGraph
创建一个空树
CvGraph* cvCreateGraph( int graph_flags, int header_size, int vtx_size,
int edge_size, CvMemStorage* storage );
graph_flags
被创建的图的类型。通常,无向图为 CV_SEQ_KIND_GRAPH,有向图为 CV_SEQ_KIND_GRAPH | CV_GRAPH_FLAG_ORIENTED.
header_size
头部大小;可能小于 sizeof(CvGraph)
vtx_size
顶点大小;常规的定点结构必须来自 CvGraphVtx (使用宏 CV_GRAPH_VERTEX_FIELDS())
edge_size
边的大小;常规的边结构必须来自 CvGraphEdge (使用宏 CV_GRAPH_EDGE_FIELDS())
storage
图的容器
函数 cvCreateGraph 创建一空图并且返回指向该图的指针。
GraphAddVtx
插入一顶点到图中
int cvGraphAddVtx( CvGraph* graph, const CvGraphVtx* vtx=NULL,
CvGraphVtx** inserted_vtx=NULL );
graph
图
vtx
可选输入参数,用来初始化新加入的顶点(仅大小超过 sizeof(CvGraphVtx) 的用户自定义的域才会被拷贝)
inserted_vertex
可选的输出参数。如果不为 NULL, 则传回新加入顶点的地址
函数 cvGraphAddVtx 将一顶点加入到图中,并返回定点的索引
GraphRemoveVtx
通过索引从图中删除一顶点
int cvGraphRemoveVtx( CvGraph* graph, int index );
graph
图
vtx_idx
被珊顶点的索引
函数 cvGraphRemoveAddVtx 从图中删除一顶点,连同删除含有此顶点的边。如果输入的顶点不属于该图的话,将报告删除出错(不存在而无法删除)。返回值为被删除的边数,如果顶点不属于该图的话,返回 -1。
GraphRemoveVtxByPtr
通过指针从图中删除一顶点
int cvGraphRemoveVtxByPtr( CvGraph* graph, CvGraphVtx* vtx );
graph
图
vtx
指向被删除的边的指针
函数 cvGraphRemoveVtxByPtr 从图中删除一顶点,连同删除含有此顶点的边。如果输入的顶点不属于该图的话,将报告删除出错(不存在而无法删除)。返回值为被删除的边数,如果顶点不属于该图的话,返回 -1。
GetGraphVtx
通过索引值查找图的相应顶点
CvGraphVtx* cvGetGraphVtx( CvGraph* graph, int vtx_idx );
graph
图
vtx_idx
定点的索引值
函数 cvGetGraphVtx 通过索引值查找对应的顶点,并返回指向该顶点的指针,如果不存在则返回 NULL.
GraphVtxIdx
返回定点相应的索引值
int cvGraphVtxIdx( CvGraph* graph, CvGraphVtx* vtx );
graph
图
vtx
指向顶点的指针
函数 cvGraphVtxIdx 返回与顶点相应的索引值
GraphAddEdge
通过索引值在图中加入一条边
int cvGraphAddEdge( CvGraph* graph, int start_idx, int end_idx,
const CvGraphEdge* edge=NULL, CvGraphEdge** inserted_edge=NULL );
graph
图
start_idx
边的起始顶点的索引值
end_idx
边的尾部顶点的索引值(对于无向图,参数的次序无关紧要,即:start_idx 和 end_idx 可互为起始顶点和尾部顶点)
edge
可选的输入参数,初始化边的数据
inserted_edge
可选的输出参数,包含被插入的边的地址。
函数 cvGraphAddEdge 连接两特定的顶点。如果该边成功地加入到图中,返回 1; 如果连接两顶点的边已经存在,返回 0;如果顶点没被发现(不存在)或者起始顶点和尾部顶点是同一个定点,或其他特殊情况,返回 -1。如果是后者(即:返回值为负),函数默认的报告一个错误。
GraphAddEdgeByPtr
通过指针在图中加入一条边
int cvGraphAddEdgeByPtr( CvGraph* graph, CvGraphVtx* start_vtx, CvGraphVtx* end_vtx,
const CvGraphEdge* edge=NULL, CvGraphEdge** inserted_edge=NULL );
graph
图
start_vtx
指向起始顶点的指针
end_vtx
指向尾部顶点的指针。对于无向图来说,顶点参数的次序无关紧要。
edge
可选的输入参数,初始化边的数据
inserted_edge
可选的输出参数,包含被插入的边的地址。
函数 cvGraphAddEdge 连接两特定的顶点。如果该边成功地加入到图中,返回 1; 如果连接两顶点的边已经存在,返回 0;如果顶点没被发现(不存在)或者起始顶点和尾部顶点是同一个定点,或其他特殊情况,返回 -1。如果是后者(即:返回值为负),函数默认的报告一个错误
GraphRemoveEdge
通过索引值从图中删除顶点
void cvGraphRemoveEdge( CvGraph* graph, int start_idx, int end_idx );
graph
图
start_idx
起始顶点的索引值
end_idx
尾部顶点的索引值。对于无向图来说,顶点参数的次序无关紧要。
函数 cvGraphRemoveEdge 删除连接两特定顶点的边。若两顶点并没有相连接(即:不存在由这两个顶点连接的边),函数什么都不做。
GraphRemoveEdgeByPtr
通过指针从图中删除边
void cvGraphRemoveEdgeByPtr( CvGraph* graph, CvGraphVtx* start_vtx, CvGraphVtx* end_vtx );
graph
图
start_vtx
指向起始顶点的指针
end_vtx
指向尾部顶点的指针。对于无向图来说,顶点参数的次序无关紧要。
函数 cvGraphRemoveEdgeByPtr 删除连接两特定顶点的边。若两顶点并没有相连接(即:不存在由这两个顶点连接的边),函数什么都不做。
FindGraphEdge
通过索引值在图中查找相应的边
CvGraphEdge* cvFindGraphEdge( const CvGraph* graph, int start_idx, int end_idx );
#define cvGraphFindEdge cvFindGraphEdge
graph
图
start_idx
起始顶点的索引值
end_idx
尾部顶点的索引值。对于无向图来说,顶点参数的次序无关紧要
函数 cvFindGraphEdge 查找与两特定顶点相对应的边,并返回指向该边的指针。如果该边不存在,返回 NULL.
FindGraphEdgeByPtr
通过指针在图中查找相应的边
CvGraphEdge* cvFindGraphEdgeByPtr( const CvGraph* graph, const CvGraphVtx* start_vtx,
const CvGraphVtx* end_vtx );
#define cvGraphFindEdgeByPtr cvFindGraphEdgeByPtr
graph
图
start_vtx
指向起始顶点的指针
end_vtx
指向尾部顶点的指针。对于无向图来说,顶点参数的次序无关紧要。
函数 cvFindGraphEdgeByPtr 查找与两特定顶点相对应的边,并返回指向该边的指针。如果该边不存在,返回 NULL
GraphEdgeIdx
返回与该边相应的索引值
int cvGraphEdgeIdx( CvGraph* graph, CvGraphEdge* edge );
graph
图
edge
指向该边的指针
函数 cvGraphEdgeIdx 返回与边对应的索引值。
GraphVtxDegree
(通过索引值)统计与顶点相关联的边数
int cvGraphVtxDegree( const CvGraph* graph, int vtx_idx );
graph
图
vtx_idx
顶点对应的索引值
函数 cvGraphVtxDegree 返回与特定顶点相关联的边数,包括以该顶点为起始顶点的和尾部顶点的。统计边数,可以适用下列代码:
CvGraphEdge* edge = vertex->first; int count = 0;
while( edge )
{
edge = CV_NEXT_GRAPH_EDGE( edge, vertex );
count++;
}
宏 CV_NEXT_GRAPH_EDGE(edge, vertex) 返回依附于该顶点的下一条边。
GraphVtxDegreeByPtr
(通过指针)统计与顶点相关联的边数
int cvGraphVtxDegreeByPtr( const CvGraph* graph, const CvGraphVtx* vtx );
graph
图
vtx
顶点对应的指针
函数 cvGraphVtxDegreeByPtr 返回与特定顶点相关联的边数,包括以该顶点为起始顶点的和尾部顶点的
ClearGraph
删除图
void cvClearGraph( CvGraph* graph );
graph
图
函数 cvClearGraph 删除该图的所有顶点和边。时间复杂度为 O(1).
CloneGraph
克隆图
CvGraph* cvCloneGraph( const CvGraph* graph, CvMemStorage* storage );
graph
待拷贝的图
storage
容器,存放拷贝
函数 cvCloneGraph 创建图的完全拷贝。如果顶点和边含有指向外部变量的指针,那么图和它的拷贝共享这些指针。在新的图中,顶点和边可能存在不同,因为函数重新分割了顶点和边的点集。
CvGraphScanner
图的遍历
typedef struct CvGraphScanner
{
CvGraphVtx* vtx;
CvGraphVtx* dst;
CvGraphEdge* edge;
CvGraph* graph;
CvSeq* stack;
int index;
int mask;
}
CvGraphScanner;
结构 cvGraphScanner 深度遍历整个图。函数的相关讨论如下(看:StartScanGraph)
StartScanGraph
创建一结构,用来对图进行深度遍历
CvGraphScanner* cvCreateGraphScanner( CvGraph* graph, CvGraphVtx* vtx=NULL,
int mask=CV_GRAPH_ALL_ITEMS );
graph
图
vtx
开始遍历的(起始)顶点。如果为 NULL, 便利就从第一个顶点开始(指:顶点序列中,具有最小索引值的顶点)
mask
事件掩码(event mask)代表用户感兴趣的事件(此时 函数 cvNextGraphItem 将控制返回给用户)。这个只可能是 CV_GRAPH_ALL_ITEMS (如果用户对所有的事件都感兴趣的话)或者是下列标志的组合:
CV_GRAPH_VERTEXT -- 在第一次被访问的顶点处停下
CV_GRAPH_TREE_EDGE -- 在 tree edge 处停下(tree edge 指连接最后被访问的顶点与接下来被访问的顶点的边)
CV_GRAPH_BACK_EDGE -- 在 back edge 处停下(back edge 指连接最后被访问的顶点与其在搜索树中祖先的边)
CV_GRAPH_FORWARD_EDGE -- 在 forward edge 处停下 (forward edge 指连接最后被访问的顶点与其在搜索树中后裔的边)
CV_GRAPH_CROSS_EDGE -- 在 cross edge 处停下(cross edge 指连接不同搜索树中或同一搜索树中不同分支的边.只有在有向图中,才存在着一概念)
CV_GRAPH_ANY_EDGE -- 在 any edge 处停下(any edge 指 任何边,包括 tree edge, back edge, forward edge, cross edge)
CV_GRAPH_NEW_TREE -- 在每一个新的搜索树开始处停下。首先遍历从起始顶点开始可以访问到的顶点和边,然后查找搜索图中访问不到的顶点或边并恢复遍历。在开始遍历一颗新的树时(包括第一次调用 cvNextGraphItem 时的树),产生 CV_GRAPH_NEW_TREE 事件。
函数 cvCreateGraphScanner 创建一结构用来深度遍历搜索树。函数 cvNextGraphItem 要使用该初始化了的结构 -- 层层遍历的过程。
NextGraphItem
逐层遍历整个图
int cvNextGraphItem( CvGraphScanner* scanner );
scanner
图的遍历状态。被此函数更新。
函数 cvNextGraphItem 遍历整个图,直到用户感兴趣的事件发生(即:调用 cvCreateGraphScanner 时, mask 对应的事件)或遍历结束。在前面一种情况下,函数返回 参数mask 相应的事件,当再次调用函数时,恢复遍历)。在后一种情况下,返回 CV_GRAPH_OVER(-1)。当 mask 相应的事件为 CV_GRAPH_BACKTRACKING 或 CV_GRAPH_NEW_TEEE 时, 当前正在被访问的顶点被存放在 scanner->vtx 中。如果事件与 边edge 相关,那幺 edge 本身被存放在 scanner->edge, 该边的起始顶点存放在 scanner->vtx 中, 尾部节点存放在 scanner->dst 中。
ReleaseGraphScanner
完成图地遍历过程
void cvReleaseGraphScanner( CvGraphScanner** scanner );
scanner
指向遍历器的指针.
函数 cvGraphScanner 完成图的遍历过程,并释放遍历器的状态。
树
CV_TREE_NODE_FIELDS
用于树结点类型声明的(助手)宏
#define CV_TREE_NODE_FIELDS(node_type) \
int flags; \
int header_size; \
struct node_type* h_prev; \
struct node_type* h_next; \
struct node_type* v_prev; \
struct node_type* v_next;
宏 CV_TREE_NODE_FIELDS() 用来声明一层次性结构,例如 CvSeq -- 所有动态结构的基本类型。如果树的节点是由该宏所声明的,那么就可以使用(该部分的)以下函数对树进行相关操作。
CvTreeNodeIterator
打开现存的存储结构或者创建新的文件存储结构
typedef struct CvTreeNodeIterator
{
const void* node;
int level;
int max_level;
}
CvTreeNodeIterator;
结构 CvTreeNodeIterator 用来对树进行遍历。该树的节点是由宏 CV_TREE_NODE_FIELDS 声明。
InitTreeNodeIterator
用来初始化树结点的迭代器
void cvInitTreeNodeIterator( CvTreeNodeIterator* tree_iterator,
const void* first, int max_level );
tree_iterator
初始化了的迭代器
first
(开始)遍历的第一个节点
max_level
限制对树进行遍历的最高层(即:第 max_level 层)(假设第一个节点所在的层为第一层)。例如:1 指的是遍历第一个节点所在层,2 指的是遍历第一层和第二层
函数 cvInitTreeNodeIterator 用来初始化树的迭代器。
NextTreeNode
返回当前节点,并将迭代器 iterator 移向当前节点的下一个节点
void* cvNextTreeNode( CvTreeNodeIterator* tree_iterator );
tree_iterator
初始化了的迭代器
函数 cvNextTreeNode 返回当前节点并且更新迭代器(iterator) -- 并将 iterator 移向(当前节点)下一个节点。换句话说,函数的行为类似于表达式 *p++ (通常的 C 指针 或 C++ 集合迭代器)。如果没有更多的节点(即:当前节点为最后的节点),则函数返回值为 NULL.
PrevTreeNode
返回当前节点,并将迭代器 iterator 移向当前节点的前一个节点
void* cvPrevTreeNode( CvTreeNodeIterator* tree_iterator );
tree_iterator
初始化了的迭代器
函数 cvPrevTreeNode 返回当前节点并且更新迭代器(iterator) -- 并将 iterator 移向(当前节点的)前一个节点。换句话说,函数的行为类似于表达式 *p-- (通常的 C 指针 或 C++ 集合迭代器)。如果没有更多的节点(即:当前节点为头节点),则函数返回值为 NULL.
TreeToNodeSeq
将所有的节点指针(即:指向树结点的指针)收集到线性表 sequence 中
CvSeq* cvTreeToNodeSeq( const void* first, int header_size, CvMemStorage* storage );
first
初始树结点
header_size
线性表的表头大小,大小通常为 sizeof(CvSeq)
函数 cvTreeToNodeSeq 将树的节点指针挨个的存放到线性表中。存放的顺序以深度为先。
InsertNodeIntoTree
将新的节点插入到树中
void cvInsertNodeIntoTree( void* node, void* parent, void* frame );
node
待插入的节点
parent
树中的父节点(即:含有子节点的节点)
frame
顶部节点。如果节点parent 等同于节点frame, 则将节点的域 v_prev 设为 NULL 而不是 parent.
函数 cvInsertNodeIntoTree 将另一个节点插入到树中。函数不分配任何内存,仅仅修改树节点的连接关系。
RemoveNodeFromTree
从树中删除节点
void cvRemoveNodeFromTree( void* node, void* frame );
node
待删除的节点。
frame
顶部节点。如果 node->v.prev = NULL 且 node->h.prev = NULL, 则将 frame->v.next 设为 node->h.next
函数 cvRemoveNodeFromTree 从树中删除节点。它不会释放任何内存,仅仅修改树中节点的连接关系
曲线与形状
CV_RGB
创建一个色彩值.
#define CV_RGB( r, g, b ) cvScalar( (b), (g), (r) )
Line
绘制连接两个点的线段
void cvLine( CvArr* img, CvPoint pt1, CvPoint pt2, CvScalar color,
int thickness=1, int line_type=8, int shift=0 );
img
图像。
pt1
线段的第一个端点。
pt2
线段的第二个端点。
color
线段的颜色。
thickness
线段的粗细程度。
line_type
线段的类型。
8 (or 0) - 8-connected line(8邻接)连接 线。
4 - 4-connected line(4邻接)连接线。
CV_AA - antialiased 线条。
shift
坐标点的小数点位数。
函数cvLine 在图像中的点1和点2之间画一条线段。线段被图像或感兴趣的矩形(ROI rectangle)所裁剪。对于具有整数坐标的non-antialiasing 线条,使用8-连接或者4-连接Bresenham 算法。画粗线条时结尾是圆形的。画 antialiased 线条使用高斯滤波。要指定线段颜色,用户可以使用使用宏CV_RGB( r, g, b )。
Rectangle
绘制简单、指定粗细或者带填充的矩形
void cvRectangle( CvArr* img, CvPoint pt1, CvPoint pt2, CvScalar color,
int thickness=1, int line_type=8, int shift=0 );
img
图像.
pt1
矩形的一个顶点。
pt2
矩形对角线上的另一个顶点
color
线条颜色 (RGB) 或亮度(灰度图像)(grayscale image)。
thickness
组成矩形的线条的粗细程度。取负值时(如 CV_FILLED)函数绘制填充了色彩的矩形。
line_type
线条的类型。见cvLine的描述
shift
坐标点的小数点位数。
函数 cvRectangle 通过对角线上的两个顶点绘制矩形。
Circle
绘制圆形。
void cvCircle( CvArr* img, CvPoint center, int radius, CvScalar color,
int thickness=1, int line_type=8, int shift=0 );
img
图像。
center
圆心坐标。
radius
圆形的半径。
color
线条的颜色。
thickness
如果是正数,表示组成圆的线条的粗细程度。否则,表示圆是否被填充。
line_type
线条的类型。见 cvLine 的描述
shift
圆心坐标点和半径值的小数点位数。
函数cvCircle绘制或填充一个给定圆心和半径的圆。圆被感兴趣矩形所裁剪。若指定圆的颜色,可以使用宏 CV_RGB ( r, g, b )。
Ellipse
绘制椭圆圆弧和椭圆扇形。
void cvEllipse( CvArr* img, CvPoint center, CvSize axes, double angle,
double start_angle, double end_angle, CvScalar color,
int thickness=1, int line_type=8, int shift=0 );
img
图像。
center
椭圆圆心坐标。
axes
轴的长度。
angle
偏转的角度。
start_angle
圆弧起始角的角度。.
end_angle
圆弧终结角的角度。
color
线条的颜色。
thickness
线条的粗细程度。
line_type
线条的类型,见CVLINE的描述。
shift
圆心坐标点和数轴的精度。
函数cvEllipse用来绘制或者填充一个简单的椭圆弧或椭圆扇形。圆弧被ROI矩形所忽略。反走样弧线和粗弧线使用线性分段近似值。所有的角都是以角度的形式给定的。下面的图片将解释这些参数的含义。
Parameters of Elliptic Arc
EllipseBox
使用一种简单的方式来绘制椭圆圆弧和椭圆扇形。
void cvEllipseBox( CvArr* img, CvBox2D box, CvScalar color,
int thickness=1, int line_type=8, int shift=0 );
img
图像。
box
绘制椭圆圆弧所需要的外界矩形.
thickness
分界线线条的粗细程度。
line_type
分界线线条的类型,见CVLINE的描述。
shift
椭圆框顶点坐标的精度。
The function cvEllipseBox draws a simple or thick ellipse outline, or fills an ellipse. The functions provides a convenient way to draw an ellipse approximating some shape; that is what cvCamShift and cvFitEllipse do. The ellipse drawn is clipped by ROI rectangle. A piecewise-linear approximation is used for antialiased arcs and thick arcs.
FillPoly
填充多边形内部
void cvFillPoly( CvArr* img, CvPoint** pts, int* npts, int contours,
CvScalar color, int line_type=8, int shift=0 );
img
图像。
pts
指向多边形的数组指针。
npts
多边形的顶点个数的数组。
contours
组成填充区域的线段的数量。
color
多边形的颜色。
line_type
组成多边形的线条的类型。
shift
顶点坐标的小数点位数。
函数cvFillPoly用于一个单独被多边形轮廓所限定的区域内进行填充。函数可以填充复杂的区域,例如,有漏洞的区域和有交叉点的区域等等。
FillConvexPoly
填充凸多边形
void cvFillConvexPoly( CvArr* img, CvPoint* pts, int npts,
CvScalar color, int line_type=8, int shift=0 );
img
图像。
pts
指向单个多边形的指针数组。
npts
多边形的顶点个数。
color
多边形的颜色。
line_type
组成多边形的线条的类型。参见cvLine
shift
顶点坐标的小数点位数。
函数cvFillConvexPoly填充凸多边形内部。这个函数比函数cvFillPoly 更快。它除了可以填充凸多边形区域还可以填充任何的单调多边形。例如:一个被水平线(扫描线)至多两次截断的多边形。
PolyLine
绘制简单线段或折线。
void cvPolyLine( CvArr* img, CvPoint** pts, int* npts, int contours, int is_closed,
CvScalar color, int thickness=1, int line_type=8, int shift=0 );
img
图像。
pts
折线的顶点指针数组。
npts
折线的定点个数数组。也可以认为是pts指针数组的大小
contours
折线的线段数量。
is_closed
指出多边形是否封闭。如果封闭,函数将起始点和结束点连线。
color
折线的颜色。
thickness
线条的粗细程度。
line_type
线段的类型。参见cvLine。
shift
顶点的小数点位数。
函数cvPolyLine 绘制一个简单直线或折线。
文本
InitFont
初始化字体结构体。
void cvInitFont( CvFont* font, int font_face, double hscale,
double vscale, double shear=0,
int thickness=1, int line_type=8 );
font
被初始化的字体结构体。
font_face
字体名称标识符。只是Hershey 字体集( http://sources.isc.org/utils/misc/hershey-font.txt )的一个子集得到支持。
CV_FONT_HERSHEY_SIMPLEX - 正常大小无衬线字体。
CV_FONT_HERSHEY_PLAIN - 小号无衬线字体。
CV_FONT_HERSHEY_DUPLEX - 正常大小无衬线字体。( 比CV_FONT_HERSHEY_SIMPLEX更复杂)
CV_FONT_HERSHEY_COMPLEX - 正常大小有衬线字体。
CV_FONT_HERSHEY_TRIPLEX - 正常大小有衬线字体 ( 比CV_FONT_HERSHEY_COMPLEX更复杂)
CV_FONT_HERSHEY_COMPLEX_SMALL - CV_FONT_HERSHEY_COMPLEX 的小译本。
CV_FONT_HERSHEY_SCRIPT_SIMPLEX - 手写风格字体。
CV_FONT_HERSHEY_SCRIPT_COMPLEX - 比CV_FONT_HERSHEY_SCRIPT_SIMPLEX更复杂。
这个参数能够由一个值和可选择的CV_FONT_ITALIC字体标记合成,就是斜体字。
hscale
字体宽度。如果等于1.0f,字符的宽度是最初的字体宽度。如果等于0.5f,字符的宽度是最初的字体宽度的一半。
vscale
字体高度。如果等于1.0f,字符的高度是最初的字体高度。如果等于0.5f,字符的高度是最初的字体高度的一半。
shear
字体的斜度。当值为0时,字符不倾斜;当值为1.0f时,字体倾斜≈45度,等等。厚度让字母着重显示。函数cvLine用于绘制字母。
thickness
字体笔划的粗细程度。
line_type
字体笔划的类型,参见cvLine。
函数cvInitFont初始化字体结构体,字体结构体可以被传递到文字显示函数中。
PutText
在图像中显示文本字符串。
void cvPutText( CvArr* img, const char* text, CvPoint org, const CvFont* font, CvScalar color );
img
输入图像。
text
要显示的字符串。
org
第一个字符左下角的坐标。
font
字体结构体。
color
文本的字体颜色。
函数cvPutText将具有指定字体的和指定颜色的文本加载到图像中。加载到图像中的文本被感兴趣的矩形框(ROI rectangle)剪切。不属于指定字体库的字符用矩形字符替代显示。
GetTextSize
获得字符串的宽度和高度。
void cvGetTextSize( const char* text_string, const CvFont* font, CvSize* text_size, int* baseline );
font
字体结构体
text_string
输入字符串。
text_size
合成字符串的字符的大小。文本的高度不包括基线以下的部分。
baseline
相对于文字最底部点的基线的Y坐标。
函数cvGetTextSize是用于在指定字体时计算字符串的绑定区域(binding rectangle)。
点集和轮廓
DrawContours
在图像中绘制外部和内部的轮廓。
void cvDrawContours( CvArr *img, CvSeq* contour,
CvScalar external_color, CvScalar hole_color,
int max_level, int thickness=1,
int line_type=8, CvPoint offset=cvPoint(0,0) );
img
用以绘制轮廓的图像。和其他绘图函数一样,边界图像被感兴趣区域(ROI)所剪切。
contour
指针指向第一个轮廓。
external_color
外层轮廓的颜色。
hole_color
内层轮廓的颜色。
max_level
绘制轮廓的最大等级。如果等级为0,绘制单独的轮廓。如果为1,绘制轮廓及在其后的相同的级别下轮廓。如果值为2,所有的轮廓。如果等级为2,绘制所有同级轮廓及所有低一级轮廓,诸此种种。如果值为负数,函数不绘制同级轮廓,但会升序绘制直到级别为abs(max_level)-1的子轮廓。
thickness
绘制轮廓时所使用的线条的粗细度。如果值为负(e.g. =CV_FILLED),绘制内层轮廓。
line_type
线条的类型。参考cvLine.
offset
按照给出的偏移量移动每一个轮廓点坐标.当轮廓是从某些感兴趣区域(ROI)中提取的然后需要在运算中考虑ROI偏移量时,将会用到这个参数。
当thickness>=0,函数cvDrawContours在图像中绘制轮廓,或者当thickness<0时,填充轮廓所限制的区域。
#include "cv.h"
#include "highgui.h"
int main( int argc, char** argv )
{
IplImage* src;
// 第一条命令行参数确定了图像的文件名。
if( argc == 2 && (src=cvLoadImage(argv[1], 0))!= 0)
{
IplImage* dst = cvCreateImage( cvGetSize(src), 8, 3 );
CvMemStorage* storage = cvCreateMemStorage(0);
CvSeq* contour = 0;
cvThreshold( src, src, 1, 255, CV_THRESH_BINARY );
cvNamedWindow( "Source", 1 );
cvShowImage( "Source", src );
cvFindContours( src, storage, &contour, sizeof(CvContour), CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE );
cvZero( dst );
for( ; contour != 0; contour = contour->h_next )
{
CvScalar color = CV_RGB( rand()&255, rand()&255, rand()&255 );
cvDrawContours( dst, contour, color, color, -1, CV_FILLED, 8 );
}
cvNamedWindow( "Components", 1 );
cvShowImage( "Components", dst );
cvWaitKey(0);
}
}
在样本中用1替代 CV_FILLED 以指示的得到外形。
(注意:在cvFindContours中参数为CV_CHAIN_CODE时,cvDrawContours用CV_FILLED时不会画出任何图形)
InitLineIterator
初始化直线迭代器
int cvInitLineIterator( const CvArr* image, CvPoint pt1, CvPoint pt2,
CvLineIterator* line_iterator, int connectivity=8,
int left_to_right=0 );
img
用以获取直线的图像。
pt1
线段的第一个端点。
pt2
线段的第二个端点。
line_iterator
指向直线迭代状态结构体的指针。
connectivity
直线的邻接方式,4邻接或者8邻接。
left_to_right
标志值,指出扫描直线是从pt1和pt2外面最左边的点扫描到最右边的点(left_to_right≠0),还是按照指定的顺序,从pt1到pt2(left_to_right=0)。
函数cvInitLineIterator初始化直线迭代器并返回两个端点间点的数目。两个端点都必须在图像内部。在迭代器初始化以后,所有的在连接两个终点的栅栏线上的点,可以通过访问CV_NEXT_LINE_POINT点的方式获得。在线上的这些点使用4-邻接或者8-邻接的Bresenham算法计算得到。
例:使用直线迭代来计算沿着彩色线上的点的像素值。
CvScalar sum_line_pixels( IplImage* image, CvPoint pt1, CvPoint pt2 )
{
CvLineIterator iterator;
int blue_sum = 0, green_sum = 0, red_sum = 0;
int count = cvInitLineIterator( image, pt1, pt2, &iterator, 8, 0 );
for( int i = 0; i < count; i++ ){
blue_sum += iterator.ptr[0];
green_sum += iterator.ptr[1];
red_sum += iterator.ptr[2];
CV_NEXT_LINE_POINT(iterator);
{
int offset, x, y;
offset = iterator.ptr - (uchar*)(image->imageData);
y = offset/image->widthStep;
x = (offset - y*image->widthStep)/(3*sizeof(uchar) );
printf("(%d,%d)\n", x, y );
}
}
return cvScalar( blue_sum, green_sum, red_sum );
}
ClipLine
剪切图像矩形区域内部的直线。
int cvClipLine( CvSize img_size, CvPoint* pt1, CvPoint* pt2 );
img_size
图像的大小。
pt1
线段的第一个端点,会被函数修改。
pt2
线段的第二个端点,会被函数修改。
函数cvClipLine计算线段完全在图像中的一部分。如果线段完全在图像中,返回0,否则返回1。
Ellipse2Poly
用折线逼近椭圆弧
int cvEllipse2Poly( CvPoint center, CvSize axes,
int angle, int arc_start,
int arc_end, CvPoint* pts, int delta );
center
弧线的中心。
axes
弧线的Half-sizes。参见下图。
angle
椭圆的旋转角度(Rotation angle),参见下图。
start_angle
椭圆的Starting angle,参见下图。
end_angle
椭圆的Ending angle,参见下图。
pts
坐标点矩阵数组,由本函数填充。
delta
与下一条折线定点的夹角,近似精度。故,得到的点数最大为ceil((end_angle - start_angle)/delta) + 1。
函数cvEllipse2Poly计算给定的椭圆弧的逼近折线的顶点,被cvEllipse使用。