package edu.harvard.mcb.leschziner.analyze; import java.util.Collection; import com.googlecode.javacv.cpp.opencv_core; import com.googlecode.javacv.cpp.opencv_core.CvMat; import com.googlecode.javacv.cpp.opencv_core.IplImage; import edu.harvard.mcb.leschziner.core.Particle; public class CvPrincipalComponentAnalyzer implements PrincipalComponentAnalyzer { /** * */ private static final long serialVersionUID = -2016995095636434924L; private final int principalComponentCount; public CvPrincipalComponentAnalyzer(int principalComponentCount) { this.principalComponentCount = principalComponentCount; } @Override public PrincipalComponents analyze(Collection<Particle> targets) { if (!targets.isEmpty()) { int particleSize = targets.iterator().next().getSize(); int particleArea = particleSize * particleSize; // Each row is an image, each column is a pixel CvMat targetMat = CvMat.create(targets.size(), particleArea, opencv_core.CV_32FC1); int i = 0; // Reshape the targets for use in the matrix for (Particle target : targets) { IplImage targetImage = target.getImage(); // A single row containing all the pixels in the image CvMat row = CvMat.createHeader(1, particleArea, targetImage.depth(), targetImage.nChannels()); opencv_core.cvReshape(targetImage, row, targetImage.nChannels(), row.rows()); // A 32 bit float row from the pca matrix CvMat targetRow = CvMat.createHeader(1, particleArea, opencv_core.CV_32FC1); opencv_core.cvGetRow(targetMat, targetRow, i); // Convert the image data row to 32 bit float, normalizing it to // 0-1 scale opencv_core.cvConvertScale(row, targetRow, 1 / 255.0, 0); i++; } // Run PCA on the target matrix CvMat eigenValues = CvMat.create(principalComponentCount, 1); CvMat eigenVectors = CvMat.create(principalComponentCount, particleArea, opencv_core.CV_32FC1); CvMat averages = CvMat.create(1, particleArea, opencv_core.CV_32FC1); System.out.println("[" + this.getClass().getSimpleName() + "]: Running PCA"); opencv_core.cvCalcPCA(targetMat, averages, eigenValues, eigenVectors, opencv_core.CV_PCA_DATA_AS_ROW); CvMat subspace = CvMat.create(targets.size(), principalComponentCount, opencv_core.CV_32FC1); // Project onto a subspace System.out.println("[" + this.getClass().getSimpleName() + "]: Projecting Eigenvectors"); opencv_core.cvProjectPCA(targetMat, averages, eigenVectors, subspace); PrincipalComponents components = new PrincipalComponents(eigenValues, eigenVectors, subspace, averages); // Stuff everything into the principal components return components; } else { return null; } } }