View Javadoc

1   /**
2    * Copyright (c) 2011, The University of Southampton and the individual contributors.
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without modification,
6    * are permitted provided that the following conditions are met:
7    *
8    *   * 	Redistributions of source code must retain the above copyright notice,
9    * 	this list of conditions and the following disclaimer.
10   *
11   *   *	Redistributions in binary form must reproduce the above copyright notice,
12   * 	this list of conditions and the following disclaimer in the documentation
13   * 	and/or other materials provided with the distribution.
14   *
15   *   *	Neither the name of the University of Southampton nor the names of its
16   * 	contributors may be used to endorse or promote products derived from this
17   * 	software without specific prior written permission.
18   *
19   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21   * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
23   * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26   * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29   */
30  package org.openimaj.workinprogress;
31  
32  import java.io.File;
33  
34  import org.openimaj.feature.local.list.LocalFeatureList;
35  import org.openimaj.feature.local.list.MemoryLocalFeatureList;
36  import org.openimaj.feature.local.matcher.FastBasicKeypointMatcher;
37  import org.openimaj.feature.local.matcher.consistent.ConsistentLocalFeatureMatcher2d;
38  import org.openimaj.image.DisplayUtilities;
39  import org.openimaj.image.FImage;
40  import org.openimaj.image.feature.local.engine.DoGSIFTEngine;
41  import org.openimaj.image.feature.local.keypoints.Keypoint;
42  import org.openimaj.image.processing.resize.ResizeProcessor;
43  import org.openimaj.math.geometry.point.Point2d;
44  import org.openimaj.math.geometry.point.Point2dImpl;
45  import org.openimaj.math.geometry.transforms.estimation.RobustAffineTransformEstimator;
46  import org.openimaj.video.capture.VideoCapture;
47  
48  public class Snap {
49  	MemoryLocalFeatureList<Keypoint> mapData = new MemoryLocalFeatureList<Keypoint>();
50  	File[] mapKeypointFiles = {
51  			new File("/Users/jon/Consulting/MapSnapper/map_data/MAP_DATA_2K/NY42.key"),
52  			new File("/Users/jon/Consulting/MapSnapper/map_data/MAP_DATA_2K/NY44.key"),
53  			new File("/Users/jon/Consulting/MapSnapper/map_data/MAP_DATA_2K/NY46.key")
54  	};
55  	int[] baseNorthing = { 200, 400, 600 };
56  	int[] baseEasting = { 400, 400, 400 };
57  
58  	// scale_factor determines how many pixels correspond to one grid square
59  	int scaleFactor = 100;
60  
61  	// map_dimension is the height/width of each map tile (they must all be the
62  	// same size)
63  	int mapDimension = 2000;
64  	private DoGSIFTEngine engine;
65  	private ConsistentLocalFeatureMatcher2d<Keypoint> matcher;
66  
67  	public Snap() {
68  		loadMapData();
69  
70  		engine = new DoGSIFTEngine();
71  		// engine.getOptions().setDoubleInitialImage(false);
72  
73  		final FastBasicKeypointMatcher<Keypoint> innerMatcher = new FastBasicKeypointMatcher<Keypoint>(8);
74  		matcher = new ConsistentLocalFeatureMatcher2d<Keypoint>(innerMatcher);
75  		final RobustAffineTransformEstimator estimator = new RobustAffineTransformEstimator(0.5);
76  		matcher.setFittingModel(estimator);
77  		matcher.setModelFeatures(mapData);
78  
79  	}
80  
81  	protected void loadMapData() {
82  		for (int i = 0; i < mapKeypointFiles.length; i++) {
83  			try {
84  				// read keypoints for current tile
85  				final MemoryLocalFeatureList<Keypoint> map = MemoryLocalFeatureList.read(mapKeypointFiles[i],
86  						Keypoint.class);
87  
88  				// loop through each keypoint in the tile and
89  				// adjust its position, so that the keypoints
90  				// x and y position is its true OSGB grid ref!
91  				for (final Keypoint k : map) {
92  					final int east = baseEasting[i] + Math.round(10.0f * (k.getX() / scaleFactor));
93  					final int north = baseNorthing[i]
94  							+ Math.round(10.0f * ((mapDimension - k.getY()) / scaleFactor)); // different
95  					// coord systems!!
96  
97  					k.setX(east);
98  					k.setY(north);
99  				}
100 
101 				mapData.addAll(map);
102 			} catch (final Exception ex) {
103 				System.out.println(ex);
104 				System.exit(1);
105 			}
106 		}
107 	}
108 
109 	/**
110 	 * Estimate a grid reference from an image using the MapSnapper algorithm.
111 	 * 
112 	 * @param image
113 	 *
114 	 * @return grid reference string
115 	 * @throws Exception
116 	 */
117 	public String getGridRef(FImage image) throws Exception {
118 		final LocalFeatureList<Keypoint> keys = engine.findFeatures(image);
119 		if (matcher.findMatches(keys)) {
120 			System.out.println("Done! -- Found Match");
121 
122 			final Point2d coords = matcher.getModel().predict(
123 					new Point2dImpl(image.width / 2.0f, image.height / 2.0f));
124 
125 			final int east = Math.round(coords.getX());
126 			final int north = Math.round(coords.getY());
127 
128 			final Object[] gr = { "NY", east, north };
129 			return String.format("%2s%3d%3d\n", gr);
130 		} else {
131 			return "Match Not Found";
132 		}
133 	}
134 
135 	public static void main(String[] args) throws Exception {
136 		final Snap snap = new Snap();
137 		final VideoCapture vc = new VideoCapture(640, 480);
138 
139 		while (true) {
140 			final FImage img = vc.getNextFrame().flatten();
141 			DisplayUtilities.displayName(img, "Live Video");
142 			final FImage patch = ResizeProcessor.resample(img, 160, 120);// .extractCenter(120,
143 			// 120);
144 			final String res = snap.getGridRef(patch);
145 			if (!res.contains("Not"))
146 				System.out.println(res);
147 		}
148 	}
149 }