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