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.local.list.LocalFeatureList; 037import org.openimaj.feature.local.list.MemoryLocalFeatureList; 038import org.openimaj.image.FImage; 039import org.openimaj.image.ImageUtilities; 040import org.openimaj.image.analysis.pyramid.SimplePyramid; 041import org.openimaj.image.feature.dense.gradient.dsift.ApproximateDenseSIFT; 042import org.openimaj.image.feature.dense.gradient.dsift.ByteDSIFTKeypoint; 043import org.openimaj.image.feature.dense.gradient.dsift.DenseSIFT; 044import org.openimaj.image.feature.dense.gradient.dsift.FloatDSIFTKeypoint; 045import org.openimaj.io.IOUtils; 046import org.openimaj.util.function.Operation; 047import org.openimaj.util.parallel.Parallel; 048 049public class FVFWDSift { 050 static interface DSFactory { 051 DenseSIFT create(); 052 } 053 054 private static void extractPDSift(final File indir, final File outDir, final DSFactory factory) throws IOException 055 { 056 Parallel.forEach(Arrays.asList(indir.listFiles()), new Operation<File>() { 057 058 @Override 059 public void perform(File dir) { 060 try { 061 if (!dir.isDirectory()) 062 return; 063 064 final DenseSIFT sift = factory.create(); 065 066 for (final File imgfile : dir.listFiles()) { 067 if (!imgfile.getName().endsWith(".jpg")) 068 continue; 069 070 final File outfile = new File(outDir, imgfile.getAbsolutePath().replace(indir.getAbsolutePath(), 071 "").replace(".jpg", ".bin")); 072 outfile.getParentFile().mkdirs(); 073 074 final FImage image = ImageUtilities.readF(imgfile); 075 076 final SimplePyramid<FImage> pyr = new SimplePyramid<FImage>((float) Math.sqrt(2), 5); 077 pyr.processImage(image); 078 079 final LocalFeatureList<FloatDSIFTKeypoint> allKeys = new MemoryLocalFeatureList<FloatDSIFTKeypoint>(); 080 for (final FImage img : pyr) { 081 sift.analyseImage(img); 082 083 final double scale = 160.0 / img.height; 084 final LocalFeatureList<ByteDSIFTKeypoint> kps = sift.getByteKeypoints(); 085 for (final ByteDSIFTKeypoint kp : kps) { 086 kp.x *= scale; 087 kp.y *= scale; 088 089 final float[] descriptor = new float[128]; 090 float sumsq = 0; 091 092 // reorder to make comparision with matlab 093 // easier; add offset 094 for (int i = 0; i < 16; i++) { 095 descriptor[i * 8] = kp.descriptor[i * 8] + 128; 096 descriptor[i * 8 + 1] = kp.descriptor[i * 8 + 7] + 128; 097 descriptor[i * 8 + 2] = kp.descriptor[i * 8 + 6] + 128; 098 descriptor[i * 8 + 3] = kp.descriptor[i * 8 + 5] + 128; 099 descriptor[i * 8 + 4] = kp.descriptor[i * 8 + 4] + 128; 100 descriptor[i * 8 + 5] = kp.descriptor[i * 8 + 3] + 128; 101 descriptor[i * 8 + 6] = kp.descriptor[i * 8 + 2] + 128; 102 descriptor[i * 8 + 7] = kp.descriptor[i * 8 + 1] + 128; 103 } 104 // rootsift 105 for (int i = 0; i < 128; i++) { 106 descriptor[i] = (float) Math.sqrt(descriptor[i]); 107 sumsq += descriptor[i] * descriptor[i]; 108 } 109 sumsq = (float) Math.sqrt(sumsq); 110 final float norm = 1f / Math.max(Float.MIN_NORMAL, sumsq); 111 for (int i = 0; i < 128; i++) { 112 descriptor[i] *= norm; 113 } 114 115 allKeys.add(new FloatDSIFTKeypoint(kp.x, kp.y, descriptor, kp.energy)); 116 } 117 } 118 119 IOUtils.writeBinary(outfile, allKeys); 120 121 System.out.println(imgfile + " " + allKeys.size()); 122 } 123 } catch (final Exception e) { 124 e.printStackTrace(); 125 System.err.println(e); 126 } 127 } 128 }); 129 } 130 131 /** 132 * @param args 133 * @throws IOException 134 */ 135 public static void main(String[] args) throws IOException { 136 final DSFactory factory = new DSFactory() { 137 @Override 138 public DenseSIFT create() { 139 return new ApproximateDenseSIFT(1, 6); 140 } 141 }; 142 143 extractPDSift( 144 new File("/Volumes/Raid/face_databases/lfw-centre-affine-matlab/"), 145 new File("/Volumes/Raid/face_databases/lfw-centre-affine-pdsift/"), 146 factory); 147 } 148 149}