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}