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.image.feature.local.engine.asift;
031
032import java.util.Map;
033
034import org.openimaj.citation.annotation.Reference;
035import org.openimaj.citation.annotation.ReferenceType;
036import org.openimaj.feature.local.list.LocalFeatureList;
037import org.openimaj.feature.local.list.MemoryLocalFeatureList;
038import org.openimaj.image.FImage;
039import org.openimaj.image.feature.local.affine.AffineSimulationExtractor;
040import org.openimaj.image.feature.local.affine.AffineSimulationKeypoint;
041import org.openimaj.image.feature.local.affine.BasicASIFT;
042import org.openimaj.image.feature.local.engine.DoGSIFTEngine;
043import org.openimaj.image.feature.local.engine.DoGSIFTEngineOptions;
044import org.openimaj.image.feature.local.engine.Engine;
045import org.openimaj.image.feature.local.keypoints.Keypoint;
046import org.openimaj.image.processing.transform.AffineParams;
047
048/**
049 * An {@link Engine} for ASIFT.
050 *
051 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk)
052 *
053 */
054@Reference(
055                type = ReferenceType.Article,
056                author = { "Morel, Jean-Michel", "Yu, Guoshen" },
057                title = "{ASIFT: A New Framework for Fully Affine Invariant Image Comparison}",
058                year = "2009",
059                journal = "SIAM J. Img. Sci.",
060                publisher = "Society for Industrial and Applied Mathematics")
061public class ASIFTEngine implements Engine<AffineSimulationKeypoint, FImage> {
062        protected AffineSimulationExtractor<LocalFeatureList<Keypoint>, Keypoint, FImage, Float> asift;
063        protected int nTilts = 5;
064
065        /**
066         * Construct using 5 tilt levels and no initial double-sizing. The default
067         * parameters for the internal {@link DoGSIFTEngine} are used.
068         */
069        public ASIFTEngine() {
070                this(false);
071        }
072
073        /**
074         * Construct using 5 tilt levels with optional initial double-sizing. The
075         * default parameters for the internal {@link DoGSIFTEngine} are used.
076         *
077         * @param hires
078         *            should the image should be double sized as a first step
079         */
080        public ASIFTEngine(boolean hires) {
081                asift = new BasicASIFT(hires);
082        }
083
084        /**
085         * Construct using given number of tilt levels with optional initial
086         * double-sizing. The default parameters for the internal
087         * {@link DoGSIFTEngine} are used.
088         *
089         * @param hires
090         *            should the image should be double sized as a first step
091         * @param nTilts
092         *            number of tilt levels
093         */
094        public ASIFTEngine(boolean hires, int nTilts) {
095                asift = new BasicASIFT(hires);
096                this.nTilts = nTilts;
097        }
098
099        /**
100         * Construct using 5 tilt levels and the given parameters for the internal
101         * {@link DoGSIFTEngine}.
102         *
103         * @param opts
104         *            parameters for the internal {@link DoGSIFTEngine}.
105         */
106        public ASIFTEngine(DoGSIFTEngineOptions<FImage> opts) {
107                asift = new BasicASIFT(opts);
108        }
109
110        /**
111         * Construct using the given numbe of tilt levels and parameters for the
112         * internal {@link DoGSIFTEngine}.
113         *
114         * @param opts
115         *            parameters for the internal {@link DoGSIFTEngine}.
116         * @param nTilts
117         *            number of tilt levels
118         */
119        public ASIFTEngine(DoGSIFTEngineOptions<FImage> opts, int nTilts) {
120                asift = new BasicASIFT(opts);
121                this.nTilts = nTilts;
122        }
123
124        /**
125         * Find the features as a list of {@link Keypoint} objects
126         *
127         * @param image
128         *            the image
129         * @return the detected features
130         */
131        public LocalFeatureList<Keypoint> findKeypoints(FImage image) {
132                asift.detectFeatures(image, nTilts);
133                return asift.getFeatures();
134        }
135
136        /**
137         * Find the features of a single simulation as a list of {@link Keypoint}
138         * objects
139         *
140         * @param image
141         *            the image
142         * @param params
143         *            the simulation parameters
144         * @return the detected features
145         */
146        public LocalFeatureList<Keypoint> findKeypoints(FImage image,
147                        AffineParams params)
148                        {
149                return asift.detectFeatures(image, params);
150                        }
151
152        /**
153         * Find the features and return the resultant features in a per-simulation
154         * format.
155         *
156         * @param image
157         *            the image
158         * @return the features
159         */
160        public Map<AffineParams, LocalFeatureList<Keypoint>> findKeypointsMapped(FImage image)
161        {
162                asift.detectFeatures(image, nTilts);
163                return asift.getKeypointsMap();
164        }
165
166        @Override
167        public LocalFeatureList<AffineSimulationKeypoint> findFeatures(FImage image) {
168                asift.detectFeatures(image, nTilts);
169                final Map<AffineParams, LocalFeatureList<Keypoint>> keypointMap = asift.getKeypointsMap();
170                final LocalFeatureList<AffineSimulationKeypoint> affineSimulationList = new MemoryLocalFeatureList<AffineSimulationKeypoint>();
171                for (final AffineParams params : asift.simulationOrder) {
172                        for (final Keypoint k : keypointMap.get(params)) {
173                                affineSimulationList.add(new AffineSimulationKeypoint(k, params, asift.simulationOrder.indexOf(params)));
174                        }
175                }
176                return affineSimulationList;
177        }
178}