• Open Source Computer Vision Library

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 宏)

调用cvCreateImageHeader创建的图像,需要调用cvReleaseImageHeader释放图像头,然后将原始图像数据单独删除。

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明确的分配数据. 当这个矩阵不需要时,仍需要调用cvReleaseMat函数释放矩阵头内存单元.

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函数对于多通道平面编排图像可以处理每个平面。

   返回的 CvMat * 结构指向输入的header。 By Jackyzzy 赵振阳

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。 如果 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
原数组元素按比例缩放后添加的值。

函数 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)\oplussrc2(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)\oplusvalue 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)。 常见论坛讨论贴 cvSum的结果分析

Avg

计算数组元素的平均值

CvScalar cvAvg( const CvArr* arr, const CvArr* mask=NULL );
arr
数组.
mask
可选操作掩模

函数 cvAvg 独立地为每一个通道计算数组元素的平均值 M :

N = \sum_i (\mbox{mask}(i) \neq 0)
M_c = \frac{1}{N} \sum_{i,\mbox{mask}(i) \neq 0} \mbox{arr}(i)_c

如果数组是 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 独立地为每一个通道计算数组元素的平均值和标准差:

N = \sum_i (mask(i) \neq 0)
\mbox{mean}_c = \frac{1}{N} \sum_{i,\mbox{mask}(i) \neq 0} \mbox{arr}(i)_c
\mbox{std-dev}_c = \sqrt{ \frac{1}{N} \sum_{i,\mbox{mask}(i) \neq 0} (\mbox{arr}(i)_c - \mbox{mean}_c)^2}

如果数组是 IplImage 类型和 设置了COI ,该函数只处理选定的通道并将平均值和标准差存储到第一个输出标量成员 (mean0std-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的情况下输出可能有很大的位深度用于维持准确性,这两种方式也适合于处理多通道数组.

注意,对于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
第二输入数组。

函数 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
输入矩阵
src2
线性系统的右部
dst
输出解答
method
解决方法(矩阵求逆) :
CV_LU - 最佳主元选取的高斯消除法
CV_SVD - 奇异值分解法 (SVD)
CV_SVD_SYM - 对正定对称矩阵的 SVD 方法

函数 cvSolve 解决线性系统或者最小二乘法问题 (后者用 SVD 方法可以解决):

\mbox{dst} = \arg \min_X |\mbox{src1}\cdot X-\mbox{src2}|

如果使用 CV_LU 方法。 如果 src1 是非奇异的,该函数则返回 1 ,否则返回 0 ,在后一种情况下 dst 是无效的。

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 ,指定这个标志将加快处理速度。

函数 cvSVD 将矩阵 A 分解成一个对角线矩阵和两个正交矩阵的乘积:

\mathbf{\it A=U W V^T}

这里 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 的标志一样。

函数 cvSVBkSb 为被分解的矩阵 A 和矩阵 B 计算回代逆(back substitution) (参见 cvSVD 说明) :

X=V*W-1*UT*B

这里

W-1(i,i)=1/W(i,i) 如果 W(i,i) > epsilon•sumiW(i,i),
否则:0.

epsilon 是一个依赖于矩阵数据类型的的很小的数。该函数和 cvSVD 函数被用来执行 cvInvert 和 cvSolve, 用这些函数 (svd & bksb)的原因是初级函数(low-level) 函数可以避免高级函数 (inv & solve) 计算中内部分配的临时矩阵。

EigenVV

计算对称矩阵的特征值和特征向量

void cvEigenVV( CvArr* mat, CvArr* evects, CvArr* evals, double eps=0 );
mat
输入对称方阵。在处理过程中将被改变。
evects
特征向量输出矩阵, 连续按行存储
evals
特征值输出矩阵,按降序存储(当然特征值和特征向量的排序是同步的)。
eps
对角化的精确度 (典型地, DBL_EPSILON=≈10-15 就足够了)。

函数 cvEigenVV 计算矩阵 A 的特征值和特征向量:

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)。

函数 cvCalcCovarMatrix 计算输入向量的协方差矩阵和平均向量。该函数 可以被运用到主成分分析中(PCA),以及马氏距离(Mahalanobis distance)比较向量中等等。

Mahalanobis

计算两个向量之间的马氏距离(Mahalanobis distance)

