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.feature.local.list.LocalFeatureList;
033import org.openimaj.image.FImage;
034import org.openimaj.image.analysis.pyramid.gaussian.GaussianOctave;
035import org.openimaj.image.analysis.pyramid.gaussian.GaussianPyramid;
036import org.openimaj.image.feature.local.descriptor.gradient.SIFTFeatureProvider;
037import org.openimaj.image.feature.local.detector.dog.collector.Collector;
038import org.openimaj.image.feature.local.detector.dog.collector.OctaveKeypointCollector;
039import org.openimaj.image.feature.local.detector.dog.extractor.AbstractDominantOrientationExtractor;
040import org.openimaj.image.feature.local.detector.dog.extractor.DominantOrientationExtractor;
041import org.openimaj.image.feature.local.detector.dog.extractor.GradientFeatureExtractor;
042import org.openimaj.image.feature.local.detector.dog.extractor.NullOrientationExtractor;
043import org.openimaj.image.feature.local.detector.dog.extractor.OrientationHistogramExtractor;
044import org.openimaj.image.feature.local.detector.pyramid.BasicOctaveGridFinder;
045import org.openimaj.image.feature.local.detector.pyramid.OctaveInterestPointFinder;
046import org.openimaj.image.feature.local.keypoints.Keypoint;
047
048/**
049 * Really basic SIFT extraction on a regular grid of interest points. This is
050 * basically a naive implementation of dense sift. Features can either be
051 * oriented or upright.
052 * 
053 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk)
054 * 
055 */
056public class BasicGridSIFTEngine implements Engine<Keypoint, FImage> {
057        boolean orientate;
058        DoGSIFTEngineOptions<FImage> options;
059
060        /**
061         * Default constructor.
062         * 
063         * @param orientate
064         *            if true oriented features will be produced; false means
065         *            upright features.
066         */
067        public BasicGridSIFTEngine(boolean orientate) {
068                this.options = new DoGSIFTEngineOptions<FImage>();
069                this.orientate = orientate;
070        }
071
072        /**
073         * Construct with the given parameters.
074         * 
075         * @param orientate
076         *            if true oriented features will be produced; false means
077         *            upright features.
078         * @param options
079         *            options for the SIFT extraction
080         */
081        public BasicGridSIFTEngine(boolean orientate, DoGSIFTEngineOptions<FImage> options) {
082                this.orientate = orientate;
083                this.options = options;
084        }
085
086        @Override
087        public LocalFeatureList<Keypoint> findFeatures(FImage image) {
088                final OctaveInterestPointFinder<GaussianOctave<FImage>, FImage> finder = new BasicOctaveGridFinder<GaussianOctave<FImage>, FImage>();
089
090                final AbstractDominantOrientationExtractor ori = orientate ?
091                                new DominantOrientationExtractor(
092                                                options.peakThreshold,
093                                                new OrientationHistogramExtractor(
094                                                                options.numOriHistBins,
095                                                                options.scaling,
096                                                                options.smoothingIterations,
097                                                                options.samplingSize
098                                                )
099                                )
100                                : new NullOrientationExtractor();
101
102                final Collector<GaussianOctave<FImage>, Keypoint, FImage> collector = new OctaveKeypointCollector<FImage>(
103                                new GradientFeatureExtractor(
104                                                ori,
105                                                new SIFTFeatureProvider(
106                                                                options.numOriBins,
107                                                                options.numSpatialBins,
108                                                                options.valueThreshold,
109                                                                options.gaussianSigma
110                                                ),
111                                                options.magnificationFactor * options.numSpatialBins
112                                )
113                                );
114
115                finder.setOctaveInterestPointListener(collector);
116
117                options.setOctaveProcessor(finder);
118
119                final GaussianPyramid<FImage> pyr = new GaussianPyramid<FImage>(options);
120                pyr.process(image);
121
122                return collector.getFeatures();
123        }
124}