转自 http://blog.csdn.net/wangjie0377/article/details/6629293
变换和置换
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 );
...
int size[] = { 2, 2, 2 };
CvMatND* mat = cvCreateMatND( 3, size, CV_32F );
CvMat row_header, *row;
row = cvReshapeND( mat, &row_header, 0, 1, 0 );
Repeat
用原数组管道式添充输出数组
void cvRepeat( const CvArr* src, CvArr* dst );
src
输入数组, 图像或矩阵。
dst
输出数组,图像或矩阵
函数cvRepeat 使用被管道化的原数组添充输出数组:
dst(i,j)=src(i mod rows(src), j mod cols(src))
因此,输出数组可能小于也可能大于输入数组.
Flip
垂直,水平或即垂直又水平翻转二维数组
void cvFlip( const CvArr* src, CvArr* dst=NULL, int flip_mode=0);
#define cvMirror cvFlip
src
原数组.
dst
目标责任制数组. 如果 dst = NULL 翻转是在内部替换.
flip_mode
指定怎样去翻转数组。
flip_mode = 0 沿X-轴翻转, flip_mode > 0 (如 1) 沿Y-轴翻转, flip_mode < 0 (如 -1) 沿X-轴和Y-轴翻转.见下面的公式
函数cvFlip 以三种方式之一翻转数组 (行和列下标是以0为基点的):
dst(i,j)=src(rows(src)-i-1,j) if flip_mode = 0
dst(i,j)=src(i,cols(src1)-j-1) if flip_mode > 0
dst(i,j)=src(rows(src)-i-1,cols(src)-j-1) if flip_mode < 0
函数主要使用在:
· 垂直翻转图像(flip_mode = 0)用于 顶-左和底-左图像结构的转换, 主要用于WIN32系统下的视频操作处理.
· 水平图像转换,使用连续的水平转换和绝对值差检查垂直轴对称(flip_mode > 0)
· 水平和垂直同时转换,用于连续的水平转换和绝对真理值差检查中心对称s(flip_mode < 0)
· 翻转1维指针数组的顺序(flip_mode > 0)
Split
分割多通道数组成几个单通道数组或者从数组中提取一个通道
void cvSplit( const CvArr* src, CvArr* dst0, CvArr* dst1,
CvArr* dst2, CvArr* dst3 );
#define cvCvtPixToPlane cvSplit
src
原数组.
dst0...dst3
目标通道
函数 cvSplit 分割多通道数组成分离的单通道数组d。可获得两种操作模式 . 如果原数组有N通道且前N输出数组非NULL, 所有的通道都会被从原数组中提取,如果前N个通道只有一个通道非NULL函数只提取该指定通道,否则会产生一个错误,馀下的通道(超过前N个通道的以上的)必须被设置成NULL,对于设置了COI的IplImage 结使用cvCopy 也可以从图像中提取单通道。
Merge
从几个单通道数组组合成多通道数组或插入一个单通道数组
void cvMerge( const CvArr* src0, const CvArr* src1,
const CvArr* src2, const CvArr* src3, CvArr* dst );
#define cvCvtPlaneToPix cvMerge
src0... src3
输入的通道.
dst
输出数组.
函数cvMerge 是前一个函数的反向操作。如果输出数组有N个通道并且前N个输入通道非NULL,就拷贝所有通道到输出数组,如果在前N个通道中只有一个单通道非NULL ,只拷贝这个通道到输出数组,否则 就会产生错误。除前N通道以外的馀下的通道必须置NULL。对于设置了COI的 IplImage结构使用 cvCopy也可以实现向图像中插入一个通道 。
MixChannels
拷贝输入数组的若干个通道到输出数组的某些通道上面.
void cvMixChannels( const CvArr** src, int src_count,
CvArr** dst, int dst_count,
const int* from_to, int pair_count );
src
输入数组
src_count
输入数组的个数
dst
输出数组
dst_count
输出数组的个数
from_to
对数的阵列
pair_count
from_to里面的对数的个数,或者说被拷贝的位面的个数.
RandShuffle
随机交换数组的元素
void cvRandShuffle( CvArr* mat, CvRNG* rng, double iter_factor=1.);
mat
输入的矩阵,用来被随机处理.
rng
随机数产生器用来随机交换数组元素.如果为NULL,一个当前的随机数发生器将被创建与使用.
iter_factor
相关的参数,用来刻划交换操作的密度.请看下面的说明.
这个函数在每个反复的操作中交换随机选择的矩阵里面的元素(在多通道的数组里面每个元素可能包括若干个部分),反复的次数(也就是交换的对数)等于round(iter_factor*rows(mat)*cols(mat)), 因此如果iter_factor=0,没有交换产生,如果等于1意味着随机交换了rows(mat)*cols(mat)对数.
算术,逻辑和比较
LUT
利用查找表转换数组
void cvLUT( const CvArr* src, CvArr* dst, const CvArr* lut );
src
元素为8位的原数组。
dst
与原数组有相同通道数的输出数组,深度不确定
lut
有256个元素的查找表;必须要与原输出数组有相同像深。
函数cvLUT 使用查找表中的值添充输出数组. 坐标入口来自于原数组,也就是说函数处理每个元素按如下方式:
dst(I)=lut[src(I)+DELTA]
这里当src的深度是CV_8U时DELTA=0 ,src的深度是CV_8S时 DELTA=128
ConvertScale
使用线性变换转换数组
void cvConvertScale( const CvArr* src, CvArr* dst, double scale=1, double shift=0 );
#define cvCvtScale cvConvertScale
#define cvScale cvConvertScale
#define cvConvert( src, dst ) cvConvertScale( (src), (dst), 1, 0 )
src
输入数组.
dst
输出数组
scale
比例因子.
shift
该加数被加到输入数组元素按比例缩放后得到的元素上
函数 cvConvertScale 有多个不同的目的因此就有多个同义函数(如上面的#define所示)。该函数首先对输入数组的元素进行比例缩放,然后将shift加到比例缩放后得到的各元素上,即: dst(I)=src(I)*scale + (shift,shift,...),最后可选的类型转换将结果拷贝到输出数组。
多通道的数组对各个通道是独立处理的。
类型转换主要用舍入和溢出截断来完成。也就是如果缩放+转换后的结果值不能用输出数组元素类型值精确表达,就设置成在输出数组数据轴上最接近该数的值。
如果 scale=1, shift=0 就不会进行比例缩放. 这是一个特殊的优化,相当于该函数的同义函数名:cvConvert 。如果原来数组和输出数组的类型相同,这是另一种特殊情形,可以被用于比例缩放和平移矩阵或图像,此时相当于该函数的同义函数名:cvScale。
ConvertScaleAbs
使用线性变换转换输入数组元素成8位无符号整型
void cvConvertScaleAbs( const CvArr* src, CvArr* dst, double scale=1, double shift=0 );
#define cvCvtScaleAbs cvConvertScaleAbs
src
原数组
dst
输出数组 (深度为 8u).
scale
比例因子.
shift
原数组元素按比例缩放后添加的值。
函数 cvConvertScaleAbs 与前一函数是相同的,但它是存贮变换结果的绝对值:
dst(I)=abs(src(I)*scale + (shift,shift,...))
函数只支持目标数数组的深度为 8u (8-bit 无符号) , 对于别的类型函数仿效于cvConvertScale 和 cvAbs 函数的联合
Add
计算两个数组中每个元素的和
void cvAdd( const CvArr* src1, const CvArr* src2, CvArr* dst, const CvArr* mask=NULL );
src1
第一个原数组
src2
第二个原数组
dst
输出数组
mask
操作的复盖面, 8-bit单通道数组; 只有复盖面指定的输出数组被修改。
函数 cvAdd 加一个数组到别一个数组中:
dst(I)=src1(I)+src2(I) if mask(I)!=0
除复盖面外所有的数组必须有相同的类型相同的大小(或ROI尺寸)。
AddS
计算数量和数组的和
void cvAddS( const CvArr* src, CvScalar value, CvArr* dst, const CvArr* mask=NULL );
src
原数组.
value
被加入数量
dst
输出数组
mask
操作的复盖面(8-bit单通道数组) ; 只有复盖面指定的输出数组被修改
函数 cvAddS 用数量值与原数组src1的每个元素想加并存贮结果到
dst(I)=src(I)+value if mask(I)!=0
除复盖面外所有数组都必须有相同的类型,相同的大小(或ROI大小)
AddWeighted
计算两数组的加权值的和
void cvAddWeighted( const CvArr* src1, double alpha,
const CvArr* src2, double beta,
double gamma, CvArr* dst );
src1
第一个原数组.
alpha
第一个数组元素的权值
src2
第二个原数组
beta
第二个数组元素的权值
dst
输出数组
gamma
添加的常数项。
函数 cvAddWeighted 计算两数组的加权值的和:
dst(I)=src1(I)*alpha+src2(I)*beta+gamma
所有的数组必须有相同的类型相同的大小(或ROI大小)
Sub
计算两个数组每个元素的差
void cvSub( const CvArr* src1, const CvArr* src2, CvArr* dst, const CvArr* mask=NULL );
src1
第一个原数组
src2
第二个原数组.
dst
输出数组.
mask
操作复盖面( 8-bit 单通道数组); 只有复盖面指定的输出数组被修改
函数cvSub 从一个数组减去别一个数组:
dst(I)=src1(I)-src2(I) if mask(I)!=0
除复盖面外所有数组都必须有相同的类型,相同的大小(或ROI大小)
SubS
计算数组和数量之间的差
void cvSubS( const CvArr* src, CvScalar value, CvArr* dst, const CvArr* mask=NULL );
src
原数组.
value
被减的数量.
dst
输出数组.
mask
操作复盖面( 8-bit 单通道数组); 只有复盖面指定的输出数组被修改
函数 cvSubS 从原数组的每个元素中减去一个数量:
dst(I)=src(I)-value if mask(I)!=0
除复盖面外所有数组都必须有相同的类型,相同的大小(或ROI大小)。
SubRS
计算数量和数组之间的差
void cvSubRS( const CvArr* src, CvScalar value, CvArr* dst, const CvArr* mask=NULL );
src
第一个原数组。
value
被减的数量
dst
输出数组
mask
操作复盖面( 8-bit 单通道数组); 只有复盖面指定的输出数组被修改
函数 cvSubRS 从一个数量减去原数组的每个元素:
dst(I)=value-src(I) if mask(I)!=0
除复盖面外所有数组都必须有相同的类型,相同的大小(或ROI大小)。
Mul
计算两个数组中每个元素的积
void cvMul( const CvArr* src1, const CvArr* src2, CvArr* dst, double scale=1 );
src1
第一个原数组.
src2
第二个原数组.
dst
输出数组.
scale
设置的比例因子
函数 cvMul 计算两个数组中每个元素的积:
dst(I)=scale•src1(I)•src2(I)
所有的数组必须有相同的类型和相同的大小(或ROI大小)
Div
两个数组每个元素相除
void cvDiv( const CvArr* src1, const CvArr* src2, CvArr* dst, double scale=1 );
src1
第一个原数组。如该指针为NULL,假高该数组的所有元素都为1
src2
第二个原数组。
dst
输出数组
scale
设置的比例因子
函数 cvDiv 用一个数组除以另一个数组:
dst(I)=scale•src1(I)/src2(I), if src1!=NULL
dst(I)=scale/src2(I),: if src1=NULL
所有的数组必须有相同的类型和相同的大小(或ROI大小)
And
计算两个数组的每个元素的按位与
void cvAnd( const CvArr* src1, const CvArr* src2, CvArr* dst, const CvArr* mask=NULL );
src1
第一个原数组
src2
第二个原数组.
dst
输出数组
mask
操作复盖面( 8-bit 单通道数组); 只有复盖面指定的输出数组被修改
函数 cvAnd 计算两个数组的每个元素的按位逻辑与:
dst(I)=src1(I)&src2(I) if mask(I)!=0
对浮点数组按位表示操作是很有利的。除复盖面,所有数组都必须有相同的类型,相同的大小(或ROI大小)。
AndS
计算数组每个元素与数量之间的按位与
void cvAndS( const CvArr* src, CvScalar value, CvArr* dst, const CvArr* mask=NULL );
src
原数组.
value
操作中用到的数量
dst
输出数组
mask
操作复盖面( 8-bit 单通道数组); 只有复盖面指定的输出数组被修改
函数 AndS 计算数组中每个元素与数量之量的按位与:
dst(I)=src(I)&value if mask(I)!=0
在实际操作之前首先把数量类型转换成与数组相同的类型。对浮点数组按位表示操作是很有利的。除复盖面,所有数组都必须有相同的类型,相同的大小(或ROI大小)。
接下来的例子描述怎样计算浮点数组元素的绝对值,通过清除最前面的符号位:
float a[] = { -1, 2, -3, 4, -5, 6, -7, 8, -9 };
CvMat A = cvMat( 3, 3, CV_32F, &a );
int i, abs_mask = 0x7fffffff;
cvAndS( &A, cvRealScalar(*(float*)&abs_mask), &A, 0 );
for( i = 0; i < 9; i++ )
printf("%.1f ", a[i] );
代码结果是:
1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0
Or
计算两个数组每个元素的按位或
void cvOr( const CvArr* src1, const CvArr* src2, CvArr* dst, const CvArr* mask=NULL );
src1
第一个原数组
src2
第二个原数组
dst
输出数组.
mask
操作复盖面( 8-bit 单通道数组); 只有复盖面指定的输出数组被修改
函数 cvOr 计算两个数组每个元素的按位或:
dst(I)=src1(I)|src2(I)
对浮点数组按位表示操作是很有利的。除复盖面,所有数组都必须有相同的类型,相同的大小(或ROI大小)。
OrS
计算数组中每个元素与数量之间的按位或
void cvOrS( const CvArr* src, CvScalar value, CvArr* dst, const CvArr* mask=NULL );
src1
原数组
value
操作中用到的数量
dst
目数组.
mask
操作复盖面( 8-bit 单通道数组); 只有复盖面指定的输出数组被修改
函数 OrS 计算数组中每个元素和数量之间的按位或:
dst(I)=src(I)|value if mask(I)!=0
在实际操作之前首先把数量类型转换成与数组相同的类型。对浮点数组按位表示操作是很有利的。除复盖面,所有数组都必须有相同的类型,相同的大小(或ROI大小)。
Xor
计算两个数组中的每个元素的按位异或
void cvXor( const CvArr* src1, const CvArr* src2, CvArr* dst, const CvArr* mask=NULL );
src1
第一个原数组
src2
第二个原数组.
dst
输出数组
mask
操作复盖面( 8-bit 单通道数组); 只有复盖面指定的输出数组被修改
函数 cvXor 计算两个数组元素的按位异或:
dst(I)=src1(I) src2(I) if mask(I)!=0
对浮点数组按位表示操作是很有利的。除复盖面,所有数组都必须有相同的类型,相同的大小(或ROI大小)。
XorS
计算数组元素与数量之间的按位异或
void cvXorS( const CvArr* src, CvScalar value, CvArr* dst, const CvArr* mask=NULL );
src
原数组
value
操作中用到的数量
dst
输出数组.
mask
操作复盖面( 8-bit 单通道数组); 只有复盖面指定的输出数组被修改。
函数 XorS 计算数组元素与数量之间的按位异或:
dst(I)=src(I) value if mask(I)!=0
在实际操作之前首先把数量类型转换成与数组相同的类型。对浮点数组按位表示操作是很有利的。除复盖面,所有数组都必须有相同的类型,相同的大小(或ROI大小)。
下面例子描述怎样对共轭复数向量转换,通过转换前面的符号位:
float a[] = { 1, 0, 0, 1, -1, 0, 0, -1 };
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 :
如果数组是 IplImage 类型和设置 COI , 该函数只处理选定的通道并将和存储到第一个标量成员 (S0)。
AvgSdv
计算数组元素的平均值和标准差
void cvAvgSdv( const CvArr* arr, CvScalar* mean, CvScalar* std_dev, const CvArr* mask=NULL );
arr
数组
mean
指向平均值的指针,如果不需要的话可以为空( NULL)。
std_dev
指向标准差的指针。
mask
可选操作掩模。
函数 cvAvgSdv 独立地为每一个通道计算数组元素的平均值和标准差:
如果数组是 IplImage 类型和设置了COI ,该函数只处理选定的通道并将平均值和标准差存储到第一个输出标量成员 (mean0 和 std-dev0)。
MinMaxLoc
查找数组和子数组的全局最小值和最大值
void cvMinMaxLoc( const CvArr* arr, double* min_val, double* max_val,
CvPoint* min_loc=NULL, CvPoint* max_loc=NULL, const CvArr* mask=NULL );
arr
输入数组, 单通道或者设置了 COI 的多通道。
min_val
指向返回的最小值的指针。
max_val
指向返回的最大值的指针。
min_loc
指向返回的最小值的位置指针。
max_loc
指向返回的最大值的位置指针。
mask
选择一个子数组的操作掩模。
函数 MinMaxLoc 查找元素中的最小值和最大值以及他们的位置。函数在整个数组、或选定的ROI区域(对IplImage)或当MASK不为NULL时指定的数组区域中,搜索极值。如果数组不止一个通道,它就必须是设置了 COI 的 IplImage 类型。 如果是多维数组 min_loc->x 和 max_loc->x 将包含极值的原始位置信息 (线性的)。
Norm
计算数组的绝对范数,绝对差分范数或者相对差分范数
double cvNorm( const CvArr* arr1, const CvArr* arr2=NULL, int norm_type=CV_L2, const CvArr* mask=NULL );
arr1
第一输入图像
arr2
第二输入图像 ,如果为空(NULL), 计算 arr1 的绝对范数,否则计算 arr1-arr2 的绝对范数或者相对范数。
normType
范数类型,参见“讨论”。
mask
可选操作掩模。
如果 arr2 为空(NULL),函数 cvNorm 计算 arr1 的绝对范数:
norm = ||arr1||C = maxI abs(arr1(I)), 如果 normType = CV_C
norm = ||arr1||L1 = sumI abs(arr1(I)), 如果 normType = CV_L1
norm = ||arr1||L2 = sqrt( sumI arr1(I)2), 如果 normType = CV_L2
如果 arr2 不为空(NULL), 该函数计算绝对差分范数或者相对差分范数:
norm = ||arr1-arr2||C = maxI abs(arr1(I)-arr2(I)), 如果 normType = CV_C
norm = ||arr1-arr2||L1 = sumI abs(arr1(I)-arr2(I)), 如果 normType = CV_L1
norm = ||arr1-arr2||L2 = sqrt( sumI (arr1(I)-arr2(I))2 ), 如果 normType = CV_L2
或者
norm = ||arr1-arr2||C/||arr2||C, 如果 normType = CV_RELATIVE_C
norm = ||arr1-arr2||L1/||arr2||L1, 如果 normType = CV_RELATIVE_L1
norm = ||arr1-arr2||L2/||arr2||L2, 如果 normType = CV_RELATIVE_L2
函数 Norm 返回计算所得的范数。多通道数组被视为单通道处理,因此,所有通道的结果是结合在一起的。
Reduce
简化一个矩阵成为一个向量
cvReduce( const CvArr* src, CvArr* dst, int dim, int op=CV_REDUCE_SUM);
src
输入矩阵
dst
输出的通过处理输入矩阵的所有行/列而得到的单行/列向量
dim
矩阵被简化后的维数索引.0意味着矩阵被处理成一行,1意味着矩阵被处理成为一列,-1时维数将根据输出向量的大小自动选择.
op
简化操作的方式,可以有以下几种取值:
CV_REDUCE_SUM-输出是矩阵的所有行/列的和.
CV_REDUCE_AVG-输出是矩阵的所有行/列的平均向量.
CV_REDUCE_MAX-输出是矩阵的所有行/列的最大值.
CV_REDUCE_MIN-输出是矩阵的所有行/列的最小值.
这个函数通过把矩阵的每行/列当作一维向量并对其做某种特殊的操作将一个矩阵简化成为一个向量.例如,这个函数可以用于计算一个光栅图象的水平或者垂直投影.在取值为CV_REDUCE_AVG与CV_REDUCE_SUM的情况下输出可能有很大的位深度用于维持准确性,这两种方式也适合于处理多通道数组.
注意,对于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的对角线元素的和。
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 方法可以解决):
如果使用 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 分解成一个对角线矩阵和两个正交矩阵的乘积:
这里 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 计算两个向量之间的加权距离,其返回结果是:
协方差矩阵可以用函数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 用均匀分布的或者正态分布的随机数填充输出数组。在下面的例子中该函数被用来添加一些正态分布的浮点数到二维数组的随机位置。
CvRNG rng_state = cvRNG(0xffffffff);
int i, pointCount = 1000;
CvMat* locations = cvCreateMat( pointCount, 1, CV_32SC2 );
CvMat* values = cvCreateMat( pointCount, 1, CV_32FC1 );
CvSize size = cvGetSize( noisy_screen );
cvRandInit( &rng_state,
0, 1,
0xffffffff ,
CV_RAND_UNI );
cvRandArr( &rng_state, locations, CV_RAND_UNI, cvScalar(0,0,0,0), cvScalar(size.width,size.height,0,0) );
rng_state.disttype = CV_RAND_NORMAL;
cvRandSetRange( &rng_state,
30 ,
100 ,
-1 );
cvRandArr( &rng_state, values, CV_RAND_NORMAL,
cvRealScalar(100), // average intensity
cvRealScalar(30) // deviation of the intensity
);
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;
}
cvReleaseMat( &locations );
cvReleaseMat( &values );
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 重写的前一个函数讨论的例子:
CvRNG rng_state = cvRNG(0xffffffff);
int i, pointCount = 1000;
CvSize size = cvGetSize( noisy_screen );
#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;
pt.x = cvRandInt( &rng_state ) % size.width;
pt.y = cvRandInt( &rng_state ) % size.height;
if( valuesLeft <= 0 )
{
cvRandArr( &rng_state, &normalValueMat, CV_RAND_NORMAL, cvRealScalar(100), cvRealScalar(30) );
valuesLeft = bufferSize;
}
((float*)cvPtr2D( noisy_screen, pt.y, pt.x, 0 ) = normalValueBuffer[--valuesLeft];
}
RandReal
返回浮点型随机数并更新 RNG
double cvRandReal( CvRNG* rng );
rng
被 cvRNG 初始化的 RNG 状态
函数 cvRandReal 返回均匀分布的随机浮点数,范围在 0..1 之间 (不包括 1 )。