astuce compacte PCA

PCA PCA_trick(const Mat& pcaset, int maxComponents)
{
     int n = pcaset.rows, p = pcaset.cols;
     cout << "\tcalculating 'true' means, varance and standard deviation..." << endl;
     Mat means(1, p, CV_32FC1);
     Mat variance(1, p, CV_32FC1);
     for (size_t i = 0; i < p; i++)
     {
       float avg = mean(pcaset.col(i)).val[0];
       means.at<float>(0, i) = avg;
       Mat p2 = Mat(1, n, CV_32F);
       for (size_t j = 0; j < n; j++)
         p2.at<float>(0, j) = pow(pcaset.at<float>(j, i), 2);
       variance.at<float>(0, i) = (1 / (float)n) * sum(p2).val[0] - pow(avg, 2);
     }

     //covariance matrix, AA', not the A'A like usual
     Mat M;
     Mat centred(n, p, CV_32FC1);
     for (size_t i = 0; i < n; i++)
       centred.row(i) = (pcaset.row(i) - means) / variance;
     mulTransposed(centred, M, 0);

     //compute eigenvalues and eigenvectors
     PCA pca;
     pca = PCA(M, cv::Mat(), CV_PCA_DATA_AS_ROW, maxComponents);

     //this is the compact trick
     pca.mean = means;
     pca.eigenvectors = pca.eigenvectors * centred;
     pca.eigenvectors = pca.eigenvectors.rowRange(Range(0, maxComponents));

     return pca;
}
Exuberant Earthworm