PCA Compact Trick
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