double cvMahalanobis( const CvArr* vec1, const CvArr* vec2, CvArr* mat );
vec1
第一个一维输入向量
vec2
第二个一维输入向量
mat
协方差矩阵的逆矩阵

函数 cvMahalanobis 计算两个向量之间的加权距离,其返回结果是:

d(vec1,vec2)=\sqrt{ \sum_{i,j} \{mat(i,j)*(vec1(i)-vec2(i))*(vec1(j)-vec2(j))\} }

协方差矩阵可以用函数cvCalcCovarMatrix 计算出来,逆矩阵可以用函数 cvInvert 计算出来 (CV_SVD 方法是一个比较好的选择, 因为矩阵可能是奇异的).

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 - 使用预先计算好的平均值

该函数对某个向量集做PCA变换.它首先利用cvCalcCovarMatrix计算协方差矩阵然后计算协方差矩阵的特征值与特征向量.输出的特征值/特征向量的个数小于或者等于MIN(rows(data),cols(data)).

ProjectPCA

把向量向某个子空间投影

void cvProjectPCA( const CvArr* data, const CvArr* avg,
                  const CvArr* eigenvectors, CvArr* result )
data
输入数据,每个向量可以是单行或者单列
avg
平均向量.要么它是单行向量那么意味着输入数据以行数据的形式存放,要么就是单列向量,那么就意味着那么输入向量就是以列的方式存放.
eigenvectors
特征向量(主分量),每个向量一行.
result
输出的分解系数矩阵,矩阵的行数必须与输入向量的个数相等,矩阵的列数必须小于特征向量的行数.

该函数将输入向量向一个正交系(eigenvectors)投影.在计算点乘之前,输入向量要减去平均向量:

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
输入浮点值

函数 cvRound, cvFloor, cvCeil 用一种舍入方法将输入浮点数转换成整数。 cvRound 返回和参数最接近的整数值。 cvFloor 返回不大于参数的最大整数值。cvCeil 返回不小于参数的最小整数值。在某些体系结构中该函数 工作起来比标准 C 操作起来还要快。如果参数的绝对值大于 231 ,结果是不可预料的。对特殊值 (±Inf, NaN) 未进行处理。

Sqrt

计算平方根

float cvSqrt( float value );
value
输入浮点值

函数 cvSqrt 计算输入值的平方根。如果输入的是复数, 结果将不可预料。

InvSqrt

计算平方根的倒数

float cvInvSqrt( float value );
value
输入浮点值

函数 cvInvSqrt 计算输入值的平方根的倒数,大多数情况下它比 1./sqrt(value) 要快。 如果输入的是 0 或者复数,结果将不可预料。特别值 (±Inf, NaN) 是不可控制的。

Cbrt

计算立方根

float cvCbrt( float value );
value
输入浮点值

函数 cvCbrt 计算输入值的立方根,大多数情况下它比 pow(value,1./3) 要快。 另外, 负数也是可操作的。特别值 (±Inf, NaN) 是不可控制的。

FastArctan

计算二维向量的角度

float cvFastArctan( float y, float x );
x
二维向量的 x 坐标
y
二维向量的 y 坐标

函数 cvFastArctan 计算二维向量的全范围角度角度, 变化范围是 0°到 360°。 精确度为 ~0.1° 。

IsNaN

判断输入是否是一个数字

int cvIsNaN( double value );
value
输入浮点值

函数 cvIsNaN 发现输入是一个数字则返回 1 ( IEEE754 标准 ),否则返回 0 。

IsInf

判断输入是否是无穷大

int cvIsInf( double value );
value
输入浮点值

函数 cvIsInf 如果输入是 ±Infinity ( IEEE754 标准 )则返回 1 ,否则返回 0 .

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°)

所有的数组只支持浮点类型的运算,也即x,y,magnitude,angle必须是浮点类型的数组。

angle_in_degrees
指示角度是用弧度或者度数表示的标志,缺省模式为弧度

函数 cvCartToPolar 计算二维向量(x(I),y(I))的长度,角度,或者两者同时计算:

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
指示角度是用弧度或者度数表示的标志,缺省模式为弧度

函数 cvPolarToCart 计算每个向量magnitude(I)*exp(angle(I)*j), j=sqrt(-1)的 x 坐标,y 坐标或者两者都计算:

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
幂指数

