在人脸表情所用的特征中,LBP特征中是一个常用的特征。但是LBP特征提取后,维数太高,即使使用LBP直方图的特征仍然很高,因此需要降维。一个比较好的降维方法就是PCA。在OpenCV中,cvCalcPCA函数可以直接调用进行PCA降维。以前在人脸识别的程序中,我曾经调用过这个函数,这次再次使用,但是却出错了。主要有两个问题:
1 特征值和特征向量的行列数设置问题
如果按如下方式使用,也就是根据PCA的数学表达式进行参数设置:
AvgVector=cvCreateMat(1,m_pm.dim,CV_32FC1);
EigenValue_Row=cvCreateMat(1,m_pm.dim,),CV_32FC1);
EigenVector=cvCreateMat((m_pm.dim),m_pm.dim,CV_32FC1);
那么就会出现错误:
Incorrect size of input array。
根据错误提示,说明特征向量的列数和输入矩阵(特征矩阵)的列数一致,行数要和特征值的数目一致;而特征值的数目(特征值矩阵的行数或列数)不能大于输入矩阵的行数和列数。
因此,需要下列设定:
AvgVector=cvCreateMat(1,m_pm.dim,CV_32FC1);
EigenValue_Row=cvCreateMat(1,min(m_pm.dim,m_pm.numOfSamples),CV_32FC1);
或EigenValue_Row=cvCreateMat(min(m_pm.dim,m_pm.numOfSamples),1,CV_32FC1);
EigenVector=cvCreateMat(min(m_pm.dim,m_pm.numOfSamples),m_pm.dim,CV_32FC1);
// 计算特征值,对原始数据进行变换,得到主成分
cvCalcPCA(vector_feature,AvgVector,EigenValue_Row,EigenVector,CV_PCA_DATA_AS_ROW);
cvProjectPCA(vector_feature,AvgVector,EigenVector,vector_pca);
2 出现中断点
由于保存输入矩阵的特征是一维的,需要转换成二维的,所以要申请一段内存保存特征,在cvCalcPCA之前这段内存不能释放,需要在cvCalcPCA之后才能释放,所以正确 的代码为:
float* features=new float[lenOfFeatures];
...
CvMat* vector_feature=cvCreateMat(m_pm.numOfSamples,m_pm.dim,CV_32FC1);
cvSetData(vector_feature,features,vector_feature->step);
CvMat *AvgVector;
CvMat *EigenVector;
CvMat *EigenValue_Row;
CvMat* vector_pca=cvCreateMat(m_pm.numOfSamples,PCA_DIM,CV_32FC1);
AvgVector=cvCreateMat(1,m_pm.dim,CV_32FC1);
EigenValue_Row=cvCreateMat(1,min(m_pm.dim,m_pm.numOfSamples),CV_32FC1);
EigenVector=cvCreateMat(min(m_pm.dim,m_pm.numOfSamples),m_pm.dim,CV_32FC1);
// 计算特征值,对原始数据进行变换,得到主成分
cvCalcPCA(vector_feature,AvgVector,EigenValue_Row,EigenVector,CV_PCA_DATA_AS_ROW);
cvProjectPCA(vector_feature,AvgVector,EigenVector,vector_pca);
delete[] features;