cvCalcEigenObject——opencv内置PCA算法的函数小记。
本文来自:http://www.cnblogs.com/linzhao/archive/2012/01/04/2312344.html
cvCalscEigenObject()函数,包含于<cvAux.h>中。在PCA人脸识别的程序中,属于核心算法。
先翻译一段注解,原文来自:
http://www710.univ-lyon1.fr/~bouakaz/OpenCV-0.9.5/docs/ref/OpenCVRef_ObjectRecognition.htm
void cvCalcEigenObjects( int nObjects, void* input, void* output, int ioFlags, int ioBufSize, void* userData,
CvTermCriteria* calcLimit, IplImage* avg, float* eigVals )
输入为目标向量,计算正交特征基向量(orthonormal eigen basis)和目标平均值。
nObjects: 目标的数量。 input: IplImage队列(数组)的指针,或者根随ioFlag的值变化的读回调函数(read callback function)
函数。 output: 对于目标的队列(数组)的指针,或者根随参数值变化的写回调函数(write callback functions)。 ioFlags:
。
ioBuffSize: buffsize,0为未知大小。 userData: 指向回调函数(callback function)必须数据结构体的指针。 calcLimit: 终止迭代计算目标特征的条件。 avg: avg。 eigVals: 以降序排列的特征值的行向量指针。可以为0。
cvCalcEigenObject计算出正交特征基(eigen face,而且是正交的,第二点是我猜的),以及输入目标的平均值。根据ioFlags参数,此函数可用在直接访问和回调函数两种模式下。根据calcLimit的参数,计算会在前maxIters主要特征目标被提取后结束(这句话有点绕,应该就是提取了前int_max_iter个特征值,),另一种结束的情况是:目前特征值同最s大特征值的比值降至calcLimit的epsilon值之下。
clacLimit的type参数必须为CV_TERMCRIT_NUMB, CV_TERMCRIT_EPS,
or CV_TERMCRIT_NUMB | CV_TERMCRIT_EPS。 函数返回maxIter&epsilond的真值。
平均值avg 计算得到的特征目标,排序是根据相应的特征值降序而得。
程序中这个函数的例子是这样的。
// compute average image, eigenvalues, and eigenvectors cvCalcEigenObjects( nTrainFaces, (void*)faceImgArr, (void*)eigenVectArr, CV_EIGOBJ_NO_CALLBACK, 0, 0, &calcLimit, pAvgTrainImg, eigenValMat->data.fl);
参数第一个不用说。faceImgArr,是IplImage**,存有nTrainFaces个训练用人脸。eigenVectArr同样也是IplImage**,是需要计算的特征脸(eigenface),每个大小和训练脸相同,取前nEigens个储存。
这段代码有助于理解。
for(i=0; i<nEigens; i++) eigenVectArr[i] = cvCreateImage(faceImgSize, IPL_DEPTH_32F, 1);
后面3个参数,表明不需要回调函数。
calcLimit是一个迭代算法终止准则。
赋值如下calcLimit = cvTermCriteria( CV_TERMCRIT_ITER, nEigens, 1);
它的类型定义如下:
typedef struct CvTermCriteria
{
int type; int max_iter; //最大迭代次数
double epsilon; //结果精确性
}
看刚才翻译的那段已经说明:
根据calcLimit的参数,计算会在前maxIters主要特征目标被提取后结束(这句话有点绕,应该就是提取了前int_max_iter个特征值),另一种结束的情况是:目前特征值同最大特征值的比值降至calcLimit的epsilon值之下。在这个迭代算法终止条件的约束下,于是就产生了nEigen个特征脸(object's eigen vector)
程序后两个参数,一个是平均目标,另一个是存nEigen个特征值的向量。
核心已经包含在opencv里面了,我们通过这个函数可以方便地调用这个算法、高效地实现目的。