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; 034 035import org.openimaj.demos.FVFWDSift.DSFactory; 036import org.openimaj.feature.FloatFV; 037import org.openimaj.feature.local.list.LocalFeatureList; 038import org.openimaj.feature.local.list.MemoryLocalFeatureList; 039import org.openimaj.image.FImage; 040import org.openimaj.image.ImageUtilities; 041import org.openimaj.image.analysis.pyramid.SimplePyramid; 042import org.openimaj.image.feature.dense.gradient.dsift.ApproximateDenseSIFT; 043import org.openimaj.image.feature.dense.gradient.dsift.ByteDSIFTKeypoint; 044import org.openimaj.image.feature.dense.gradient.dsift.DenseSIFT; 045import org.openimaj.image.feature.dense.gradient.dsift.FloatDSIFTKeypoint; 046import org.openimaj.image.feature.local.aggregate.FisherVector; 047import org.openimaj.io.IOUtils; 048import org.openimaj.math.matrix.algorithm.pca.PrincipalComponentAnalysis; 049import org.openimaj.math.statistics.distribution.MixtureOfGaussians; 050import org.openimaj.util.array.ArrayUtils; 051import org.openimaj.util.function.Operation; 052import org.openimaj.util.parallel.Parallel; 053 054import scala.actors.threadpool.Arrays; 055 056public class FVFWFVEncodeMatlab { 057 /** 058 * @param args 059 * @throws IOException 060 */ 061 @SuppressWarnings("unchecked") 062 public static void main(String[] args) throws IOException { 063 final MixtureOfGaussians gmm = FVFWCheckPCAGMM.loadMoG(new File( 064 "/Users/jon/Downloads/data/lfw_aligned/SIFT_1pix_PCA64_GMM512/codebooks/1/gmm_512.mat")); 065 final PrincipalComponentAnalysis pca = FVFWCheckPCAGMM.loadPCA(new File( 066 "/Users/jon/Downloads/data/lfw_aligned/SIFT_1pix_PCA64_GMM512/codebooks/1/PCA_64.mat")); 067 068 final FisherVector<float[]> fisher = new FisherVector<float[]>(gmm, true, true); 069 070 final DSFactory factory = new DSFactory() { 071 @Override 072 public DenseSIFT create() { 073 return new ApproximateDenseSIFT(1, 6); 074 } 075 }; 076 077 final File indir = new File("/Volumes/Raid/face_databases/lfw-centre-affine-matlab/"); 078 final File outdir = new File("/Volumes/Raid/face_databases/lfw-centre-affine-matlab-fisher/"); 079 080 Parallel.forEach(Arrays.asList(indir.listFiles()), new Operation<File>() { 081 @Override 082 public void perform(File dir) { 083 if (dir.isDirectory()) { 084 final DenseSIFT sift = factory.create(); 085 086 for (final File f : dir.listFiles()) { 087 if (f.getName().endsWith(".jpg")) { 088 try { 089 final File outfile = new File(outdir, f.getAbsolutePath().replace( 090 indir.getAbsolutePath(), "").replace(".jpg", ".bin")); 091 outfile.getParentFile().mkdirs(); 092 093 if (outfile.exists()) 094 continue; 095 096 System.out.println(f); 097 098 final LocalFeatureList<FloatDSIFTKeypoint> features = computeFeatures(f, pca, sift); 099 100 final FloatFV fv = fisher.aggregate(features); 101 IOUtils.writeBinary(outfile, fv); 102 } catch (final Exception e) { 103 e.printStackTrace(); 104 } 105 } 106 } 107 } 108 } 109 110 private LocalFeatureList<FloatDSIFTKeypoint> computeFeatures(File f, PrincipalComponentAnalysis pca, 111 DenseSIFT sift) throws IOException 112 { 113 final FImage image = ImageUtilities.readF(f); 114 115 final SimplePyramid<FImage> pyr = new SimplePyramid<FImage>((float) Math.sqrt(2), 5); 116 pyr.processImage(image); 117 118 final LocalFeatureList<FloatDSIFTKeypoint> allKeys = new MemoryLocalFeatureList<FloatDSIFTKeypoint>(); 119 for (final FImage img : pyr) { 120 sift.analyseImage(img); 121 122 final double scale = 160.0 / img.height; 123 final LocalFeatureList<ByteDSIFTKeypoint> kps = sift.getByteKeypoints(); 124 for (final ByteDSIFTKeypoint kp : kps) { 125 kp.x = (float) ((kp.x + 1) * scale); 126 kp.y = (float) ((kp.y + 1) * scale); 127 128 float[] descriptor = new float[128]; 129 float sumsq = 0; 130 131 // reorder to make comparision with matlab 132 // easier; add offset 133 for (int i = 0; i < 16; i++) { 134 descriptor[i * 8] = kp.descriptor[i * 8] + 128; 135 descriptor[i * 8 + 1] = kp.descriptor[i * 8 + 7] + 128; 136 descriptor[i * 8 + 2] = kp.descriptor[i * 8 + 6] + 128; 137 descriptor[i * 8 + 3] = kp.descriptor[i * 8 + 5] + 128; 138 descriptor[i * 8 + 4] = kp.descriptor[i * 8 + 4] + 128; 139 descriptor[i * 8 + 5] = kp.descriptor[i * 8 + 3] + 128; 140 descriptor[i * 8 + 6] = kp.descriptor[i * 8 + 2] + 128; 141 descriptor[i * 8 + 7] = kp.descriptor[i * 8 + 1] + 128; 142 } 143 // rootsift 144 for (int i = 0; i < 128; i++) { 145 descriptor[i] = (float) Math.sqrt(descriptor[i]); 146 sumsq += descriptor[i] * descriptor[i]; 147 } 148 sumsq = (float) Math.sqrt(sumsq); 149 final float norm = 1f / Math.max(Float.MIN_NORMAL, sumsq); 150 for (int i = 0; i < 128; i++) { 151 descriptor[i] *= norm; 152 } 153 154 // PCA 155 descriptor = ArrayUtils.convertToFloat(pca.project(ArrayUtils.convertToDouble(descriptor))); 156 157 // Augment 158 final int nf = descriptor.length; 159 descriptor = Arrays.copyOf(descriptor, nf + 2); 160 descriptor[nf] = (kp.x / 125f) - 0.5f; 161 descriptor[nf + 1] = (kp.y / 160f) - 0.5f; 162 163 allKeys.add(new FloatDSIFTKeypoint(kp.x, kp.y, descriptor, kp.energy)); 164 } 165 } 166 return allKeys; 167 } 168 169 }); 170 171 FVFWExperiment.main(null); 172 } 173}