Permalink
Browse files

update with modern examples and readme with illustrations

  • Loading branch information...
Greg Borenstein
Greg Borenstein committed Oct 22, 2012
1 parent f951fba commit b56dae0ec9ac279717f7319251d5015f13ac6cb5
View
BIN .DS_Store
Binary file not shown.
View
172 PCA.pde
@@ -1,172 +0,0 @@
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileReader;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.SortedSet;
-import java.util.StringTokenizer;
-import java.util.TreeSet;
-
-import Jama.EigenvalueDecomposition;
-import Jama.Matrix;
-
-
-class PrincipleComponent implements Comparable<PrincipleComponent> {
- double eigenValue;
- double[] eigenVector;
-
- PrincipleComponent(double eigenValue, double[] eigenVector) {
- this.eigenValue = eigenValue;
- this.eigenVector = eigenVector;
- }
-
- int compareTo(PrincipleComponent o) {
- int ret = 0;
- if (eigenValue > o.eigenValue) {
- ret = -1;
- } else if (eigenValue < o.eigenValue) {
- ret = 1;
- }
- return ret;
- }
-
- // FIXME: make eigenvectors print out nicer
- String toString() {
- return "Principle Component, eigenvalue: " + eigenValue + ", eigenvector: ["
- + eigenVector + "]";
- }
-}
-
-
-class PCA {
- Matrix covMatrix;
- EigenvalueDecomposition eigenstuff;
- double[] eigenvalues;
- Matrix eigenvectors;
- SortedSet<PrincipleComponent> principleComponents;
- double[] means;
-
- PCA(double[][] input) {
- means = new double[input[0].length];
- double[][] cov = getCovariance(input, means);
- covMatrix = new Matrix(cov);
- eigenstuff = covMatrix.eig();
- eigenvalues = eigenstuff.getRealEigenvalues();
- eigenvectors = eigenstuff.getV();
- double[][] vecs = eigenvectors.getArray();
- int numComponents = eigenvectors.getColumnDimension(); // same as num rows.
- principleComponents = new TreeSet<PrincipleComponent>();
- for (int i = 0; i < numComponents; i++) {
- double[] eigenvector = new double[numComponents];
- for (int j = 0; j < numComponents; j++) {
- eigenvector[j] = vecs[i][j];
- }
- principleComponents.add(new PrincipleComponent(eigenvalues[i], eigenvector));
- }
- }
-
- /**
- * Subtracts the mean value from each column. The means must be precomputed, which you get for
- * free when you make a PCA instance (just call getMeans()).
- *
- * @param input
- * Some data, where each row is a sample point, and each column is a dimension.
- * @param mean
- * The means of each dimension. This could be computed from 'input' directly, but for
- * efficiency's sake, it should only be done once and the result saved.
- * @return Returns a translated matrix where each cell has been translated by the mean value of
- * its dimension.
- */
- double[][] getMeanAdjusted(double[][] input, double[] mean) {
- int nRows = input.length;
- int nCols = input[0].length;
- double[][] ret = new double[nRows][nCols];
- for (int row = 0; row < nRows; row++) {
- for (int col = 0; col < nCols; col++) {
- ret[row][col] = input[row][col] - mean[col];
- }
- }
- return ret;
- }
-
- /**
- * Returns the top n principle components in descending order of relevance.
- */
- List<PrincipleComponent> getDominantComponents(int n) {
- List<PrincipleComponent> ret = new ArrayList<PrincipleComponent>();
- int count = 0;
- for (PrincipleComponent pc : principleComponents) {
- ret.add(pc);
- count++;
- if (count >= n) {
- break;
- }
- }
- return ret;
- }
-
-
- Matrix getDominantComponentsMatrix(List<PrincipleComponent> dom) {
- int nRows = dom.get(0).eigenVector.length;
- int nCols = dom.size();
- Matrix matrix = new Matrix(nRows, nCols);
- for (int col = 0; col < nCols; col++) {
- for (int row = 0; row < nRows; row++) {
- matrix.set(row, col, dom.get(col).eigenVector[row]);
- }
- }
- return matrix;
- }
-
- int getNumComponents() {
- return eigenvalues.length;
- }
-
- double[][] getCovariance(double[][] input, double[] meanValues) {
- int numDataVectors = input.length;
- int n = input[0].length;
-
- double[] sum = new double[n];
- double[] mean = new double[n];
- for (int i = 0; i < numDataVectors; i++) {
- double[] vec = input[i];
- for (int j = 0; j < n; j++) {
- sum[j] = sum[j] + vec[j];
- }
- }
- for (int i = 0; i < sum.length; i++) {
- mean[i] = sum[i] / numDataVectors;
- }
-
- double[][] ret = new double[n][n];
- for (int i = 0; i < n; i++) {
- for (int j = i; j < n; j++) {
- double v = getCovariance(input, i, j, mean);
- ret[i][j] = v;
- ret[j][i] = v;
- }
- }
- if (meanValues != null) {
- System.arraycopy(mean, 0, meanValues, 0, mean.length);
- }
- return ret;
- }
-
- double getCovariance(double[][] matrix, int colA, int colB, double[] mean) {
- double sum = 0;
- for (int i = 0; i < matrix.length; i++) {
- double v1 = matrix[i][colA] - mean[colA];
- double v2 = matrix[i][colB] - mean[colB];
- sum = sum + (v1 * v2);
- }
- int n = matrix.length;
- double ret = (sum / (n - 1));
- return ret;
- }
-
- double[] getMeans() {
- return means;
- }
-}
-
View
@@ -0,0 +1,30 @@
+## Processing-PCA
+
+Examples of using Principle Component Analysis in Processing with [pca_transform](https://github.com/mkobos/pca_transform).
+
+### Using PCA with basic numerical data
+
+<a href="http://www.flickr.com/photos/unavoidablegrain/8112912665/" title="PCA with basic data by atduskgreg, on Flickr"><img src="http://farm9.staticflickr.com/8195/8112912665_83202bcb86.jpg" width="479" height="500" alt="PCA with basic data"></a>
+
+This example demonstrates the most basic application of PCA to find the main axes of variation amongst some random 2D points.
+
+### Using PCA with OpenCV to find object orientation
+
+<a href="http://www.flickr.com/photos/unavoidablegrain/8074895164/" title="PCA and OpenCV to find object orientation in Processing by atduskgreg, on Flickr"><img src="http://farm8.staticflickr.com/7121/8074895164_86852dce43.jpg" width="500" height="392" alt="PCA and OpenCV to find object orientation in Processing"></a>
+
+This example uses OpenCV to reduce an image of a pen on a white background to a binary image (each pixel 100% white or black). It then treats these pixels as points to perform PCA. The resulting principle components make up the axes of orientation of the object.
+
+### Using PCA with OpenCV for live object orienation
+
+<iframe src="http://player.vimeo.com/video/51174493?byline=0&amp;portrait=0&amp;color=ffffff" width="500" height="313" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe> <p><a href="http://vimeo.com/51174493">PCA Object Orientation Tracking with Processing</a> from <a href="http://vimeo.com/user1249829">Greg Borenstein</a> on <a href="http://vimeo.com">Vimeo</a>.</p>
+
+This example improves on the one above by applying the same technique to live video to find object orientation interactively.
+
+
+### Using PCA with Kinect to find Head and Hand Orientation
+
+<a href="http://www.flickr.com/photos/unavoidablegrain/8111539204/" title="PCA with Kinect for head orientation by atduskgreg, on Flickr"><img src="http://farm9.staticflickr.com/8465/8111539204_ff5ae2bb5d.jpg" width="500" height="386" alt="PCA with Kinect for head orientation"></a>
+
+<a href="http://www.flickr.com/photos/unavoidablegrain/8111539238/" title="PCA with Kinect for hand orientation by atduskgreg, on Flickr"><img src="http://farm9.staticflickr.com/8473/8111539238_b768e78912.jpg" width="500" height="386" alt="PCA with Kinect for hand orientation"></a>
+
+This example uses the [SimpleOpenNI Kinect library](http://code.google.com/p/simple-openni/) to access the depth points and joint data from the Kinect. It finds all of the depth points within a bounding box around a given joint (in this case, the head) and then conducts PCA on those points in order to find the orientation of the joint. This gives you head or hand orientation, which is otherwise not available from the Kinect joint data.
View
@@ -1,128 +0,0 @@
-// get this from here: http://www.gicentre.org/utils/index.php
-import org.gicentre.utils.stat.*;
-XYChart lineChart;
-
-void setup() {
-
- size(500,500);
-
- double[][] matrix = new double[][] {
- {
- 2.5, 2.4
- }
- , {
- 0.5, 0.7
- }
- , {
- 2.2, 2.9
- }
- , {
- 1.9, 2.2
- }
- , {
- 3.1, 3.0
- }
- , {
- 2.3, 2.7
- }
- , {
- 2, 1.6
- }
- , {
- 1, 1.1
- }
- , {
- 1.5, 1.6
- }
- , {
- 1.1, 0.9
- }
- };
-
- lineChart = new XYChart(this);
- Matrix originalData = new Matrix(matrix);
-
-
- double[] all = originalData.getColumnPackedCopy();
- double[] column1 = Arrays.copyOfRange(all,0,9);
- double[] column2 = Arrays.copyOfRange(all,10,19);
-
-
- lineChart.setData(dToF(column1), dToF(column2));
- lineChart.showXAxis(true);
- lineChart.showYAxis(true);
- lineChart.setMinY(0);
- lineChart.setPointColour(color(180,50,50));
- lineChart.setPointSize(5);
-
- originalData.print(8, 4);
- PCA pca = new PCA(matrix);
- int numComponents = pca.getNumComponents();
- println("There are " + numComponents + " components.");
-
- int k = 2;
- List<PrincipleComponent> mainComponents = pca.getDominantComponents(k);
- int counter = 1;
- println("Showing top " + k + " principle components.");
- for (PrincipleComponent pc : mainComponents) {
- println("Component " + (counter++) + ": " + pc);
- }
-
- Matrix features = pca.getDominantComponentsMatrix(mainComponents);
- println("Feature matrix (k=" + k + ") :");
- features.print(8, 2);
-
- Matrix featuresXpose = features.transpose();
- println("Transposed feature matrix (k=" + k + ") :");
- featuresXpose.print(8, 4);
-
- double[][] matrixAdjusted = pca.getMeanAdjusted(matrix, pca.getMeans());
- Matrix adjustedInput = new Matrix(matrixAdjusted);
- println("Original input adjusted by dimension means (k=" + k + ") :");
- adjustedInput.print(8, 4);
- Matrix xformedData = featuresXpose.times(adjustedInput.transpose());
- println("Transformed data into PCA-space (k=" + k + ") :");
- xformedData.transpose().print(8, 4);
-
- k = 1;
- mainComponents = pca.getDominantComponents(k);
- counter = 1;
- println("Showing top " + k + " principle components.");
- for (PrincipleComponent pc : mainComponents) {
- println("Component " + (counter++) + ": " + pc);
- }
-
- features = pca.getDominantComponentsMatrix(mainComponents);
- println("Feature matrix (k=" + k + ") :");
- features.print(8, 4);
-
- featuresXpose = features.transpose();
- println("Xposed feature matrix (k=" + k + ") :");
- featuresXpose.print(8, 4);
-
- matrixAdjusted = pca.getMeanAdjusted(matrix, pca.getMeans());
- adjustedInput = new Matrix(matrixAdjusted);
- println("Original input adjusted by dimension means (k=" + k + ") :");
- adjustedInput.print(8, 4);
- xformedData = featuresXpose.times(adjustedInput.transpose());
- println("Transformed data into PCA-space (k=" + k + ") :");
- xformedData.transpose().print(8, 4);
-
- noLoop();
-}
-
-void draw() {
- background(255);
- lineChart.draw(15, 15, width-30, height-30);
-}
-
-float[] dToF(double[] doubleArray) {
- float[] floatArray = new float[doubleArray.length];
- for (int i = 0 ; i < doubleArray.length; i++)
- {
- floatArray[i] = (float) doubleArray[i];
- }
- return floatArray;
-
-}
-
File renamed without changes.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Oops, something went wrong.

0 comments on commit b56dae0

Please sign in to comment.