001/** 002 * Copyright (c) 2011, The University of Southampton and the individual contributors. 003 * All rights reserved. 004 * 005 * Redistribution and use in source and binary forms, with or without modification, 006 * are permitted provided that the following conditions are met: 007 * 008 * * Redistributions of source code must retain the above copyright notice, 009 * this list of conditions and the following disclaimer. 010 * 011 * * Redistributions in binary form must reproduce the above copyright notice, 012 * this list of conditions and the following disclaimer in the documentation 013 * and/or other materials provided with the distribution. 014 * 015 * * Neither the name of the University of Southampton nor the names of its 016 * contributors may be used to endorse or promote products derived from this 017 * software without specific prior written permission. 018 * 019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 020 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 021 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 022 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 023 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 026 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 028 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 029 */ 030package org.openimaj.demos; 031 032import java.io.File; 033import java.io.IOException; 034import java.util.Arrays; 035 036import org.openimaj.feature.FloatFV; 037import org.openimaj.feature.local.list.MemoryLocalFeatureList; 038import org.openimaj.image.feature.dense.gradient.dsift.FloatDSIFTKeypoint; 039import org.openimaj.image.feature.local.aggregate.FisherVector; 040import org.openimaj.math.matrix.algorithm.pca.PrincipalComponentAnalysis; 041import org.openimaj.math.matrix.algorithm.pca.ThinSvdPrincipalComponentAnalysis; 042import org.openimaj.math.statistics.distribution.DiagonalMultivariateGaussian; 043import org.openimaj.math.statistics.distribution.MixtureOfGaussians; 044import org.openimaj.math.statistics.distribution.MultivariateGaussian; 045import org.openimaj.util.array.ArrayUtils; 046 047import Jama.Matrix; 048 049import com.jmatio.io.MatFileReader; 050import com.jmatio.io.MatFileWriter; 051import com.jmatio.types.MLArray; 052import com.jmatio.types.MLDouble; 053import com.jmatio.types.MLSingle; 054import com.jmatio.types.MLStructure; 055 056/** 057 * 058 * @author Sina Samangooei (ss@ecs.soton.ac.uk) 059 */ 060public class FVFWCheckPCAGMM { 061 062 private static final String GMM_MATLAB_FILE = "/Users/ss/Experiments/FVFW/data/gmm_512.mat"; 063 private static final String PCA_MATLAB_FILE = "/Users/ss/Experiments/FVFW/data/PCA_64.mat"; 064 private static final String[] FACE_DSIFTS = new String[] { 065 "/Users/ss/Experiments/FVFW/data/Aaron_Eckhart_0001-pdfsift.bin" 066 }; 067 068 public static void main(String[] args) throws IOException { 069 final MixtureOfGaussians mog = loadMoG(new File(GMM_MATLAB_FILE)); 070 final PrincipalComponentAnalysis pca = loadPCA(new File(PCA_MATLAB_FILE)); 071 final FisherVector<float[]> fisher = new FisherVector<float[]>(mog, true, true); 072 for (final String faceFile : FACE_DSIFTS) { 073 final MemoryLocalFeatureList<FloatDSIFTKeypoint> loadDSIFT = MemoryLocalFeatureList.read(new File(faceFile), 074 FloatDSIFTKeypoint.class); 075 projectPCA(loadDSIFT, pca); 076 077 final FloatFV fvec = fisher.aggregate(loadDSIFT); 078 System.out.println(String.format("%s: %s", faceFile, fvec)); 079 System.out.println("Writing..."); 080 081 final File out = new File(faceFile + ".fisher.mat"); 082 final MLArray data = toMLArray(fvec); 083 new MatFileWriter(out, Arrays.asList(data)); 084 } 085 } 086 087 private static MLArray toMLArray(FloatFV fvec) { 088 final MLDouble data = new MLDouble("fisherface", new int[] { fvec.values.length, 1 }); 089 for (int i = 0; i < fvec.values.length; i++) { 090 data.set((double) fvec.values[i], i, 0); 091 } 092 return data; 093 } 094 095 private static void projectPCA( 096 MemoryLocalFeatureList<FloatDSIFTKeypoint> loadDSIFT, 097 PrincipalComponentAnalysis pca) 098 { 099 for (final FloatDSIFTKeypoint kp : loadDSIFT) { 100 kp.descriptor = ArrayUtils.convertToFloat(pca.project(ArrayUtils.convertToDouble(kp.descriptor))); 101 final int nf = kp.descriptor.length; 102 kp.descriptor = Arrays.copyOf(kp.descriptor, nf + 2); 103 kp.descriptor[nf] = (kp.x / 125f) - 0.5f; 104 kp.descriptor[nf + 1] = (kp.y / 160f) - 0.5f; 105 } 106 loadDSIFT.resetVecLength(); 107 } 108 109 static class LoadedPCA extends ThinSvdPrincipalComponentAnalysis { 110 111 public LoadedPCA(Matrix basis, double[] mean) { 112 super(basis.getRowDimension()); 113 this.basis = basis; 114 this.mean = mean; 115 } 116 117 } 118 119 public static PrincipalComponentAnalysis loadPCA(File f) throws IOException { 120 final MatFileReader reader = new MatFileReader(f); 121 final MLSingle mean = (MLSingle) reader.getContent().get("mu"); 122 final MLSingle eigvec = (MLSingle) reader.getContent().get("proj"); 123 final Matrix basis = new Matrix(eigvec.getM(), eigvec.getN()); 124 final double[] meand = new double[eigvec.getN()]; 125 for (int j = 0; j < eigvec.getN(); j++) { 126 // meand[i] = mean.get(i,0); ignore the means 127 meand[j] = 0; 128 for (int i = 0; i < eigvec.getM(); i++) { 129 basis.set(i, j, eigvec.get(i, j)); 130 } 131 } 132 final PrincipalComponentAnalysis ret = new LoadedPCA(basis.transpose(), meand); 133 return ret; 134 } 135 136 public static MixtureOfGaussians loadMoG(File f) throws IOException { 137 final MatFileReader reader = new MatFileReader(f); 138 final MLStructure codebook = (MLStructure) reader.getContent().get("codebook"); 139 140 final MLSingle mean = (MLSingle) codebook.getField("mean"); 141 final MLSingle variance = (MLSingle) codebook.getField("variance"); 142 final MLSingle coef = (MLSingle) codebook.getField("coef"); 143 144 final int n_gaussians = mean.getN(); 145 final int n_dims = mean.getM(); 146 147 final MultivariateGaussian[] ret = new MultivariateGaussian[n_gaussians]; 148 final double[] weights = new double[n_gaussians]; 149 for (int i = 0; i < n_gaussians; i++) { 150 weights[i] = coef.get(i, 0); 151 final DiagonalMultivariateGaussian d = new DiagonalMultivariateGaussian(n_dims); 152 for (int j = 0; j < n_dims; j++) { 153 d.mean.set(0, j, mean.get(j, i)); 154 d.variance[j] = variance.get(j, i); 155 } 156 ret[i] = d; 157 } 158 159 return new MixtureOfGaussians(ret, weights); 160 } 161 162}