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.clusterquantiser;
031
032import java.io.File;
033import java.io.IOException;
034import java.io.InputStream;
035import java.util.Arrays;
036import java.util.Scanner;
037
038/**
039 * Utility functions for reading lowe-style keypoint files and the (similar) files produced by the MSER and oxford tools
040 * 
041 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk)
042 * @author Sina Samangooei (ss@ecs.soton.ac.uk)
043 */
044public class AsciiInterestPoint {
045        /**
046         * Number of location elements for ellipse files
047         */
048        public static final int NUM_ELLIPSE_LOC_FEATS = 5;
049        /**
050         * Number of location elements for circle files
051         */
052        public static final int NUM_CIRCLE_LOC_FEATS = 4;
053        /**
054         * Number of location features for ASIFT files
055         */
056        public static final int NUM_ASIFT_LOC_FEATS = 7;
057        
058        /**
059         * Read the header
060         * 
061         * @param file
062         * @param reverse
063         * @return the header info
064         * @throws IOException
065         */
066        public static Header readHeader(File file, boolean reverse) throws IOException {
067                Scanner scanner = null;
068                try {
069                        scanner = new Scanner(file);
070                        return readHeader(scanner, reverse);
071                } finally {
072                        scanner.close();
073                }
074        }
075        
076        /**
077         * Read the data
078         * 
079         * @param file
080         * @param reverse
081         * @param nLocationFeatures
082         * @return the data
083         * @throws IOException
084         */
085        public static byte [][] readData(File file, boolean reverse, int nLocationFeatures) throws IOException {
086                Scanner scanner = null;
087                
088                try {
089                        scanner = new Scanner(file);
090                        Header header = readHeader(scanner, reverse);                   
091                        return readData(scanner, header, nLocationFeatures);
092                } finally {
093                        scanner.close();
094                }
095        }
096        
097        /**
098         * Read the data
099         * @param file
100         * @param indices
101         * @param reverse
102         * @param nLocationFeatures
103         * @return the data
104         * @throws IOException
105         */
106        public static byte  [][] readData(File file, int [] indices, boolean reverse, int nLocationFeatures) throws IOException {
107                Scanner scanner = null;
108
109                try {
110                        byte [][] data = new byte[indices.length][];
111                        
112                        scanner = new Scanner(file);
113                        
114                        Arrays.sort(indices);
115                
116                        Header header = readHeader(scanner, reverse);
117                
118                        if (indices[indices.length-1] >= header.nfeatures)
119                                throw new IllegalArgumentException("Invalid index");
120                
121                        int currentIdx = 0;
122                        for (int i=0; i<=indices[indices.length-1]; i++) {
123                                if (i == indices[currentIdx]) {
124                                        data[currentIdx] = readLine(scanner, header, nLocationFeatures);
125                                        currentIdx++;
126                                } else {
127                                        skipLine(scanner, header, nLocationFeatures);
128                                }
129                        }
130                        return data;
131                } finally {
132                        scanner.close();
133                }
134        }
135        
136        /**
137         * Read the file
138         * @param source
139         * @param reverse
140         * @param nLocationFeatures
141         * @return the data
142         * @throws IOException
143         */
144        public static FeatureFile read(InputStream source, boolean reverse,int nLocationFeatures) throws IOException {
145                
146                Scanner scanner = null;
147                try {
148                        scanner = new Scanner(source);
149                        Header header = readHeader(scanner, reverse);
150                        
151                
152                        
153                        byte[][] data = new byte[header.nfeatures][header.ndims];
154                        String[] locations = new String[header.nfeatures];
155                
156                        for (int i=0; i<header.nfeatures; i++) {
157                                String location = "";
158                                for (int j=0; j<nLocationFeatures; j++)
159                                        location += scanner.nextFloat() + " ";
160                                locations[i] = location;
161                        
162                                for (int j=0; j<header.ndims; j++)
163                                        data[i][j] = (byte)(scanner.nextInt()-128);
164                        }
165                        FeatureFile ff = new MemoryFeatureFile(data,locations);
166                        return ff;
167                } finally {
168                        scanner.close();
169                }
170        }
171        
172        /**
173         * Read the file
174         * @param file
175         * @param reverse
176         * @param nLocationFeatures
177         * @return the data
178         * @throws IOException
179         */
180        public static FeatureFile read(File file, boolean reverse, int nLocationFeatures) throws IOException {
181                Scanner scanner = null;
182                
183                try {
184                        scanner = new Scanner(file);
185                        Header header = readHeader(scanner, reverse);
186                
187                        
188                        byte[][] data = new byte[header.nfeatures][header.ndims];
189                        String[] locations = new String[header.nfeatures];
190                
191                        for (int i=0; i<header.nfeatures; i++) {
192                                String location = "";
193                                for (int j=0; j<nLocationFeatures; j++)
194                                        location += scanner.nextFloat() + " ";
195                                locations[i] = location;
196                        
197                                for (int j=0; j<header.ndims; j++)
198                                        data[i][j] = (byte) (scanner.nextInt()-128);
199                        }
200                        FeatureFile ff = new MemoryFeatureFile(data,locations);
201                        return ff;
202                } finally {
203                        scanner.close();
204                }
205        }
206        
207        protected static Header readHeader(Scanner scanner, boolean reverse) throws IOException {
208                Header header = new Header();
209                
210                if (reverse) {
211                        header.ndims = scanner.nextInt();
212                        header.nfeatures = scanner.nextInt();
213                } else {
214                        header.nfeatures = scanner.nextInt();
215                        header.ndims = scanner.nextInt();
216                }
217                
218                return header;
219        }
220        
221        protected static byte [][] readData(Scanner scanner, Header header, int nLocationFeatures) {
222                byte [][] data = new byte[header.nfeatures][header.ndims];
223                
224                for (int i=0; i<header.nfeatures; i++) {        
225                        data[i] = readLine(scanner, header, nLocationFeatures);
226                }
227                
228                return data;
229        }
230        
231        protected static byte [] readLine(Scanner scanner, Header header, int nLocationFeatures) {
232                byte [] data = new byte[header.ndims];
233                
234                //skip the location data
235                for (int j=0; j<nLocationFeatures; j++)
236                        scanner.nextFloat();
237                        
238                for (int j=0; j<header.ndims; j++)
239                        data[j] = (byte) (scanner.nextInt() - 128);
240                
241                return data;
242        }
243        
244        protected static void skipLine(Scanner scanner, Header header, int nLocationFeatures) {
245                //skip the location data
246                for (int j=0; j<nLocationFeatures; j++)
247                        scanner.next();
248//                      scanner.nextFloat();
249
250                for (int j=0; j<header.ndims; j++)
251                        scanner.next();
252//                      scanner.nextInt();
253        }
254
255        
256}