001/*******************************************************************************
002 * This software is provided as a supplement to the authors' textbooks on digital
003 *  image processing published by Springer-Verlag in various languages and editions.
004 * Permission to use and distribute this software is granted under the BSD 2-Clause 
005 * "Simplified" License (see http://opensource.org/licenses/BSD-2-Clause). 
006 * Copyright (c) 2006-2016 Wilhelm Burger, Mark J. Burge. All rights reserved. 
007 * Visit http://imagingbook.com for additional details.
008 *******************************************************************************/
009
010package imagingbook.pub.sift.util;
011
012import ij.IJ;
013
014import java.io.File;
015import java.io.FileNotFoundException;
016import java.io.FileReader;
017import java.util.ArrayList;
018import java.util.List;
019import java.util.Locale;
020import java.util.Scanner;
021
022public class SiftKeyfileReaderLowe {
023        
024        public List<SiftKeypoint> readKeypointFile(String filename) {
025                List<SiftKeypoint> keypoints = new ArrayList<SiftKeypoint>();
026                File keyfile = new File(filename);
027
028                Scanner sc = null;
029                try {
030                        FileReader fr = new FileReader(keyfile);
031                        sc = new Scanner(fr);
032                } catch (FileNotFoundException e) {
033                        return null;
034                }
035
036                sc.useLocale(Locale.US);
037
038                try {
039                        int nKeypoints = sc.nextInt();
040                        int descriptorLength = sc.nextInt();
041
042                        IJ.log("keypoints: " + nKeypoints);
043                        IJ.log("descriptorLength: " + descriptorLength);
044
045                        while(sc.hasNext()) {
046                                // read one keypoint:
047                                double ypos = sc.nextDouble();  //NOTE: x/y swapped!
048                                double xpos = sc.nextDouble();
049                                double scale = sc.nextDouble();
050                                double orientation = -sc.nextDouble(); //NOTE: angle in opposite direction!
051                                int[] descriptor = new int[descriptorLength];
052                                for (int i=0; i<descriptorLength; i++) {
053                                        descriptor[i] = sc.nextInt();
054                                }
055                                keypoints.add(new SiftKeypoint(xpos, ypos, scale, orientation, descriptor));
056                        }
057                }
058                catch (Exception e) {
059                        IJ.log("Exception: " + e);
060                }
061                
062                sc.close();
063                return keypoints;
064        }
065}
066
067
068/* Lowe's file format for SIFT keys:
069The file format starts with 2 integers giving the total number of
070keypoints and the length of the descriptor vector for each keypoint
071(128). Then the location of each keypoint in the image is specified by
0724 floating point numbers giving subpixel row and column location,
073scale, and orientation (in radians from -PI to PI).  Obviously, these
074numbers are not invariant to viewpoint, but can be used in later
075stages of processing to check for geometric consistency among matches.
076Finally, the invariant descriptor vector for the keypoint is given as
077a list of 128 integers in range [0,255].  Keypoints from a new image
078can be matched to those from previous images by simply looking for the
079descriptor vector with closest Euclidean distance among all vectors
080from previous images.
081*/
082