初始化
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 也能处理他, 但是这个函数只能创建交叉存取图像.
header = cvCreateImageHeader(size,depth,channels); cvCreateData(header); //只是创建空间,并不会初始化空间内的数据
CreateImageHeader
分配,初始化,并且返回 IplImage结构IplImage* cvCreateImageHeader( CvSize size, int depth, int channels );
- size
- 图像宽、高.
- depth
- 像深 (见 CreateImage).
- channels
- 通道数 (见 CreateImage).
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 宏)
调用cvCreateImageHeader创建的图像,需要调用cvReleaseImageHeader释放图像头,然后将原始图像数据单独删除。
ReleaseImageHeader
释放头void cvReleaseImageHeader( IplImage** image );
- image
- 双指针指向头内存分配单元.
if( image ) { iplDeallocate( *image, IPL_IMAGE_HEADER | IPL_IMAGE_ROI ); *image = 0; }
然而IPL函数不是作为默认的 (见 CV_TURN_ON_IPL_COMPATIBILITY 宏)
ReleaseImage
释放头和图像数据void cvReleaseImage( IplImage** image );
- image
- 双指针指向图像内存分配单元。
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 字节.
CloneImage
制作图像的完整拷贝IplImage* cvCloneImage( const IplImage* image );
- image
- 原图像.
SetImageCOI
基于给定的值设置感兴趣通道void cvSetImageCOI( IplImage* image, int coi );
- image
- 图像头.
- coi
- 感兴趣通道.
GetImageCOI
返回感兴趣通道号int cvGetImageCOI( const IplImage* image );
- image
- 图像头.
SetImageROI
基于给定的矩形设置'感兴趣'区域void cvSetImageROI( IplImage* image, CvRect rect );
- image
- 图像.
- rect
- ROI 矩形.
ResetImageROI
释放图像的ROIvoid cvResetImageROI( IplImage* image );
- image
- 图像头.
cvSetImageROI( image, cvRect( 0, 0, image->width, image->height )); cvSetImageCOI( image, 0 );
但是后者的变量不分配 image->roi.
GetImageROI
返回图像的 ROI 坐标CvRect cvGetImageROI( const IplImage* image );
- image
- 图像头.
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).
ReleaseMat
删除矩阵void cvReleaseMat( CvMat** mat );
- mat
- 双指针指向矩阵.
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的最小可能值。也就是说默认情况下假定矩阵的行与行之间无隙.
例如, 下面的代码计算通用数组格式存贮的数据的矩阵乘积.
计算两个矩阵的积
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 mat; cvInitMatHeader( &mat, rows, cols, type, data, CV_AUTOSTEP );
CloneMat
创建矩阵拷贝CvMat* cvCloneMat( const CvMat* mat );
- mat
- 输入矩阵.
CreateMatND
创建多维密集数组CvMatND* cvCreateMatND( int dims, const int* sizes, int type );
- dims
- 数组维数. 但不许超过 CV_MAX_DIM (默认=32,但这个默认值可能在编译时被改变 )的定义
- sizes
- 数组的维大小.
- type
- 数组元素类型. 与 CvMat相同
CvMatND* mat = cvCreateMatNDHeader( dims, sizes, type ); cvCreateData( mat );
矩阵按行存贮. 所有的行以4个字节排列。.
CreateMatNDHeader
创建新的数组头CvMatND* cvCreateMatNDHeader( int dims, const int* sizes, int type );
- dims
- 数组维数.
- sizes
- 维大小.
- type
- 数组元素类型. 与 CvMat相同
ReleaseMatND
删除多维数组void cvReleaseMatND( CvMatND** mat );
- mat
- 指向数组的双指针.
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
- 可选的分配给矩阵头的数据指针.
CloneMatND
创建多维数组的完整拷贝CvMatND* cvCloneMatND( const CvMatND* mat );
- mat
- 输入数组
DecRefData
缩减数组数据的引用计数void cvDecRefData( CvArr* arr );
- arr
- 数组头.
- 使用cvSetData指派外部数据给矩阵头;
- 代表部分大的矩阵或图像的矩阵头;
- 是从图像头或N维矩阵头转换过来的矩阵头,
IncRefData
增加数组数据的引用计数int cvIncRefData( CvArr* arr );
- arr
- 数组头.
CreateData
分配数组数据void cvCreateData( CvArr* arr );
- arr
- 数组头.
ReleaseData
释放数组数据void cvReleaseData( CvArr* arr );
- arr
- 数组头
SetData
指派用户数据给数组头void cvSetData( CvArr* arr, void* data, int step );
- arr
- 数组头.
- data
- 用户数据.
- step
- 整行字节长.
GetRawData
返回数组的底层信息void cvGetRawData( const CvArr* arr, uchar** data, int* step=NULL, CvSize* roi_size=NULL );
- arr
- 数组头.
- data
- 输出指针,指针指向整个图像的结构或ROI
- step
- 输出行字节长
- roi_size
- 输出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函数对于多通道平面编排图像可以处理每个平面。
返回的 CvMat * 结构指向输入的header。 By Jackyzzy 赵振阳
GetImage
从不确定数组返回图像头IplImage* cvGetImage( const CvArr* arr, IplImage* image_header );
- arr
- 输入数组.
- image_header
- 指向IplImage结构的指针,该结构存贮在一个临时缓存 .
CreateSparseMat
创建稀疏数组CvSparseMat* cvCreateSparseMat( int dims, const int* sizes, int type );
- dims
- 数组维数。相对于密集型矩阵,稀疏数组的维数是不受限制的(最多可达 216)。
- sizes
- 数组的维大小。
- type
- 数组元素类型,见 CvMat。
ReleaseSparseMat
删除稀疏数组void cvReleaseSparseMat( CvSparseMat** mat );
- mat
- 双指针指向数组。
CloneSparseMat
创建稀疏数组的拷贝CvSparseMat* cvCloneSparseMat( const CvSparseMat* mat );
- mat
- 输入数组。
获取元素和数组子集
GetSubRect
返回输入的图像或矩阵的矩形数组子集的矩阵头CvMat* cvGetSubRect( const CvArr* arr, CvMat* submat, CvRect rect );
- arr
- 输入数组。
- submat
- 指向矩形数组子集矩阵头的指针。
- rect
- 以0坐标为基准的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行提取一行。
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开始。
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是主对角线下对角线,以此类推。
GetSize
返回矩阵或图像ROI的大小CvSize cvGetSize( const CvArr* arr );
- arr
- 数组头。
InitSparseMatIterator
初始化稀疏数组元素迭代器CvSparseNode* cvInitSparseMatIterator( const CvSparseMat* mat, CvSparseMatIterator* mat_iterator );
- mat
- 输入的数组.
- mat_iterator
- 被初始化的迭代器.
GetNextSparseNode
初始化稀疏数组元素迭代器CvSparseNode* cvGetNextSparseNode( CvSparseMatIterator* mat_iterator );
- mat_iterator
- 稀疏数组的迭代器
利用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( "%gn", val ); sum += val; printf( "nTotal sum = %gn", sum );
GetElemType
返回数组元素类型int cvGetElemType( const CvArr* arr );
- arr
- 输入数组.
- 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意味着宽。
// 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: 提供了一个例子)
函数也可以用于稀疏数组,并且如果被需要的节点不存在函数可以创建这个节点并设置为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
- 元素下标数组
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
- 元素下标数组
如果指定的点不存在对于稀疏数组点会返回0(不会创建新的节点)。
mGet
返回单通道浮点矩阵指定元素double cvmGet( const CvMat* mat, int row, int col );
- mat
- 输入矩阵.
- row
- 行下标,以0为基点.
- col
- 列下标,以0为基点
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
- 指派的值
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
- 指派的值
对于稀疏数组如果指定的节点不存在函数会创建该节点。
mSet
为单通道浮点矩阵的指定元素赋值。void cvmSet( CvMat* mat, int row, int col, double value );
- mat
- 矩阵.
- row
- 行下标,以0为基点.
- col
- 列下标,以0为基点.
- value
- 矩阵元素的新值
ClearND
清除指定数组元素void cvClearND( CvArr* arr, int* idx );
- arr
- 输入数组.
- idx
- 数组元素下标
拷贝和添加
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比特单通道的数组,它指定了输出数组中被改变的元素。
- arr(I)=value if mask(I)!=0
SetZero
清空数组void cvSetZero( CvArr* arr ); #define cvZero cvSetZero
- arr
- 要被清空数组.
SetIdentity
初始化带尺度的单位矩阵void cvSetIdentity( CvArr* mat, CvScalar value=cvRealScalar(1) );
- mat
- 待初始化的矩阵 (不一定是方阵)。
- value
- 赋值给对角线元素的值。
- 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 值修改输出数组
例如, 接下来的代码创建一个图像缓存、两个图像头,第一个是 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 是不被使用的
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
- 输出数组,图像或矩阵
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-轴翻转.见下面的公式
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
- 目标通道
Merge
从几个单通道数组组合成多通道数组或插入一个单通道数组void cvMerge( const CvArr* src0, const CvArr* src1, const CvArr* src2, const CvArr* src3, CvArr* dst ); #define cvCvtPlaneToPix cvMerge
- src0... src3
- 输入的通道.
- dst
- 输出数组.
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
- 相关的参数,用来刻划交换操作的密度.请看下面的说明.
算术,逻辑和比较
LUT
利用查找表转换数组void cvLUT( const CvArr* src, CvArr* dst, const CvArr* lut );
- src
- 元素为8位的原数组。
- dst
- 与原数组有相同通道数的输出数组,深度不确定
- lut
- 有256个元素的查找表;必须要与原输出数组有相同像深 。
- dst(I)=lut[src(I)+DELTA]
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
- 该加数被加到输入数组元素按比例缩放后得到的元素上
多通道的数组对各个通道是独立处理的。
类型转换主要用舍入和溢出截断来完成。也就是如果缩放+转换后的结果值不能用输出数组元素类型值精确表达,就设置成在输出数组数据轴上最接近该数的值。
如果 scale=1, shift=0 且输入数组和输出数组类型相同,则不会进行比例缩放,相当于该函数的同义函数:cvConvert。 如果 scale=1, shift=0 且输入数组和输出数组类型不同,则cvConvertScale会根据两种类型自动调整scale和shift,使得输入数组类型区间中的任意值能够映射到输出数组的类型区间上。
ConvertScaleAbs
使用线性变换转换输入数组元素成8位无符号整型void cvConvertScaleAbs( const CvArr* src, CvArr* dst, double scale=1, double shift=0 ); #define cvCvtScaleAbs cvConvertScaleAbs
- src
- 原数组
- dst
- 输出数组 (深度为 8u).
- scale
- 比例因子.
- shift
- 原数组元素按比例缩放后添加的值。
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单通道数组; 只有复盖面指定的输出数组被修改。
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单通道数组) ; 只有复盖面指定的输出数组被修改
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
- 添加的常数项。
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 单通道数组); 只有复盖面指定的输出数组被修改
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 单通道数组); 只有复盖面指定的输出数组被修改
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 单通道数组); 只有复盖面指定的输出数组被修改
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
- 设置的比例因子
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
- 设置的比例因子
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 单通道数组); 只有复盖面指定的输出数组被修改
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 单通道数组); 只有复盖面指定的输出数组被修改
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 单通道数组); 只有复盖面指定的输出数组被修改
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 单通道数组); 只有复盖面指定的输出数组被修改
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 单通道数组); 只有复盖面指定的输出数组被修改
- dst(I)=src1(I)
src2(I) if mask(I)!=0
XorS
计算数组元素与数量之间的按位异或void cvXorS( const CvArr* src, CvScalar value, CvArr* dst, const CvArr* mask=NULL );
- src
- 原数组
- value
- 操作中用到的数量
- dst
- 输出数组.
- mask
- 操作复盖面( 8-bit 单通道数组); 只有复盖面指定的输出数组被修改。
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
比较两个数组元素Pvoid 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)
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
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 类型.
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 类型.
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
- 输出数组
dst(I)=max(src1(I), src2(I))
所有的数组必须的一个单通道,相同的数据类型和相同的大小(或ROI大小)
MaxS
查找数组元素与数量之间的较大值void cvMaxS( const CvArr* src, double value, CvArr* dst );
- src
- 第一个原数组.
- value
- 数量值.
- dst
- 输出数组
dst(I)=max(src(I), value)
所有数组必须有一个单一通道,相同的数据类型相同的大小(或ROI大小)
Min
查找两个数组元素之间 的较小值void cvMin( const CvArr* src1, const CvArr* src2, CvArr* dst );
- src1
- 第一个原数组
- src2
- 第二个原数组.
- dst
- 输出数组.
dst(I)=min(src1(I),src2(I))
所有数组必须有一个单一通道,相同的数据类型相同的大小(或ROI大小)
MinS
查找数组元素和数量之间的较小值void cvMinS( const CvArr* src, double value, CvArr* dst );
- src
- 第一个原数组
- value
- 数量值.
- dst
- 输出数组..
dst(I)=min(src(I), value)
所有数组必须有一个单一通道,相同的数据类型相同的大小(或ROI大小)
AbsDiff
计算两个数组差的绝对值void cvAbsDiff( const CvArr* src1, const CvArr* src2, CvArr* dst );
- src1
- 第一个原数组
- src2
- 第二个原数组
- dst
- 输出数组
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
- 数量.
dst(I)c = abs(src(I)c - valuec).
所有数组必须有相同的数据类型相同的大小(或ROI大小)
统计
CountNonZero
计算非零数组元素个数int cvCountNonZero( const CvArr* arr );
- arr
- 数组, 必须是单通道数组或者设置COI(感兴趣通道)的多通道图像。
result = sumI arr(I)!=0
当IplImage 支持ROI和COI。
Sum
计算数组元素的和CvScalar cvSum( const CvArr* arr );
- arr
- 数组.
Sc = sumI arr(I)c
如果数组是IplImage类型和设置了COI, 该函数只处理选定的通道并将和存储到第一个标量成员 (S0)。 常见论坛讨论贴 cvSum的结果分析
Avg
计算数组元素的平均值CvScalar cvAvg( const CvArr* arr, const CvArr* mask=NULL );
- arr
- 数组.
- mask
- 可选操作掩模
AvgSdv
计算数组元素的平均值和标准差void cvAvgSdv( const CvArr* arr, CvScalar* mean, CvScalar* std_dev, const CvArr* mask=NULL );
- arr
- 数组
- mean
- 指向平均值的指针, 如果不需要的话可以为空( NULL)。
- std_dev
- 指向标准差的指针。
- mask
- 可选操作掩模。
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
- 选择一个子数组的操作掩模。
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
- 可选操作掩模。
- 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
- 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
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_SUM和CV_REDUCE_AVG方式来说,输入和输出的位数定义有如下关系
输入:CV_8U 输出:CV_32S CV_32F
输入:CV_16U 输出:CV_32F CV_64F
输入:CV_16S 输出:CV_32F CV_64F
输入:CV_32F 输出: CV_32F CV_64F
输入:CV_64F 输出: CV_64F
而对于CV_REDUCE_MAX和CV_REDUCE_MIN方式来说,输入和输出的位数必须一致
线性代数
DotProduct
用欧几里得准则计算两个数组的点积double cvDotProduct( const CvArr* src1, const CvArr* src2 );
- src1
- 第一输入数组。
- src2
- 第二输入数组。
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
- 输出向量
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
- 输出数组
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
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
- 可选偏移向量
- dst(I)=transmat*src(I) + shiftvec
- dst(I)k=sumj(transmat(k,j)*src(I)j) + shiftvec(k)
输入数组和输出数组应该有相同的位深(depth)和同样的大小或者 ROI 大小。 transmat 和 shiftvec 应该是实数浮点矩阵。
该函数可以用来进行 ND 点集的几何变换,任意的线性颜色空间变换,通道转换等。
PerspectiveTransform
向量数组的透视变换void cvPerspectiveTransform( const CvArr* src, CvArr* dst, const CvMat* mat );
- src
- 输入的三通道浮点数组
- dst
- 输出三通道浮点数组
- mat
- 4 × 4 变换矩阵
- (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)
MulTransposed
计算数组和数组的转置的乘积void cvMulTransposed( const CvArr* src, CvArr* dst, int order, const CvArr* delta=NULL );
- src
- 输入矩阵
- dst
- 目标矩阵
- order
- 乘法顺序
- delta
- 一个可选数组, 在乘法之前从 src 中减去该数组。
函数求值公式:
如果 order=0
- dst=(src-delta)*(src-delta)T
- dst=(src-delta)T*(src-delta)
Trace
返回矩阵的迹CvScalar cvTrace( const CvArr* mat );
- mat
- 输入矩阵
-
tr(src) = ∑ mat(i,i) i
Transpose
矩阵的转置void cvTranspose( const CvArr* src, CvArr* dst ); #define cvT cvTranspose
- src
- 输入矩阵
- dst
- 目标矩阵
- dst(i,j)=src(j,i)
Det
返回矩阵的行列式值double cvDet( const CvArr* mat );
- mat
- 输入矩阵
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 方法
如果是 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
- 输入矩阵
- src2
- 线性系统的右部
- dst
- 输出解答
- method
- 解决方法(矩阵求逆) :
- CV_LU - 最佳主元选取的高斯消除法
- CV_SVD - 奇异值分解法 (SVD)
- CV_SVD_SYM - 对正定对称矩阵的 SVD 方法
SVD
对实数浮点矩阵进行奇异值分解void cvSVD( CvArr* A, CvArr* W, CvArr* U=NULL, CvArr* V=NULL, int flags=0 );
- A
- M×N 的输入矩阵
- W
- 结果奇异值矩阵 (M×N 或者 N×N) 或者 向量 (N×1).
- U
- 可选的左部正交矩阵 (M×M or M×N). 如果 CV_SVD_U_T 被指定, 应该交换上面所说的行与列的数目。
- V
- 可选右部正交矩阵(N×N)
- flags
- 操作标志; 可以是 0 或者下面的值的组合:
- CV_SVD_MODIFY_A 通过操作可以修改矩阵 src1 。这样处理速度会比较快。
- CV_SVD_U_T 意味着会返回转置矩阵 U ,指定这个标志将加快处理速度。
- CV_SVD_V_T 意味着会返回转置矩阵 V ,指定这个标志将加快处理速度。
这里 W 是一个奇异值的对角线矩阵,它可以被编码成奇异值的一维向量,U 和 V 也是一样。 所有的奇异值都是非负的并按降序存储。(U 和 V 也相应的存储)。
SVD 算法在数值处理上已经很稳定,它的典型应用包括:
- 当 A 是一个方阵、对称阵和正矩阵时精确的求解特征值问题,例如, 当 A 时一个协方差矩阵时。在这种情况下 W 将是一个特征值的的向量,并且 U=V是矩阵的特征向量(因此,当需要计算特征向量时 U 和 V 只需要计算其中一个就可以了) 。
- 精确的求解病态线性系统。
- 超定线性系统的最小二乘求解。上一个问题和这个问题都可以用指定 CV_SVD 的 cvSolve 方法。
- 精确计算矩阵的不同特征,如秩(非零奇异值的数目), 条件数(最大奇异值和最小奇异值的比例), 行列式值(行列式的绝对值等于奇异值的乘积).上述的所有这些值都不要求计算矩阵 U 和 V 。
SVBkSb
奇异值回代算法(back substitution)void cvSVBkSb( const CvArr* W, const CvArr* U, const CvArr* V, const CvArr* B, CvArr* X, int flags );
- W
- 奇异值矩阵或者向量
- U
- 左正交矩阵 (可能是转置的)
- V
- 右正交矩阵 (可能是转置的)
- B
- 原始矩阵 A 的伪逆的乘法矩阵。这个是可选参数。如果它被省略则假定它是一个适当大小的单位矩阵(因此 x 将是 A 的伪逆的重建).。
- X
- 目标矩阵: 奇异值回代算法的结果
- flags
- 操作标志, 和刚刚讨论的 cvSVD 的标志一样。
- X=V*W-1*UT*B
- W-1(i,i)=1/W(i,i) 如果 W(i,i) > epsilon•sumiW(i,i),
- 否则:0.
EigenVV
计算对称矩阵的特征值和特征向量void cvEigenVV( CvArr* mat, CvArr* evects, CvArr* evals, double eps=0 );
- mat
- 输入对称方阵。在处理过程中将被改变。
- evects
- 特征向量输出矩阵, 连续按行存储
- evals
- 特征值输出矩阵,按降序存储(当然特征值和特征向量的排序是同步的)。
- eps
- 对角化的精确度 (典型地, DBL_EPSILON=≈10-15 就足够了)。
mat*evects(i,:)' = evals(i)*evects(i,:)' (在 MATLAB 的记法)
矩阵 A 的数据将会被这个函数修改。
目前这个函数比函数 cvSVD 要慢,精确度要低, 如果已知 A 是正定的,(例如, 它是一个协方差矩阵), 它通常被交给函数 cvSVD 来计算其特征值和特征向量,尤其是在不需要计算特征向量的情况下
CalcCovarMatrix
计算向量集合的协方差矩阵void cvCalcCovarMatrix( const CvArr** vects, int count, CvArr* cov_mat, CvArr* avg, int flags );
- vects
- 输入向量。他们必须有同样的数据类型和大小。这个向量不一定非是一维的,他们也可以是二维(例如,图像)等等。
- count
- 输入向量的数目
- cov_mat
- 输出协方差矩阵,它是浮点型的方阵。
- avg
- 输入或者输出数组 (依赖于标记“flags”) - 输入向量的平均向量。
- flags
- 操作标志,下面值的组合:
- CV_COVAR_SCRAMBLED - 输出协方差矩阵按下面计算:
- scale * [vects[0] − avg,vects[1] − avg,...]T * [vects[0] − avg,vects[1] − avg,...], 即协方差矩阵是 count×count. 这样一个不寻常的矩阵用于一组大型向量的快速PCA方法(例如, 人脸识别的 EigenFaces 技术)。这个混杂("scrambled")矩阵的特征值将和真正的协方差矩阵的特征值匹配,真正的特征向量可以很容易的从混杂("scrambled")协方差矩阵的特征向量中计算出来。
- CV_COVAR_NORMAL - 输出协方差矩阵被计算成:
- scale * [vects[0] − avg,vects[1] − avg,...] * [vects[0] − avg,vects[1] − avg,...]T, 也就是说, cov_mat 将是一个和每一个输入向量的元素数目具有同样线性大小的通常协方差矩阵。 CV_COVAR_SCRAMBLED 和 CV_COVAR_NORMAL 只能同时指定其中一个。
- CV_COVAR_USE_AVG - 如果这个标志被指定, 该函数将不会从输入向量中计算 avg ,而是用过去的 avg 向量,如果 avg 已经以某种方式计算出来了这样做是很有用的。或者如果协方差矩阵是部分计算出来的 - 倘若这样, avg 不是输入向量的子集的平均值,而是整个集合的平均向量。
- CV_COVAR_SCALE - 如果这个标志被指定,协方差矩阵被缩放了。 the covariation matrix is scaled.在 "normal" 模式下缩放比例是 1./count, 在 "scrambled" 模式下缩放比例是每一个输入向量的元素总和的倒数。 缺省地(如果没有指定标志) 协方差矩阵不被缩放 (scale=1)。
- CV_COVAR_SCRAMBLED - 输出协方差矩阵按下面计算:
Mahalanobis
计算两个向量之间的马氏距离(Mahalanobis distance)double cvMahalanobis( const CvArr* vec1, const CvArr* vec2, CvArr* mat );
- vec1
- 第一个一维输入向量
- vec2
- 第二个一维输入向量
- mat
- 协方差矩阵的逆矩阵
CalcPCA
对一个向量集做PCA变换void cvCalcPCA( const CvArr* data, CvArr* avg, CvArr* eigenvalues, CvArr* eigenvectors, int flags );
- data
- 输入数据,每个向量是单行向量(CV_PCA_DATA_AS_ROW)或者单列向量(CV_PCA_DATA_AS_COL).
- avg
- 平均向量,在函数内部计算或者由调用者提供
- eigenvalues
- 输出的协方差矩阵的特征值
- eigenvectors
- 输出的协方差矩阵的特征向量(也就是主分量),每个向量一行
- flags
- 操作标志,可以是以下几种方式的组合:
- CV_PCA_DATA_AS_ROW - 向量以行的方式存放(也就是说任何一个向量都是连续存放的)
- CV_PCA_DATA_AS_COL - 向量以列的方式存放(也就是说某一个向量成分的数值是连续存放的)
- (上面两种标志是互相排斥的)
- CV_PCA_USE_AVG - 使用预先计算好的平均值
ProjectPCA
把向量向某个子空间投影void cvProjectPCA( const CvArr* data, const CvArr* avg, const CvArr* eigenvectors, CvArr* result )
- data
- 输入数据,每个向量可以是单行或者单列
- avg
- 平均向量.要么它是单行向量那么意味着输入数据以行数据的形式存放,要么就是单列向量,那么就意味着那么输入向量就是以列的方式存放.
- eigenvectors
- 特征向量(主分量),每个向量一行.
- result
- 输出的分解系数矩阵,矩阵的行数必须与输入向量的个数相等,矩阵的列数必须小于特征向量的行数.
result(i,:)=(data(i,:)-avg)*eigenvectors' // for CV_PCA_DATA_AS_ROW layout.
BackProjectPCA
根据投影系数重构原来的向量void cvBackProjectPCA( const CvArr* proj, const CvArr* avg, const CvArr* eigenvects, CvArr* result );
- proj
- 输入数据,与cvProjectPCA里面的格式一致
- avg
- 平均向量.如果它是单行向量,那么意味着输出向量是以行的方式存放.否则就是单列向量,那么输出向量就是以列的方式存放.
- eigenvectors
- 特征向量(主分量),每个向量一行.
- result
- 输出的重构出来的矩阵
result(i,:)=proj(i,:)*eigenvectors + avg // for CV_PCA_DATA_AS_ROW layout.
数学函数
Round, Floor, Ceil
转换浮点数为整数int cvRound( double value ); int cvFloor( double value ); int cvCeil( double value );
- value
- 输入浮点值
Sqrt
计算平方根float cvSqrt( float value );
- value
- 输入浮点值
InvSqrt
计算平方根的倒数float cvInvSqrt( float value );
- value
- 输入浮点值
Cbrt
计算立方根float cvCbrt( float value );
- value
- 输入浮点值
FastArctan
计算二维向量的角度float cvFastArctan( float y, float x );
- x
- 二维向量的 x 坐标
- y
- 二维向量的 y 坐标
IsNaN
判断输入是否是一个数字int cvIsNaN( double value );
- value
- 输入浮点值
IsInf
判断输入是否是无穷大int cvIsInf( double value );
- value
- 输入浮点值
CartToPolar
计算二维向量的长度和/或者角度void cvCartToPolar( const CvArr* x, const CvArr* y, CvArr* magnitude, CvArr* angle=NULL, int angle_in_degrees=0 );
- x
- x 坐标数组
- y
- y 坐标数组
- magnitude
- 存储向量长度输出数组, 如果不是必要的它可以为空(NULL)
- angle
- 存储角度输出数组, 如果不是必要的它可以为空(NULL)。它可以被标准化为弧度 (0..2π) 或者度数(0..360°)
- angle_in_degrees
- 指示角度是用弧度或者度数表示的标志,缺省模式为弧度
magnitude(I) = sqrt(x(I)2 + y(I)2), angle(I) = atan(y(I) / x(I))
角度的精确度 ≈0.1°. (0,0) 点的角度被设置为 0.
(建议:英文文档虽然是写成atan( y(I)/x(I) ),但是建议和C中的表达方式统一。atan不能识别在那个象限,只能返回0-180°,atan2(x,y)才能返回0-360°的值)
PolarToCart
计算极坐标形式的二维向量对应的直角坐标void cvPolarToCart( const CvArr* magnitude, const CvArr* angle, CvArr* x, CvArr* y, int angle_in_degrees=0 );
- magnitude
- 长度数组.如果为空(NULL),长度被假定为全是 1's.
- angle
- 角度数组,弧度或者角度表示.
- x
- 输出 x 坐标数组, 如果不需要,可以为空(NULL).
- y
- 输出 y 坐标数组, 如果不需要,可以为空(NULL).
- angle_in_degrees
- 指示角度是用弧度或者度数表示的标志,缺省模式为弧度
x(I)=magnitude(I)*cos(angle(I)), y(I)=magnitude(I)*sin(angle(I))
Pow
对数组内每个元素求幂void cvPow( const CvArr* src, CvArr* dst, double power );
- src
- 输入数组
- dst
- 输出数组, 应该和输入数组有相同的类型
- power
- 幂指数
dst(I)=src(I)^p, 如果p是整数 否则dst(I)=abs(src(I))^p
也就是说,对于非整型的幂指数使用输入数组元素的绝对值进行计算。然而,使用一些额外的操作,负值也可以得到正确的结果,象下面的例子,计算数组元素的立方根:
CvSize size = cvGetSize(src); CvMat* mask = cvCreateMat( size.height, size.width, CV_8UC1 ); cvCmpS( src, 0, mask, CV_CMP_LT ); /* 查找负数 */ cvPow( src, dst, 1./3 ); cvSubRS( dst, cvScalarAll(0), dst, mask ); /* 输入的负值的结果求反 */ cvReleaseMat( &mask );
对于一些幂值, 例如整数值, 0.5 和 -0.5, 优化算法被使用。
Exp
计算数组元素的指数幂void cvExp( const CvArr* src, CvArr* dst );
- src
- 输入数组
- dst
- 输出数组, 它应该是 double 型的或者和输入数组有相同的类型
dst(I)=exp(src(I))
最大相对误差为 ≈7e-6. 通常, 该函数转换无法输出的值为 0 输出。
Log
计算每个数组元素的绝对值的自然对数void cvLog( const CvArr* src, CvArr* dst );
- src
- 输入数组。
- dst
- 输出数组,它应该是 double 型的或者和输入数组有相同的类型。
dst(I)=log(abs(src(I))), src(I)!=0 dst(I)=C, src(I)=0
这里 C 是一个大负数 (≈-700 现在的实现中)。
SolveCubic
求解曲线函数的实根void cvSolveCubic( const CvArr* coeffs, CvArr* roots );
- coeffs
- 等式系数, 一个三到四个元素的数组.
- roots
- 输出的矩阵等式的实根。它应该具有三个元素.
- coeffs[0]*x^3 + coeffs[1]*x^2 + coeffs[2]*x + coeffs[3] = 0
- (如果coeffs是四元素的矢量)
- x^3 + coeffs[0]*x^2 + coeffs[1]*x + coeffs[2] = 0
- (如果coeffs是三元素的矢量)
随机数生成
RNG
初始化随机数生成器状态CvRNG cvRNG( int64 seed=-1 );
- seed
- 64-bit 的值用来初始化一个随机序列
RandArr
用随机数填充数组并更新 RNG 状态void cvRandArr( CvRNG* rng, CvArr* arr, int dist_type, CvScalar param1, CvScalar param2 );
- rng
- 被 cvRNG 初始化的 RNG 状态.
- arr
- 输出数组
- dist_type
- 分布类型:
- CV_RAND_UNI - 均匀分布
- CV_RAND_NORMAL - 正态分布 或者 高斯分布
- param1
- 分布的第一个参数。如果是均匀分布它是随机数范围的闭下边界。如果是正态分布它是随机数的平均值。
- param2
- 分布的第二个参数。如果是均匀分布它是随机数范围的开上边界。如果是正态分布它是随机数的标准差。
/* let's noisy_screen be the floating-point 2d array that is to be "crapped" */ CvRNG rng_state = cvRNG(0xffffffff); int i, pointCount = 1000; /* allocate the array of coordinates of points */ CvMat* locations = cvCreateMat( pointCount, 1, CV_32SC2 ); /* arr of random point values */ CvMat* values = cvCreateMat( pointCount, 1, CV_32FC1 ); CvSize size = cvGetSize( noisy_screen ); cvRandInit( &rng_state, 0, 1, /* 现在使用虚参数以后再调整 */ 0xffffffff /*这里使用一个确定的种子 */, CV_RAND_UNI /* 指定为均匀分布类型 */ ); /* 初始化 locations */ cvRandArr( &rng_state, locations, CV_RAND_UNI, cvScalar(0,0,0,0), cvScalar(size.width,size.height,0,0) ); /* modify RNG to make it produce normally distributed values */ rng_state.disttype = CV_RAND_NORMAL; cvRandSetRange( &rng_state, 30 /* deviation */, 100 /* average point brightness */, -1 /* initialize all the dimensions */ ); /* generate values */ cvRandArr( &rng_state, values, CV_RAND_NORMAL, cvRealScalar(100), // average intensity cvRealScalar(30) // deviation of the intensity ); /* set the points */ for( i = 0; i < pointCount; i++ ) { CvPoint pt = *(CvPoint*)cvPtr1D( locations, i, 0 ); float value = *(float*)cvPtr1D( values, i, 0 ); *((float*)cvPtr2D( noisy_screen, pt.y, pt.x, 0 )) += value; } /* not to forget to release the temporary arrays */ cvReleaseMat( &locations ); cvReleaseMat( &values ); /* RNG state does not need to be deallocated */
RandInt
返回 32-bit 无符号整型并更新 RNGunsigned cvRandInt( CvRNG* rng );
- rng
- 被 cvRNG 初始化的 RNG 状态,被 RandSetRange (虽然, 后面这个函数对我们正讨论的函数的结果没有什么影响)随意地设置。
该函数用来产生一个标量随机数,例如点, patch sizes, table indices 等,用模操作可以产生一个确定边界的整数,人和其他特定的边界缩放到 0.. 1可以产生一个浮点数。下面是用 cvRandInt 重写的前一个函数讨论的例子:
/* the input and the task is the same as in the previous sample. */ CvRNG rng_state = cvRNG(0xffffffff); int i, pointCount = 1000; /* ... - no arrays are allocated here */ CvSize size = cvGetSize( noisy_screen ); /* make a buffer for normally distributed numbers to reduce call overhead */ #define bufferSize 16 float normalValueBuffer[bufferSize]; CvMat normalValueMat = cvMat( bufferSize, 1, CV_32F, normalValueBuffer ); int valuesLeft = 0; for( i = 0; i < pointCount; i++ ) { CvPoint pt; /* generate random point */ pt.x = cvRandInt( &rng_state ) % size.width; pt.y = cvRandInt( &rng_state ) % size.height; if( valuesLeft <= 0 ) { /* fulfill the buffer with normally distributed numbers if the buffer is empty */ cvRandArr( &rng_state, &normalValueMat, CV_RAND_NORMAL, cvRealScalar(100), cvRealScalar(30) ); valuesLeft = bufferSize; } ((float*)cvPtr2D( noisy_screen, pt.y, pt.x, 0 ) = normalValueBuffer[--valuesLeft]; } /* there is no need to deallocate normalValueMat because we have both the matrix header and the data on stack. It is a common and efficient practice of working with small, fixed-size matrices */
RandReal
返回浮点型随机数并更新 RNGdouble cvRandReal( CvRNG* rng );
- rng
- 被 cvRNG 初始化的 RNG 状态
离散变换
DFT
执行一维或者二维浮点数组的离散傅立叶正变换或者离散傅立叶逆变换#define CV_DXT_FORWARD 0 #define CV_DXT_INVERSE 1 #define CV_DXT_SCALE:2 #define CV_DXT_ROWS: 4 #define CV_DXT_INV_SCALE (CV_DXT_SCALE|CV_DXT_INVERSE) #define CV_DXT_INVERSE_SCALE CV_DXT_INV_SCALE void cvDFT( const CvArr* src, CvArr* dst, int flags, int nonzero_rows=0);
- src
- 输入数组, 实数或者复数.
- dst
- 输出数组,和输入数组有相同的类型和大小。
- flags
- 变换标志, 下面的值的组合:
- CV_DXT_FORWARD - 正向 1D 或者 2D 变换. 结果不被缩放.
- CV_DXT_INVERSE - 逆向 1D 或者 2D 变换. 结果不被缩放.当然 CV_DXT_FORWARD 和 CV_DXT_INVERSE 是互斥的.
- CV_DXT_SCALE - 对结果进行缩放: 用数组元素数除以它. 通常, 它和 CV_DXT_INVERSE 组合在一起,可以使用缩写 CV_DXT_INV_SCALE.
- CV_DXT_ROWS - 输入矩阵的每个独立的行进行整型或者逆向变换。这个标志允许用户同时变换多个向量,减少开销(它往往比处理它自己要快好几倍), 进行 3D 和高维的变换等等。
- nonzero_rows
- 输入矩阵中非0行的个数(在2维的Forward变换中),或者是输出矩阵中感兴趣的行(在反向的2维变换中)。如果这个值是负数,0,或者大于总行数的一个值,它将会被忽略。这个参数可以用来加速2维DFT/IDFT的速度。见下面的例子。
- N 元一维向量的正向傅立叶变换:
- y = F(N)•x, 这里 F(N)jk=exp(-i•2Pi•j•k/N), i=sqrt(-1)
- N 元一维向量的逆向傅立叶变换:
- x'= (F(N))-1•y = conj(F(N))•y
- x = (1/N)•x
- M×N 元二维向量的正向傅立叶变换:
- Y = F(M)•X•F(N)
- M×N 元二维向量的逆向傅立叶变换:
- X'= conj(F(M))•Y•conj(F(N))
- X = (1/(M•N))•X'
Re Y0,0: Re Y0,1:Im Y0,1:Re Y0,2: Im Y0,2 ... Re Y0,N/2-1 Im Y0,N/2-1 Re Y0,N/2 Re Y1,0: Re Y1,1:Im Y1,1:Re Y1,2: Im Y1,2 ... Re Y1,N/2-1 Im Y1,N/2-1 Re Y1,N/2 Im Y1,0: Re Y2,1:Im Y2,1:Re Y2,2: Im Y2,2 ... Re Y2,N/2-1 Im Y2,N/2-1 Im Y2,N/2 ............................................................................................ Re YM/2-1,0 Re YM-3,1 Im YM-3,1 Re YM-3,2 Im YM-3,2 ... Re YM-3,N/2-1 Im YM-3,N/2-1 Re YM-3,N/2 Im YM/2-1,0 Re YM-2,1 Im YM-2,1 Re YM-2,2 Im YM-2,2 ... Re YM-2,N/2-1 Im YM-2,N/2-1 Im YM-2,N/2 Re YM/2,0:Re YM-1,1 Im YM-1,1 Re YM-1,2 Im YM-1,2 ... Re YM-1,N/2-1 Im YM-1,N/2-1 Im YM-1,N/2
注意:如果 N 时偶数最后一列存在(is present), 如果 M 时偶数最后一行(is present).
如果是一维实数的变换结果就像上面矩阵的第一行的形式。 利用DFT求解二维卷积
CvMat* A = cvCreateMat( M1, N1, CV_32F ); CvMat* B = cvCreateMat( M2, N2, A->type ); // it is also possible to have only abs(M2-M1)+1×abs(N2-N1)+1 // part of the full convolution result CvMat* conv = cvCreateMat( A->rows + B->rows - 1, A->cols + B->cols - 1, A->type ); // initialize A and B ... int dft_M = cvGetOptimalDFTSize( A->rows + B->rows - 1 ); int dft_N = cvGetOptimalDFTSize( A->cols + B->cols - 1 ); CvMat* dft_A = cvCreateMat( dft_M, dft_N, A->type ); CvMat* dft_B = cvCreateMat( dft_M, dft_N, B->type ); CvMat tmp; // copy A to dft_A and pad dft_A with zeros cvGetSubRect( dft_A, &tmp, cvRect(0,0,A->cols,A->rows)); cvCopy( A, &tmp ); cvGetSubRect( dft_A, &tmp, cvRect(A->cols,0,dft_A->cols - A->cols,A->rows)); cvZero( &tmp ); // no need to pad bottom part of dft_A with zeros because of // use nonzero_rows parameter in cvDFT() call below cvDFT( dft_A, dft_A, CV_DXT_FORWARD, A->rows ); // repeat the same with the second array cvGetSubRect( dft_B, &tmp, cvRect(0,0,B->cols,B->rows)); cvCopy( B, &tmp ); cvGetSubRect( dft_B, &tmp, cvRect(B->cols,0,dft_B->cols - B->cols,B->rows)); cvZero( &tmp ); // no need to pad bottom part of dft_B with zeros because of // use nonzero_rows parameter in cvDFT() call below cvDFT( dft_B, dft_B, CV_DXT_FORWBRD, B->rows ); cvMulSpectrums( dft_A, dft_B, dft_A, 0 /* or CV_DXT_MUL_CONJ to get correlation ::::::::::: rather than convolution */ ); cvDFT( dft_A, dft_A, CV_DXT_INV_SCALE, conv->rows ); // calculate only the top part cvGetSubRect( dft_A, &tmp, cvRect(0,0,conv->cols,conv->rows) ); cvCopy( &tmp, conv );
GetOptimalDFTSize
对于给定的矢量尺寸返回最优DFT尺寸int cvGetOptimalDFTSize( int size0 );
- size0
- 矢量长度.
The function returns a negative number if size0 is too large (very close to INT_MAX)
MulSpectrums
两个傅立叶频谱的每个元素的乘法(Performs per-element multiplication of two Fourier spectrums)void cvMulSpectrums( const CvArr* src1, const CvArr* src2, CvArr* dst, int flags );
- src1
- 第一输入数组
- src2
- 第二输入数组
- dst
- 输出数组,和输入数组有相同的类型和大小。
- flags
- 下面列举的值的组合:
- CV_DXT_ROWS - 把数组的每一行视为一个单独的频谱 (参见 cvDFT 的参数讨论).
- CV_DXT_MUL_CONJ - 在做乘法之前取第二个输入数组的共轭.
该函数和 cvDFT 可以用来快速计算两个数组的卷积.
DCT
执行一维或者二维浮点数组的离散馀弦变换或者离散反馀弦变换#define CV_DXT_FORWARD 0 #define CV_DXT_INVERSE 1 #define CV_DXT_ROWS: 4 void cvDCT( const CvArr* src, CvArr* dst, int flags );
- src
- 输入数组, 1D 或者 2D 实数数组.
- dst
- 输出数组,和输入数组有相同的类型和大小。
- flags
- 变换标志符, 下面值的组合:
- CV_DXT_FORWARD - 1D 或者 2D 馀弦变换.
- CV_DXT_INVERSE - 1D or 2D 反馀弦变换.
- CV_DXT_ROWS - 对输入矩阵的每个独立的行进行馀弦或者反馀弦变换. 这个标志允许用户同时进行多个向量的变换,可以用来减少开销(它往往比处理它自己要快好几倍),以及 3D 和高维变换等等。
- N 元一维向量的馀弦变换:
- y = C(N)•x, 这里 C(N)jk=sqrt((j==0?1:2)/N)•cos(Pi•(2k+1)•j/N)
- N 元一维向量的反馀弦变换:
- x = (C(N))-1•y = (C(N))T•y
- M×N 元二维向量的馀弦变换:
- Y = (C(M))•X•(C(N))T
- M×N 元二维向量的反馀弦变换:
- X = (C(M))T•Y•C(N)
收藏的用户(0) X
正在加载信息~
推荐阅读
最新回复 (0)
站点信息
- 文章2300
- 用户1336
- 访客10858883
每日一句
Challenges spark life; conquering them gives purpose.
挑战点亮生活,征服赋予意义。
挑战点亮生活,征服赋予意义。
语法错误: 意外的令牌“标识符”
全面理解Gradle - 定义Task
Motrix全能下载工具 (支持 BT / 磁力链 / 百度网盘)
谷歌Pixel正在开始起飞?
获取ElementUI Table排序后的数据
Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is
亲测!虚拟机VirtualBox安装MAC OS 10.12图文教程
华为手机app闪退重启界面清空log日志问题
android ndk开发之asm/page.h: not found
手机屏幕碎了怎么备份操作?
免ROOT实现模拟点击任意位置
新手必看修改DSDT教程
thinkpad t470p装黑苹果系统10.13.2
新会员