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;
031
032import org.openimaj.citation.annotation.Reference;
033import org.openimaj.citation.annotation.ReferenceType;
034import org.openimaj.citation.annotation.References;
035import org.openimaj.feature.local.list.LocalFeatureList;
036import org.openimaj.image.FImage;
037import org.openimaj.image.analysis.pyramid.gaussian.GaussianOctave;
038import org.openimaj.image.analysis.pyramid.gaussian.GaussianPyramid;
039import org.openimaj.image.feature.local.descriptor.gradient.SIFTFeatureProvider;
040import org.openimaj.image.feature.local.detector.dog.collector.Collector;
041import org.openimaj.image.feature.local.detector.dog.collector.OctaveKeypointCollector;
042import org.openimaj.image.feature.local.detector.dog.extractor.DominantOrientationExtractor;
043import org.openimaj.image.feature.local.detector.dog.extractor.GradientFeatureExtractor;
044import org.openimaj.image.feature.local.detector.dog.extractor.OrientationHistogramExtractor;
045import org.openimaj.image.feature.local.detector.dog.pyramid.DoGOctaveExtremaFinder;
046import org.openimaj.image.feature.local.detector.pyramid.BasicOctaveExtremaFinder;
047import org.openimaj.image.feature.local.detector.pyramid.OctaveInterestPointFinder;
048import org.openimaj.image.feature.local.keypoints.Keypoint;
049
050/**
051 * <p>
052 * An implementation of Lowe's SIFT: specifically both the
053 * difference-of-Gaussian detector coupled with a SIFT descriptor.
054 * </p>
055 * <p>
056 * This class and its sister options class {@link DoGSIFTEngineOptions} wrap all
057 * the work needed to extract SIFT features into a single place without having
058 * to deal with the setup of pyramid finders, collectors and providers.
059 * </p>
060 * 
061 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk)
062 * 
063 */
064@References(references = {
065                @Reference(
066                                type = ReferenceType.Article,
067                                author = { "David Lowe" },
068                                title = "Distinctive image features from scale-invariant keypoints",
069                                year = "2004",
070                                journal = "IJCV",
071                                pages = { "91", "110" },
072                                month = "January",
073                                number = "2",
074                                volume = "60"),
075                @Reference(
076                                type = ReferenceType.Inproceedings,
077                                author = { "David Lowe" },
078                                title = "Object recognition from local scale-invariant features",
079                                year = "1999",
080                                booktitle = "Proc. of the International Conference on Computer Vision {ICCV}",
081                                pages = { "1150", "1157" }
082                )
083})
084public class DoGSIFTEngine implements Engine<Keypoint, FImage> {
085        DoGSIFTEngineOptions<FImage> options;
086
087        /**
088         * Construct a DoGSIFTEngine with the default options.
089         */
090        public DoGSIFTEngine() {
091                this(new DoGSIFTEngineOptions<FImage>());
092        }
093
094        /**
095         * Construct a DoGSIFTEngine with the given options.
096         * 
097         * @param options
098         *            the options
099         */
100        public DoGSIFTEngine(DoGSIFTEngineOptions<FImage> options) {
101                this.options = options;
102        }
103
104        @Override
105        public LocalFeatureList<Keypoint> findFeatures(FImage image) {
106                final OctaveInterestPointFinder<GaussianOctave<FImage>, FImage> finder =
107                                new DoGOctaveExtremaFinder(new BasicOctaveExtremaFinder(options.magnitudeThreshold,
108                                                options.eigenvalueRatio));
109
110                final Collector<GaussianOctave<FImage>, Keypoint, FImage> collector = new OctaveKeypointCollector<FImage>(
111                                new GradientFeatureExtractor(
112                                                new DominantOrientationExtractor(
113                                                                options.peakThreshold,
114                                                                new OrientationHistogramExtractor(
115                                                                                options.numOriHistBins,
116                                                                                options.scaling,
117                                                                                options.smoothingIterations,
118                                                                                options.samplingSize
119                                                                )
120                                                ),
121                                                new SIFTFeatureProvider(
122                                                                options.numOriBins,
123                                                                options.numSpatialBins,
124                                                                options.valueThreshold,
125                                                                options.gaussianSigma
126                                                ),
127                                                options.magnificationFactor * options.numSpatialBins
128                                )
129                                );
130
131                finder.setOctaveInterestPointListener(collector);
132
133                options.setOctaveProcessor(finder);
134
135                final GaussianPyramid<FImage> pyr = new GaussianPyramid<FImage>(options);
136                pyr.process(image);
137
138                return collector.getFeatures();
139        }
140
141        /**
142         * @return the current options used by the engine
143         */
144        public DoGSIFTEngineOptions<FImage> getOptions() {
145                return options;
146        }
147}