最近使用opencv+vs2008读取摄像头的时候,抓取图像总是返回空。无解,在网上看到一个资料,转载于此。
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 点集的几何变换,任意的线性颜色空间变换,通道转换等。
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 方法可以解决):
如果使用 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)。
-
CV_COVAR_SCRAMBLED - 输出协方差矩阵按下面计算:
函数 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
附
|