Cxcore数组操作
Wikipedia,自由的百科全书
初始化
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 ); /* get pointer to the element indices */
float val = *(float*)CV_NODE_VAL( array, node ); /* get value of the element
(assume that the type is CV_32FC1) */
printf( "(" );
for( i = 0; i < dims; i++ )
printf( "%4d%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]
变换和置换
Reshape
不拷贝数据修改矩阵/图像形状
CvMat* cvReshape( const CvArr* arr, CvMat* header, int new_cn, int new_rows=0 );
- arr
- 输入的数组.
- header
- 被添充的矩阵头
- new_cn
- 新的通道数.new_cn = 0 意味着不修改通道数
- new_rows
- 新的行数. 如果new_rows = 0保持原行数不修改否则根据 new_cn 值修改输出数组
函数 cvReshape 初始化 CvMat 头header 以便于让头指向修改后的形状(但数据保持原样)-也就是说修改通道数,修改行数或者两者者改变.
例如, 接下来的代码创建一个图像缓存、两个图像头,第一个是 320x240x3 图像第二个是 960x240x1 图像:
IplImage* color_img = cvCreateImage( cvSize(320,240), IPL_DEPTH_8U, 3 ); CvMat gray_mat_hdr; IplImage gray_img_hdr, *gray_img; cvReshape( color_img, &gray_mat_hdr, 1 ); gray_img = cvGetImage( &gray_mat_hdr, &gray_img_hdr );
下一个例子转换3x3 矩阵成单向量 1x9
CvMat* mat = cvCreateMat( 3, 3, CV_32F ); CvMat row_header, *row; row = cvReshape( mat, &row_header, 0, 1 );
ReshapeMatND
修改多维数组形状,拷贝/不拷贝数据
CvArr* cvReshapeMatND( const CvArr* arr,
int sizeof_header, CvArr* header,
int new_cn, int new_dims, int* new_sizes );
#define cvReshapeND( arr, header, new_cn, new_dims, new_sizes ) \
cvReshapeMatND( (arr), sizeof(*(header)), (header), \
(new_cn), (new_dims), (new_sizes))
- arr
- 输入数组
- sizeof_header
- 输出头的大小,对于IplImage, CvMat 和 CvMatND 各种结构输出的头均是不同的.
- header
- 被添充的输出头.
- new_cn
- 新的通道数,如果new_cn = 0 则通道数保持原样
- new_dims
- 新的维数. 如果new_dims = 0 则维数保持原样。
- new_sizes
- 新的维大小.只有当 new_dims=1值被使用,因为要保持数组的总数一致,因此如果 new_dims = 1, new_sizes 是不被使用的
函数cvReshapeMatND 是 cvReshape 的高级版本,它可以处理多维数组(能够处理通用的图像和矩阵)并且修改维数,下面的是使用cvReshapeMatND重写 cvReshape的二个例子 :
IplImage* color_img = cvCreateImage( cvSize(320,240), IPL_DEPTH_8U, 3 );
IplImage gray_img_hdr, *gray_img;
gray_img = (IplImage*)cvReshapeND( color_img, &gray_img_hdr, 1, 0, 0 );
...
/*second example is modified to convert 2x2x2 array to 8x1 vector */
int size[] = { 2, 2, 2 };
CvMatND* mat = cvCreateMatND( 3, size, CV_32F );
CvMat row_header, *row;
row = cvReshapeND( mat, &row_header, 0, 1, 0 );
Repeat
用原数组管道式添充输出数组
void cvRepeat( const CvArr* src, CvArr* dst );
- src
- 输入数组, 图像或矩阵。
- dst
- 输出数组,图像或矩阵
函数cvRepeat 使用被管道化的原数组添充输出数组:
dst(i,j)=src(i mod rows(src), j mod cols(src))
因此 ,输出数组可能小于也可能大于输入数组.
Flip
垂直,水平或即垂直又水平翻转二维数组
void cvFlip( const CvArr* src, CvArr* dst=NULL, int flip_mode=0); #define cvMirror cvFlip
- src
- 原数组.
- dst
- 目标责任制数组. 如果 dst = NULL 翻转是在内部替换.
- flip_mode
- 指定怎样去翻转数组。
- flip_mode = 0 沿X-轴翻转, flip_mode > 0 (如 1) 沿Y-轴翻转, flip_mode < 0 (如 -1) 沿X-轴和Y-轴翻转.见下面的公式
函数cvFlip 以三种方式之一翻转数组 (行和列下标是以0为基点的):
dst(i,j)=src(rows(src)-i-1,j) if flip_mode = 0 dst(i,j)=src(i,cols(src1)-j-1) if flip_mode > 0 dst(i,j)=src(rows(src)-i-1,cols(src)-j-1) if flip_mode < 0
函数主要使用在:
- 垂直翻转图像(flip_mode > 0)用于 顶-左和底-左图像结构的转换, 主要用于WIN32系统下的视频操作处理.
- 水平图像转换,使用连续的水平转换和绝对值差检查垂直轴对称(flip_mode > 0)
- 水平和垂直同时转换,用于连续的水平转换和绝对真理值差检查中心对称s(flip_mode < 0)
- 翻转1维指针数组的顺序(flip_mode > 0)
Split
分割多通道数组成几个单通道数组或者从数组中提取一个通道
void cvSplit( const CvArr* src, CvArr* dst0, CvArr* dst1,
CvArr* dst2, CvArr* dst3 );
#define cvCvtPixToPlane cvSplit
- src
- 原数组.
- dst0...dst3
- 目标通道
函数 cvSplit 分割多通道数组成分离的单通道数组d。可获得两种操作模式 . 如果原数组有N通道且前N输出数组非NULL, 所有的通道都会被从原数组中提取,如果前N个通道只有一个通道非NULL函数只提取该指定通道,否则会产生一个错误,余下的通道(超过前N个通道的以上的)必须被设置成NULL,对于设置了COI的IplImage 结使用cvCopy 也可以从图像中提取单通道。
Merge
从几个单通道数组组合成多通道数组或插入一个单通道数组
void cvMerge( const CvArr* src0, const CvArr* src1,
const CvArr* src2, const CvArr* src3, CvArr* dst );
#define cvCvtPlaneToPix cvMerge
- src0... src3
- 输入的通道.
- dst
- 输出数组.
函数cvMerge 是前一个函数的反向操作。如果输出数组有N个通道并且前N个输入通道非NULL,就拷贝所有通道到输出数组,如果在前N个通道中只有一个单通道非NULL ,只拷贝这个通道到输出数组,否则 就会产生错误。除前N通道以外的余下的通道必须置NULL。对于设置了COI的 IplImage结构使用 cvCopy也可以实现向图像中插入一个通道 。
MixChannels
拷贝输入数组的若干个通道到输出数组的某些通道上面.
void cvMixChannels( const CvArr** src, int src_count,
CvArr** dst, int dst_count,
const int* from_to, int pair_count );
- src
- 输入数组
- src_count
- 输入数组的个数
- dst
- 输出数组
- dst_count
- 输出数组的个数
- from_to
- 对数的阵列
- pair_count
- from_to里面的对数的个数,或者说被拷贝的位面的个数.
RandShuffle
随机交换数组的元素
void cvRandShuffle( CvArr* mat, CvRNG* rng, double iter_factor=1.);
- mat
- 输入的矩阵,用来被随机处理.
- rng
- 随机数产生器用来随机交换数组元素.如果为NULL,一个当前的随机数发生器将被创建与使用.
- iter_factor
- 相关的参数,用来刻划交换操作的密度.请看下面的说明.
这个函数在每个反复的操作中交换随机选择的矩阵里面的元素(在多通道的数组里面每个元素可能包括若干个部分),反复的次数(也就是交换的对数)等于round(iter_factor*rows(mat)*cols(mat)), 因此如果iter_factor=0,没有交换产生,如果等于1意味着随机交换了rows(mat)*cols(mat)对数.
算术,逻辑和比较
LUT
利用查找表转换数组
void cvLUT( const CvArr* src, CvArr* dst, const CvArr* lut );
- src
- 元素为8位的原数组。
- dst
- 与原数组有相同通道数的输出数组,深度不确定
- lut
- 有256个元素的查找表;必须要与原输出数组有相同像深 。
函数cvLUT 使用查找表中的值添充输出数组. 坐标入口来自于原数组,也就是说函数处理每个元素按如下方式:
- dst(I)=lut[src(I)+DELTA]
这里当src的深度是CV_8U时DELTA=0 ,src的深度是CV_8S时 DELTA=128
ConvertScale
使用线性变换转换数组
void cvConvertScale( const CvArr* src, CvArr* dst, double scale=1, double shift=0 ); #define cvCvtScale cvConvertScale #define cvScale cvConvertScale #define cvConvert( src, dst ) cvConvertScale( (src), (dst), 1, 0 )
- src
- 输入数组.
- dst
- 输出数组
- scale
- 比例因子.
- shift
- 该加数被加到输入数组元素按比例缩放后得到的元素上
函数 cvConvertScale 有多个不同的目的因此就有多个同义函数(如上面的#define所示)。 该函数首先对输入数组的元素进行比例缩放,然后将shift加到比例缩放后得到的各元素上,即: dst(I)=src(I)*scale + (shift,shift,...),最后可选的类型转换将结果拷贝到输出数组。
多通道的数组对各个通道是独立处理的。
类型转换主要用舍入和溢出截断来完成。也就是如果缩放+转换后的结果值不能用输出数组元素类型值精确表达,就设置成在输出数组数据轴上最接近该数的值。
如果 scale=1, shift=0 就不会进行比例缩放. 这是一个特殊的优化,相当于该函数的同义函数名:cvConvert 。如果原来数组和输出数组的类型相同,这是另一种特殊情形,可以被用于比例缩放和平移矩阵或图像,此时相当于该函数的同义函数名:cvScale。
ConvertScaleAbs
使用线性变换转换输入数组元素成8位无符号整型
void cvConvertScaleAbs( const CvArr* src, CvArr* dst, double scale=1, double shift=0 ); #define cvCvtScaleAbs cvConvertScaleAbs
- src
- 原数组
- dst
- 输出数组 (深度为 8u).
- scale
- 比例因子.
- shift
- 原数组元素按比例缩放后添加的值。
函数 cvConvertScaleAbs 与前一函数是相同的,但它是存贮变换结果的绝对值:
dst(I)=abs(src(I)*scale + (shift,shift,...))
函数只支持目标数数组的深度为 8u (8-bit 无符号) , 对于别的类型函数仿效于cvConvertScale 和 cvAbs 函数的联合
Add
计算两个数组中每个元素的和
void cvAdd( const CvArr* src1, const CvArr* src2, CvArr* dst, const CvArr* mask=NULL );
- src1
- 第一个原数组
- src2
- 第二个原数组
- dst
- 输出数组
- mask
- 操作的覆盖面, 8-bit单通道数组; 只有覆盖面指定的输出数组被修改。
函数 cvAdd 加一个数组到别一个数组中:
dst(I)=src1(I)+src2(I) if mask(I)!=0
除覆盖面外所有的数组必须有相同的类型相同的大小(或ROI尺寸)。
AddS
计算数量和数组的和
void cvAddS( const CvArr* src, CvScalar value, CvArr* dst, const CvArr* mask=NULL );
- src
- 原数组.
- value
- 被加入数量
- dst
- 输出数组
- mask
- 操作的覆盖面(8-bit单通道数组) ; 只有覆盖面指定的输出数组被修改
函数 cvAddS 用数量值与原数组src1的每个元素想加并存贮结果到
dst(I)=src(I)+value if mask(I)!=0
除覆盖面外所有数组都必须有相同的类型,相同的大小(或ROI大小)
AddWeighted
计算两数组的加权值的和
void cvAddWeighted( const CvArr* src1, double alpha,
const CvArr* src2, double beta,
double gamma, CvArr* dst );
- src1
- 第一个原数组.
- alpha
- 第一个数组元素的权值
- src2
- 第二个原数组
- beta
- 第二个数组元素的权值
- dst
- 输出数组
- gamma
- 添加的常数项。
函数 cvAddWeighted 计算两数组的加权值的和:
dst(I)=src1(I)*alpha+src2(I)*beta+gamma
所有的数组必须的相同的类型相同的大小(或ROI大小)
Sub
计算两个数组每个元素的差
void cvSub( const CvArr* src1, const CvArr* src2, CvArr* dst, const CvArr* mask=NULL );
- src1
- 第一个原数组
- src2
- 第二个原数组.
- dst
- 输出数组.
- mask
- 操作覆盖面( 8-bit 单通道数组); 只有覆盖面指定的输出数组被修改
函数cvSub 从一个数组减去别一个数组:
dst(I)=src1(I)-src2(I) if mask(I)!=0
除覆盖面外所有数组都必须有相同的类型,相同的大小(或ROI大小)
SubS
计算数组和数量之间的差
void cvSubS( const CvArr* src, CvScalar value, CvArr* dst, const CvArr* mask=NULL );
- src
- 原数组.
- value
- 被减的数量.
- dst
- 输出数组.
- mask
- 操作覆盖面( 8-bit 单通道数组); 只有覆盖面指定的输出数组被修改
函数 cvSubS 从原数组的每个元素中减去一个数量:
dst(I)=src(I)-value if mask(I)!=0
除覆盖面外所有数组都必须有相同的类型,相同的大小(或ROI大小)。
SubRS
计算数量和数组之间的差
void cvSubRS( const CvArr* src, CvScalar value, CvArr* dst, const CvArr* mask=NULL );
- src
- 第一个原数组。
- value
- 被减的数量
- dst
- 输出数组
- mask
- 操作覆盖面( 8-bit 单通道数组); 只有覆盖面指定的输出数组被修改
函数 cvSubRS 从一个数量减去原数组的每个元素:
dst(I)=value-src(I) if mask(I)!=0
除覆盖面外所有数组都必须有相同的类型,相同的大小(或ROI大小)。
Mul
计算两个数组中每个元素的积
void cvMul( const CvArr* src1, const CvArr* src2, CvArr* dst, double scale=1 );
- src1
- 第一个原数组.
- src2
- 第二个原数组.
- dst
- 输出数组.
- scale
- 设置的比例因子
函数 cvMul 计算两个数组中每个元素的积:
dst(I)=scale•src1(I)•src2(I)
所有的数组必须有相同的类型和相同的大小(或ROI大小)
Div
两个数组每个元素相除
void cvDiv( const CvArr* src1, const CvArr* src2, CvArr* dst, double scale=1 );
- src1
- 第一个原数组。如该指针为NULL,假高该数组的所有元素都为1
- src2
- 第二个原数组。
- dst
- 输出数组
- scale
- 设置的比例因子
函数 cvDiv 用一个数组除以另一个数组:
dst(I)=scale•src1(I)/src2(I), if src1!=NULL dst(I)=scale/src2(I),: if src1=NULL
所有的数组必须有相同的类型和相同的大小(或ROI大小)
And
计算两个数组的每个元素的按位与
void cvAnd( const CvArr* src1, const CvArr* src2, CvArr* dst, const CvArr* mask=NULL );
- src1
- 第一个原数组
- src2
- 第二个原数组.
- dst
- 输出数组
- mask
- 操作覆盖面( 8-bit 单通道数组); 只有覆盖面指定的输出数组被修改
函数 cvAnd 计算两个数组的每个元素的按位逻辑与:
dst(I)=src1(I)&src2(I) if mask(I)!=0
对浮点数组按位表示操作是很有利的。除覆盖面,所有数组都必须有相同的类型,相同的大小(或ROI大小)。
AndS
计算数组每个元素与数量之间的按位与
void cvAndS( const CvArr* src, CvScalar value, CvArr* dst, const CvArr* mask=NULL );
- src
- 原数组.
- value
- 操作中用到的数量
- dst
- 输出数组
- mask
- 操作覆盖面( 8-bit 单通道数组); 只有覆盖面指定的输出数组被修改
函数 AndS 计算数组中每个元素与数量之量的按位与:
dst(I)=src(I)&value if mask(I)!=0
在实际操作之前首先把数量类型转换成与数组相同的类型。对浮点数组按位表示操作是很有利的。除覆盖面,所有数组都必须有相同的类型,相同的大小(或ROI大小)。
接下来的例子描述怎样计算浮点数组元素的绝对值,通过清除最前面的符号位:
float a[] = { -1, 2, -3, 4, -5, 6, -7, 8, -9 };
CvMat A = cvMat( 3, 3, CV_32F, &a );
int i, abs_mask = 0x7fffffff;
cvAndS( &A, cvRealScalar(*(float*)&abs_mask), &A, 0 );
for( i = 0; i < 9; i++ )
printf("%.1f ", a[i] );
代码结果是:
1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0
Or
计算两个数组每个元素的按位或
void cvOr( const CvArr* src1, const CvArr* src2, CvArr* dst, const CvArr* mask=NULL );
- src1
- 第一个原数组
- src2
- 第二个原数组
- dst
- 输出数组.
- mask
- 操作覆盖面( 8-bit 单通道数组); 只有覆盖面指定的输出数组被修改
函数 cvOr 计算两个数组每个元素的按位或:
dst(I)=src1(I)|src2(I)
对浮点数组按位表示操作是很有利的。除覆盖面,所有数组都必须有相同的类型,相同的大小(或ROI大小)。
OrS
计算数组中每个元素与数量之间的按位或
void cvOrS( const CvArr* src, CvScalar value, CvArr* dst, const CvArr* mask=NULL );
- src1
- 原数组
- value
- 操作中用到的数量
- dst
- 目数组.
- mask
- 操作覆盖面( 8-bit 单通道数组); 只有覆盖面指定的输出数组被修改
函数 OrS 计算数组中每个元素和数量之间的按位或:
dst(I)=src(I)|value if mask(I)!=0
在实际操作之前首先把数量类型转换成与数组相同的类型。对浮点数组按位表示操作是很有利的。除覆盖面,所有数组都必须有相同的类型,相同的大小(或ROI大小)。
Xor
计算两个数组中的每个元素的按位异或
void cvXor( const CvArr* src1, const CvArr* src2, CvArr* dst, const CvArr* mask=NULL );
- src1
- 第一个原数组
- src2
- 第二个原数组.
- dst
- 输出数组
- mask
- 操作覆盖面( 8-bit 单通道数组); 只有覆盖面指定的输出数组被修改
函数 cvXor 计算两个数组元素的按位异或:
- dst(I)=src1(I)^src2(I) if mask(I)!=0
对浮点数组按位表示操作是很有利的。除覆盖面,所有数组都必须有相同的类型,相同的大小(或ROI大小)。
XorS
计算数组元素与数量之间的按位异或
void cvXorS( const CvArr* src, CvScalar value, CvArr* dst, const CvArr* mask=NULL );
- src
- 原数组
- value
- 操作中用到的数量
- dst
- 输出数组.
- mask
- 操作覆盖面( 8-bit 单通道数组); 只有覆盖面指定的输出数组被修改。
函数 XorS 计算数组元素与数量之间的按位异或:
dst(I)=src(I)^value if mask(I)!=0
在实际操作之前首先把数量类型转换成与数组相同的类型。对浮点数组按位表示操作是很有利的。除覆盖面,所有数组都必须有相同的类型,相同的大小(或ROI大小)。
下面例子描述怎样对共轭复数向量转换,通过转换前面的符号位:
float a[] = { 1, 0, 0, 1, -1, 0, 0, -1 }; /* 1, j, -1, -j */
CvMat A = cvMat( 4, 1, CV_32FC2, &a );
int i, neg_mask = 0x80000000;
cvXorS( &A, cvScalar( 0, *(float*)&neg_mask, 0, 0 ), &A, 0 );
for( i = 0; i < 4; i++ )
printf("(%.1f, %.1f) ", a[i*2], a[i*2+1] );
The code should print:
(1.0,0.0) (0.0,-1.0) (-1.0,0.0) (0.0,1.0)
Not
计算数组元素的按位取反
void cvNot( const CvArr* src, CvArr* dst );
- src1
- 原数组
- dst
- 输出数组
函数不取反每个数组元素的每一位
dst(I)=~src(I)
Cmp
比较两个数组元素P
void cvCmp( const CvArr* src1, const CvArr* src2, CvArr* dst, int cmp_op );
- src1
- 第一个原数组
- src2
- 第二个原数组,这两个数组必须有一个单通道
- dst
- 输出数组必须是 8u 或 8s 类型.
- cmp_op
- 该标识指定要检查的元素之间的关系:
- CV_CMP_EQ - src1(I) "等于" src2(I)
- CV_CMP_GT - src1(I) "大于" src2(I)
- CV_CMP_GE - src1(I) "大于等于" src2(I)
- CV_CMP_LT - src1(I) "小于" src2(I)
- CV_CMP_LE - src1(I) "小于等于" src2(I)
- CV_CMP_NE - src1(I) "不等于" src2(I)
函数 cvCmp 比较两个数组的对应元素并且添充输出数组:
dst(I)=src1(I) op src2(I),
这里 op 是 '=', '>', '>=', '<', '<=' or '!='.
如果元素之间的关系为真则设置dst(I)为 0xff (也就是所有的位都为 '1') 否则为0。除了输出数组所有数组必须是相同的类型相同的大小(或ROI大小)。
CmpS
比较数组的每个元素与数量的关系
void cvCmpS( const CvArr* src, double value, CvArr* dst, int cmp_op );
- src
- 原数,必须有一个单通道。
- value
- 用与数组元素比较的数量值
- dst
- 输出数组必须是 8u 或 8s 类型.
- cmp_op
- 该标识指定要检查的元素之间的关系:
- CV_CMP_EQ - src1(I) "等于" value
- CV_CMP_GT - src1(I) "大于" value
- CV_CMP_GE - src1(I) "大于等于" value
- CV_CMP_LT - src1(I) "小于" value
- CV_CMP_LE - src1(I) "小于等于" value
- CV_CMP_NE - src1(I) "不等于" value
函数 cvCmpS 比较数组元素与数量并且添充目标覆盖面数组:
dst(I)=src(I) op scalar,
这里 op 是 '=', '>', '>=', '<', '<=' or '!='.
如果元素之间的关系为真则设置dst(I)为 0xff (也就是所有的位都为 '1') 否则为0。所有的数组必须有相同的大小(或ROI大小)
InRange
检查数组元素是否在两个数组之间
void cvInRange( const CvArr* src, const CvArr* lower, const CvArr* upper, CvArr* dst );
- src
- 第一个原数组
- lower
- 包括进的下边界数组
- upper
- 不包括进的上边界线数组
- dst
- 输出数组必须是 8u 或 8s 类型.
函数 cvInRange 对输入的数组作范围检查,对于单通道数组:
dst(I)=lower(I)0 <= src(I)0 < upper(I)0
对二通道数组:
dst(I)=lower(I)0 <= src(I)0 < upper(I)0 &&
lower(I)1 <= src(I)1 < upper(I)1
以此类推
如果 src(I) 在范围内dst(I)被设置为 0xff (每一位都是 '1')否则置0 。 除了输出数组所有数组必须是相同的类型相同的大小(或ROI大小)。
InRangeS
检查数组元素是否在两个数量之间
void cvInRangeS( const CvArr* src, CvScalar lower, CvScalar upper, CvArr* dst );
- src
- 第一个原数组
- lower
- 包括进的下边界.
- upper
- 不包括进的上边界
- dst
- 输出数组必须是 8u 或 8s 类型.
函数 cvInRangeS 检查输入数组元素范围: 对于单通道数组:
dst(I)=lower0 <= src(I)0 < upper0
对于双通道数组以此类推:
dst(I)=lower0 <= src(I)0 < upper0 &&
lower1 <= src(I)1 < upper1
如果 src(I) 在范围内dst(I)被设置为 0xff (每一位都是 '1')否则置0 。所有的数组必须有相同的大小(或ROI大小)
Max
查找两个数组中每个元素的较大值
void cvMax( const CvArr* src1, const CvArr* src2, CvArr* dst );
- src1
- 第一个原数组
- src2
- 第二个原数组
- dst
- 输出数组
函数 cvMax 计算两个数组中每个元素的较大值:
dst(I)=max(src1(I), src2(I))
所有的数组必须的一个单通道,相同的数据类型和相同的大小(或ROI大小)
MaxS
查找数组元素与数量之间的较大值
void cvMaxS( const CvArr* src, double value, CvArr* dst );
- src
- 第一个原数组.
- value
- 数量值.
- dst
- 输出数组
函数 cvMaxS 计算数组元素和数量之间的较大值:
dst(I)=max(src(I), value)
所有数组必须有一个单一通道,相同的数据类型相同的大小(或ROI大小)
Min
查找两个数组元素之间 的较小值
void cvMin( const CvArr* src1, const CvArr* src2, CvArr* dst );
- src1
- 第一个原数组
- src2
- 第二个原数组.
- dst
- 输出数组.
函数cvMin计算两个数组元素的较小值
dst(I)=min(src1(I),src2(I))
所有数组必须有一个单一通道,相同的数据类型相同的大小(或ROI大小)
MinS
查找数组元素和数量之间的较大值
void cvMinS( const CvArr* src, double value, CvArr* dst );
- src
- 第一个原数组
- value
- 数量值.
- dst
- 输出数组..
函数 cvMinS 计算数组元素和数量之量的较小值:
dst(I)=min(src(I), value)
所有数组必须有一个单一通道,相同的数据类型相同的大小(或ROI大小)
AbsDiff
计算两个数组差的绝对值
void cvAbsDiff( const CvArr* src1, const CvArr* src2, CvArr* dst );
- src1
- 第一个原数组
- src2
- 第二个原数组
- dst
- 输出数组
函数 cvAbsDiff 计算两个数组差的绝对值
dst(I)c = abs(src1(I)c - src2(I)c).
所有数组必须有相同的数据类型相同的大小(或ROI大小)
AbsDiffS
计算数组元素与数量之间差的绝对值
void cvAbsDiffS( const CvArr* src, CvArr* dst, CvScalar value ); #define cvAbs(src, dst) cvAbsDiffS(src, dst, cvScalarAll(0))
- src
- 原数组.
- dst
- 输出数组
- value
- 数量.
函数 cvAbsDiffS 计算数组元素与数量之间差的绝对值
dst(I)c = abs(src(I)c - valuec).
所有数组必须有相同的数据类型相同的大小(或ROI大小)
统计
CountNonZero
计算非零数组元素
int cvCountNonZero( const CvArr* arr );
- arr
- 数组, 必须是单通道数组或者设置COI(感兴趣通道)的多通道图像。
函数 cvCountNonZero 返回arr中非零元素的数目:
result = sumI arr(I)!=0
当IplImage 支持ROI和COI。
Sum
计算数组元素的和
CvScalar cvSum( const CvArr* arr );
- arr
- 数组.
函数 cvSum 独立地为每一个通道计算数组元素的和 S :
Sc = sumI arr(I)c
如果数组是IplImage类型和设置了COI, 该函数只处理选定的通道并将和存储到第一个标量成员 (S0)。
Avg
计算数组元素的平均值
CvScalar cvAvg( const CvArr* arr, const CvArr* mask=NULL );
- arr
- 数组.
- mask
- 可选操作掩模
函数 cvAvg 独立地为每一个通道计算数组元素的平均值 M :
如果数组是 IplImage 类型和设置 COI , 该函数只处理选定的通道并将和存储到第一个标量成员 (S0)。
AvgSdv
计算数组元素的平均值
void cvAvgSdv( const CvArr* arr, CvScalar* mean, CvScalar* std_dev, const CvArr* mask=NULL );
- arr
- 数组
- mean
- 指向平均值的指针, 如果不需要的话可以为空( NULL)。
- std_dev
- 指向标准差的指针。
- mask
- 可选操作掩模。
函数 cvAvgSdv 独立地为每一个通道计算数组元素的平均值和标准差:
如果数组是 IplImage 类型和 设置了COI ,该函数只处理选定的通道并将平均值和标准差存储到第一个输出标量成员 (mean0 和 std-dev0)。
MinMaxLoc
查找数组和子数组的全局最小值和最大值
void cvMinMaxLoc( const CvArr* arr, double* min_val, double* max_val,
CvPoint* min_loc=NULL, CvPoint* max_loc=NULL, const CvArr* mask=NULL );
- arr
- 输入数组, 单通道或者设置了 COI 的多通道。
- min_val
- 指向返回的最小值的指针。
- max_val
- 指向返回的最大值的指针。
- min_loc
- 指向返回的最小值的位置指针。
- max_loc
- 指向返回的最大值的位置指针。
- mask
- 选择一个子数组的操作掩模。
函数 MinMaxLoc 查找元素中的最小值和最大值以及他们的位置。函数在整个数组、或选定的ROI区域(对IplImage)或当MASK不为NULL时指定的数组区域中,搜索极值 。如果数组不止一个通道,它就必须是设置了 COI 的 IplImage 类型。 如果是多维数组 min_loc->x 和 max_loc->x 将包含极值的原始位置信息 (线性的)。
Norm
计算数组的绝对范数, 绝对差分范数或者相对差分范数
double cvNorm( const CvArr* arr1, const CvArr* arr2=NULL, int norm_type=CV_L2, const CvArr* mask=NULL );
- arr1
- 第一输入图像
- arr2
- 第二输入图像 ,如果为空(NULL), 计算 arr1 的绝对范数,否则计算 arr1-arr2 的绝对范数或者相对范数。
- normType
- 范数类型,参见“讨论”。
- mask
- 可选操作掩模。
如果 arr2 为空(NULL),函数 cvNorm 计算 arr1 的绝对范数:
- norm = ||arr1||C = maxI abs(arr1(I)), 如果 normType = CV_C
- norm = ||arr1||L1 = sumI abs(arr1(I)), 如果 normType = CV_L1
- norm = ||arr1||L2 = sqrt( sumI arr1(I)2), 如果 normType = CV_L2
如果 arr2 不为空(NULL), 该函数计算绝对差分范数或者相对差分范数:
- norm = ||arr1-arr2||C = maxI abs(arr1(I)-arr2(I)), 如果 normType = CV_C
- norm = ||arr1-arr2||L1 = sumI abs(arr1(I)-arr2(I)), 如果 normType = CV_L1
- norm = ||arr1-arr2||L2 = sqrt( sumI (arr1(I)-arr2(I))2 ), 如果 normType = CV_L2
或者
- norm = ||arr1-arr2||C/||arr2||C, 如果 normType = CV_RELATIVE_C
- norm = ||arr1-arr2||L1/||arr2||L1, 如果 normType = CV_RELATIVE_L1
- norm = ||arr1-arr2||L2/||arr2||L2, 如果 normType = CV_RELATIVE_L2
函数 Norm 返回计算所得的范数。多通道数组被视为单通道处理,因此,所有通道的结果是结合在一起的。
Reduce
简化一个矩阵成为一个向量
cvReduce( const CvArr* src, CvArr* dst, int dim, int op=CV_REDUCE_SUM);
- src
- 输入矩阵
- dst
- 输出的通过处理输入矩阵的所有行/列而得到的单行/列向量
- dim
- 矩阵被简化后的维数索引.0意味着矩阵被处理成一行,1意味着矩阵被处理成为一列,-1时维数将根据输出向量的大小自动选择.
- op
- 简化操作的方式,可以有以下几种取值:
- CV_REDUCE_SUM-输出是矩阵的所有行/列的和.
- CV_REDUCE_AVG-输出是矩阵的所有行/列的平均向量.
- CV_REDUCE_MAX-输出是矩阵的所有行/列的最大值.
- CV_REDUCE_MIN-输出是矩阵的所有行/列的最小值.
这个函数通过把矩阵的每行/列当作一维向量并对其做某种特殊的操作将一个矩阵简化成为一个向量.例如,这个函数可以用于计算一个光栅图象的水平或者垂直投影.在取值为CV_REDUCE_AVG与CV_REDUCE_SUM的情况下输出可能有很大的位深度用于维持准确性,这两种方式也适合于处理多通道数组.
线性代数
DotProduct
用欧几里得准则计算两个数组的点积
double cvDotProduct( const CvArr* src1, const CvArr* src2 );
- src1
- 第一输入数组。
- src2
- 第二输入数组。
函数 cvDotProduct 计算并返回两个数组的欧几里得点积。
src1•src2 = sumI(src1(I)*src2(I))
如果是多通道数组,所有通道的结果是累加在一起的。特别地, cvDotProduct(a,a),将返回 ||a||2 ,这里 a 是一个复向量。 该函数可以处理多通道数组,逐行或逐层等等。
Normalize
根据某种范数或者数值范围归一化数组.
void cvNormalize( const CvArr* src, CvArr* dst,
double a=1, double b=0, int norm_type=CV_L2,
const CvArr* mask=NULL );
- src
- 输入数组
- dst
- 输出数组,支持原地运算
- a
- 输出数组的最小/最大值或者输出数组的范数
- b
- 输出数组的最大/最小值
- norm_type
- 归一化的类型,可以有以下的取值:
- CV_C - 归一化数组的C-范数(绝对值的最大值)
- CV_L1 - 归一化数组的L1-范数(绝对值的和)
- CV_L2 - 归一化数组的(欧几里德)L2-范数
- CV_MINMAX - 数组的数值被平移或缩放到一个指定的范围
- mask
- 操作掩膜,用于指示函数是否仅仅对指定的元素进行操作
该函数归一化输入数组使它的范数或者数值范围在一定的范围内
当norm_type==CV_MINMAX:
dst(i,j)=(src(i,j)-min(src))*(b'-a')/(max(src)-min(src)) + a', if mask(i,j)!=0
dst(i,j)=src(i,j) otherwise
其中b'=MAX(a,b), a'=MIN(a,b);
当norm_type!=CV_MINMAX:
dst(i,j)=src(i,j)*a/cvNorm(src,0,norm_type,mask), if mask(i,j)!=0
dst(i,j)=src(i,j) otherwise
下面是一个简单的例子: float v[3] = { 1, 2, 3 };
CvMat V = cvMat( 1, 3, CV_32F, v );
// make vector v unit-length;
// equivalent to
// for(int i=0;i<3;i++) v[i]/=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
cvNormalize( &V, &V );
CrossProduct
计算两个三维向量的叉积
void cvCrossProduct( const CvArr* src1, const CvArr* src2, CvArr* dst );
- src1
- 第一输入向量。
- src2
- 第二输入向量。
- dst
- 输出向量
函数 cvCrossProduct 计算两个三维向量的差积:
dst = src1 × src2, (dst1 = src12src23 - src13src22 , dst2 = src13src21 - src11src23 , dst3 = src11src22 - src12src21).
ScaleAdd
计算一个数组缩放后与另一个数组的和
void cvScaleAdd( const CvArr* src1, CvScalar scale, const CvArr* src2, CvArr* dst ); #define cvMulAddS cvScaleAdd
- src1
- 第一输入数组
- scale
- 第一输入数组的缩放因子
- src2
- 第二输入数组
- dst
- 输出数组
函数 cvScaleAdd 计算一个数组缩放后与另一个数组的和:
dst(I)=src1(I)*scale + src2(I)
所有的数组参数必须有相同的类型和大小。
GEMM
通用矩阵乘法
void cvGEMM( const CvArr* src1, const CvArr* src2, double alpha,
const CvArr* src3, double beta, CvArr* dst, int tABC=0 );
#define cvMatMulAdd( src1, src2, src3, dst ) cvGEMM( src1, src2, 1, src3, 1, dst, 0 )
#define cvMatMul( src1, src2, dst ) cvMatMulAdd( src1, src2, 0, dst )
- src1
- 第一输入数组
- src2
- 第二输入数组
- src3
- 第三输入数组 (偏移量),如果没有偏移量,可以为空( NULL) 。
- dst
- 输出数组
- tABC
- T操作标志,可以是 0 或者下面列举的值的组合:
- CV_GEMM_A_T - 转置 src1
- CV_GEMM_B_T - 转置 src2
- CV_GEMM_C_T - 转置 src3
- 例如, CV_GEMM_A_T+CV_GEMM_C_T 对应
- alpha*src1T*src2 + beta*src3T
函数 cvGEMM 执行通用矩阵乘法:
dst = alpha*op(src1)*op(src2) + beta*op(src3), 这里 op(X) 是 X 或者 XT
所有的矩阵应该有相同的数据类型和协调的矩阵大小。支持实数浮点矩阵或者复数浮点矩阵。
Transform
对数组每一个元素执行矩阵变换
void cvTransform( const CvArr* src, CvArr* dst, const CvMat* transmat, const CvMat* shiftvec=NULL );
- src
- 输入数组
- dst
- 输出数组
- transmat
- 变换矩阵
- shiftvec
- 可选偏移向量
函数 cvTransform 对数组 src 每一个元素执行矩阵变换并将结果存储到 dst:
- dst(I)=transmat*src(I) + shiftvec
或者
- dst(I)k=sumj(transmat(k,j)*src(I)j) + shiftvec(k)
N-通道数组 src 的每一个元素都被视为一个N元向量,使用一个 M×N 的变换矩阵 transmat 和偏移向量 shiftvec 把它变换到一个 M-通道的数组 dst 的一个元素中。 这里可以选择将偏移向量 shiftvec 嵌入到 transmat 中。这样的话 transmat 应该是 M×N+1 的矩阵,并且最右边的一列被看作是偏移向量 。
输入数组和输出数组应该有相同的位深(depth)和同样的大小或者 ROI 大小。 transmat 和 shiftvec 应该是实数浮点矩阵。
该函数可以用来进行 ND 点集的几何变换,任意的线性颜色空间变换,通道转换等。
PerspectiveTransform
向量数组的透视变换
void cvPerspectiveTransform( const CvArr* src, CvArr* dst, const CvMat* mat );
- src
- 输入的三通道浮点数组
- dst
- 输出三通道浮点数组
- mat
- 4 × 4 变换矩阵
函数 cvPerspectiveTransform 用下面的方式变换 src 的每一个元素 (通过将其视为二维或者三维的向量):
- (x, y, z) -> (x'/w, y'/w, z'/w)
或者
- (x, y) -> (x'/w, y'/w),
这里
- (x', y', z', w') = mat*(x, y, z, 1)
或者
- (x', y', w') = mat*(x, y, 1)
并且 w = w' 如果 w'!=0, 否则 w = inf
MulTransposed
计算数组和数组的转置的乘积
void cvMulTransposed( const CvArr* src, CvArr* dst, int order, const CvArr* delta=NULL );
- src
- 输入矩阵
- dst
- 目标矩阵
- order
- 乘法顺序
- delta
- 一个可选数组, 在乘法之前从 src 中减去该数组。
函数 cvMulTransposed 计算 src 和它的转置的乘积。
函数求值公式:
如果 order=0
- dst=(src-delta)*(src-delta)T
否则
- dst=(src-delta)T*(src-delta)
Trace
返回矩阵的迹
CvScalar cvTrace( const CvArr* mat );
- mat
- 输入矩阵
函数 cvTrace 返回矩阵mat的对角线元素的和。
tr(src) = ∑ mat(i,i) i
Transpose
矩阵的转置
void cvTranspose( const CvArr* src, CvArr* dst ); #define cvT cvTranspose
- src
- 输入矩阵
- dst
- 目标矩阵
函数 cvTranspose 对矩阵 src 求转置:
- dst(i,j)=src(j,i)
注意,假设是复数矩阵不会求得复数的共轭。共轭应该是独立的:查看的 cvXorS 例子代码。
Det
返回矩阵的行列式值
double cvDet( const CvArr* mat );
- mat
- 输入矩阵
函数 cvDet 返回方阵 mat 的行列式值。对小矩阵直接计算,对大矩阵用 高斯(GAUSSIAN)消去法。对于对称正定(positive-determined)矩阵也可以用 SVD 函数来求,U=V=NULL ,然后用 w 的对角线元素的乘积来计算行列式。
Invert
查找矩阵的逆矩阵或伪逆矩阵
double cvInvert( const CvArr* src, CvArr* dst, int method=CV_LU ); #define cvInv cvInvert
- src
- 输入矩阵
- dst
- 目标矩阵
- method
- 求逆方法:
- CV_LU -最佳主元选取的高斯消除法
- CV_SVD - 奇异值分解法 (SVD)
- CV_SVD_SYM - 正定对称矩阵的 SVD 方法
函数 cvInvert 对矩阵 src 求逆并将结果存储到 dst。
如果是 LU 方法该函数返回 src 的行列式值 (src 必须是方阵)。 如果是 0, 矩阵不求逆, dst 用 0 填充。
如果 SVD 方法该函数返回 src 的条件数的倒数(最小奇异值和最大奇异值的比值) ,如果 src 全为 0 则返回0。 如果 src 是奇异的, SVD 方法计算一个伪逆矩阵。
Solve
求解线性系统或者最小二乘法问题
int cvSolve( const CvArr* src1, const CvArr* src2, CvArr* dst, int method=CV_LU );
- src1