函数 cvPow 计算输入数组的每个元素的 p 次幂:

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 型的或者和输入数组有相同的类型

函数 cvExp 计算输入数组的每个元素的 e 次幂:

dst(I)=exp(src(I))

最大相对误差为 ≈7e-6. 通常, 该函数转换无法输出的值为 0 输出。

Log

计算每个数组元素的绝对值的自然对数

void cvLog( const CvArr* src, CvArr* dst );
src
输入数组。
dst
输出数组,它应该是 double 型的或者和输入数组有相同的类型。

函数 cvLog 计算输入数组每个元素的绝对值的自然对数:

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
输出的矩阵等式的实根。它应该具有三个元素.

函数 cvSolveCubic 求解曲线函数的实根:

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是三元素的矢量)

函数返回求解得到的实根数目. 实根被存储在矩阵root中, 如果只有一个实根则用0来替代相关值.

随机数生成

RNG

初始化随机数生成器状态

CvRNG cvRNG( int64 seed=-1 );
seed
64-bit 的值用来初始化一个随机序列

函数 cvRNG 初始化随机数生成器并返回其状态。指向这个状态的指针可以传递给函数 cvRandInt, cvRandReal 和 cvRandArr . 在通常的实现中使用一个 multiply-with-carry generator 。

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
分布的第二个参数。如果是均匀分布它是随机数范围的开上边界。如果是正态分布它是随机数的标准差。

函数 cvRandArr 用均匀分布的或者正态分布的随机数填充输出数组。在下面的例子中该函数被用来添加一些正态分布的浮点数到二维数组的随机位置。

/* 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 无符号整型并更新 RNG

unsigned cvRandInt( CvRNG* rng );
rng
被 cvRNG 初始化的 RNG 状态,被 RandSetRange (虽然, 后面这个函数对我们正讨论的函数的结果没有什么影响)随意地设置。

函数 cvRandInt 返回均匀分布的随机 32-bit 无符号整型值并更新 RNG 状态。它和 C 运行库里面的 rand() 函数十分相似,但是它产生的总是一个 32-bit 数而 rand() 返回一个 0 到 RAND_MAX (它是 2**16 或者 2**32, 依赖于操作平台)之间的数。

该函数用来产生一个标量随机数,例如点, 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

返回浮点型随机数并更新 RNG

double cvRandReal( CvRNG* rng );
rng
被 cvRNG 初始化的 RNG 状态

函数 cvRandReal 返回均匀分布的随机浮点数,范围在 0..1 之间 (不包括 1 )。

离散变换

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的速度。见下面的例子。


函数 cvDFT 执行一维或者二维浮点数组的离散傅立叶正变换或者离散傅立叶逆变换:

N 元一维向量的正向傅立叶变换:
y = F(N)•x, 这里 F(N)jk=exp(-i•2Pi•j•k/N), i=sqrt(-1)

y[k] =\sum_{n=0}^{N-1}x[n]e^{-i\frac{2\pi}{N} nk}           k=0,1,...N-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'

假设时实数数据 (单通道) ,从 IPL 借鉴过来的压缩格式被用来表现一个正向傅立叶变换的结果或者逆向傅立叶变换的输入:

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
矢量长度.

函数 cvGetOptimalDFTSize 返回最小值 N that is greater to equal to size0, such that DFT of a vector of size N can be computed fast. In the current implementation N=2p×3q×5r for some p, q, r.

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 - 在做乘法之前取第二个输入数组的共轭.

函数 cvMulSpectrums 执行两个 CCS-packed 或者实数或复数傅立叶变换的结果复数矩阵的每个元素的乘法。(performs per-element multiplication of the two CCS-packed or complex matrices that are results of real or complex Fourier transform.)

该函数和 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 和高维变换等等。

函数 cvDCT 执行一维或者二维浮点数组的离散余弦变换或者离散反余弦变换:

N 元一维向量的余弦变换:
y = C(N)•x, 这里 C(N)jk=sqrt((j==0?1:2)/N)•cos(Pi•(2k+1)•j/N)
 y[m] =    \sum_{k=0}^{N-1} x_k \cos \left[\frac{\pi}{N} m \left(k+\frac{1}{2}\right) \right]
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)
Views
Personal tools