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.tools.cbir; 031 032import java.io.File; 033import java.io.IOException; 034import java.util.ArrayList; 035import java.util.List; 036import java.util.regex.Pattern; 037 038import org.kohsuke.args4j.CmdLineException; 039import org.kohsuke.args4j.CmdLineParser; 040import org.kohsuke.args4j.Option; 041import org.openimaj.feature.local.LocalFeature; 042import org.openimaj.feature.local.LocalFeatureExtractor; 043import org.openimaj.image.MBFImage; 044import org.openimaj.image.feature.local.aggregate.VLAD; 045import org.openimaj.image.indexing.vlad.VLADIndexerDataBuilder; 046import org.openimaj.io.IOUtils; 047 048/** 049 * Tool to build a {@link VLAD} object and serialise it to a file. 050 * 051 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk) 052 * 053 */ 054public class VLADBuilder { 055 @Option( 056 name = "--extractor-file", 057 aliases = "-ef", 058 required = true, 059 usage = "the local feature extractor used to generate the input features") 060 protected File extractorFile; 061 062 @Option( 063 name = "--features-dir", 064 required = true, 065 usage = "directory of the files containing the input local features (one per image)") 066 protected File localFeaturesDir; 067 068 @Option( 069 name = "--features-regex", 070 required = false, 071 usage = "regular expression to match the feature filenames against") 072 protected String regex; 073 074 @Option( 075 name = "--normalise", 076 aliases = "-norm", 077 required = false, 078 usage = "should the resultant VLAD features be l2 normalised?") 079 protected boolean normalise = false; 080 081 @Option( 082 name = "--sample-proportion", required = false, 083 usage = "the proportion of features to sample for the clustering the VLAD centroids") 084 protected float sampleProp = 0.1f; 085 086 @Option( 087 name = "--num-vlad-centroids", 088 aliases = "-n", 089 required = false, 090 usage = "the number of centroids for VLAD (16~64). Defaults to 64.") 091 protected int numVladCentroids = 64; 092 093 @Option( 094 name = "--num-iterations", 095 aliases = "-ni", 096 required = false, 097 usage = "the number of clustering iterations (~100). Defaults to 100.") 098 protected int numIterations = 100; 099 100 @Option( 101 name = "--output", 102 aliases = "-o", 103 required = true, 104 usage = "the output file") 105 protected File output; 106 107 /** 108 * Main method 109 * 110 * @param args 111 * arguments 112 * @throws IOException 113 * if an error occurs during reading or writing 114 */ 115 public static void main(String[] args) throws IOException { 116 final VLADBuilder builder = new VLADBuilder(); 117 final CmdLineParser parser = new CmdLineParser(builder); 118 119 try { 120 parser.parseArgument(args); 121 } catch (final CmdLineException e) { 122 System.err.println(e.getMessage()); 123 System.err.println("Usage: java -jar CBIRTool.jar VLADBuilder [options]"); 124 parser.printUsage(System.err); 125 return; 126 } 127 128 final LocalFeatureExtractor<LocalFeature<?, ?>, MBFImage> extractor = IOUtils.readFromFile(builder.extractorFile); 129 130 final List<File> localFeatures = new ArrayList<File>(); 131 getInputFiles(localFeatures, builder.localFeaturesDir, 132 builder.regex == null ? null : Pattern.compile(builder.regex)); 133 134 final VLADIndexerDataBuilder vladBuilder = new VLADIndexerDataBuilder(extractor, localFeatures, 135 builder.normalise, 136 builder.numVladCentroids, builder.numIterations, 0, 0, 0, builder.sampleProp, 1, null); 137 138 final VLAD<float[]> vlad = vladBuilder.buildVLAD(); 139 140 IOUtils.writeToFile(vlad, builder.output); 141 } 142 143 protected static void getInputFiles(List<File> localFeatures, File dir, Pattern pattern) { 144 for (final File f : dir.listFiles()) { 145 if (f.isDirectory()) { 146 getInputFiles(localFeatures, f, pattern); 147 } else { 148 if (pattern == null || pattern.matcher(f.getName()).matches()) { 149 localFeatures.add(f); 150 } 151 } 152 } 153 } 154}