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.MBFImage; 038import org.openimaj.image.analysis.pyramid.gaussian.GaussianOctave; 039import org.openimaj.image.analysis.pyramid.gaussian.GaussianPyramid; 040import org.openimaj.image.colour.ColourSpace; 041import org.openimaj.image.feature.local.descriptor.gradient.SIFTFeatureProvider; 042import org.openimaj.image.feature.local.detector.dog.collector.Collector; 043import org.openimaj.image.feature.local.detector.dog.collector.OctaveKeypointCollector; 044import org.openimaj.image.feature.local.detector.dog.extractor.ColourGradientFeatureExtractor; 045import org.openimaj.image.feature.local.detector.dog.extractor.DominantOrientationExtractor; 046import org.openimaj.image.feature.local.detector.dog.extractor.OrientationHistogramExtractor; 047import org.openimaj.image.feature.local.detector.dog.pyramid.FirstBandDoGOctaveExtremaFinder; 048import org.openimaj.image.feature.local.detector.pyramid.BasicOctaveExtremaFinder; 049import org.openimaj.image.feature.local.detector.pyramid.OctaveInterestPointFinder; 050import org.openimaj.image.feature.local.keypoints.Keypoint; 051 052/** 053 * The {@link DoGSIFTEngine} extended to colour images (aka Colour-SIFT). 054 * <p> 055 * The {@link DoGColourSIFTEngine} creates a luminance image from which to apply 056 * the difference-of-Gaussian interest point detection algorithm, but extracts 057 * the actual SIFT features from the bands of the input image directly. This 058 * means that the type of Colour-SIFT feature is controlled directly by the 059 * colour-space of the input image; for example if an RGB image is given as 060 * input, then the feature will be standard RGB-SIFT. 061 * 062 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk) 063 */ 064@References(references = { 065 @Reference( 066 type = ReferenceType.Article, 067 author = { "Burghouts, Gertjan J.", "Geusebroek, Jan-Mark" }, 068 title = "Performance evaluation of local colour invariants", 069 year = "2009", 070 journal = "Comput. Vis. Image Underst.", 071 pages = { "48", "", "62" }, 072 url = "http://dx.doi.org/10.1016/j.cviu.2008.07.003", 073 month = "jan", 074 number = "1", 075 publisher = "Elsevier Science Inc.", 076 volume = "113", 077 customData = { 078 "issn", "1077-3142", 079 "numpages", "15", 080 "doi", "10.1016/j.cviu.2008.07.003", 081 "acmid", "1465842", 082 "address", "New York, NY, USA", 083 "keywords", "Colour, Local descriptors, SIFT" 084 } 085 ), 086 @Reference( 087 type = ReferenceType.Article, 088 author = { "van de Sande, K. E. A.", "Gevers, T.", "Snoek, C. G. M." }, 089 title = "Evaluating Color Descriptors for Object and Scene Recognition", 090 year = "2010", 091 journal = "IEEE Transactions on Pattern Analysis and Machine Intelligence", 092 pages = { "1582", "", "1596" }, 093 url = "http://www.science.uva.nl/research/publications/2010/vandeSandeTPAMI2010", 094 number = "9", 095 volume = "32" 096 ) 097}) 098public class DoGColourSIFTEngine implements Engine<Keypoint, MBFImage> { 099 DoGSIFTEngineOptions<MBFImage> options; 100 101 /** 102 * Construct with the default values for the {@link DoGSIFTEngineOptions}. 103 */ 104 public DoGColourSIFTEngine() { 105 this(new DoGSIFTEngineOptions<MBFImage>()); 106 } 107 108 /** 109 * Construct with the given options. 110 * 111 * @param options 112 * the options. 113 */ 114 public DoGColourSIFTEngine(DoGSIFTEngineOptions<MBFImage> options) { 115 this.options = options; 116 } 117 118 @Override 119 public LocalFeatureList<Keypoint> findFeatures(MBFImage image) { 120 final FImage luminance = ColourSpace.convert(image, ColourSpace.LUMINANCE_NTSC).bands.get(0); 121 122 return findFeatures(image, luminance); 123 } 124 125 /** 126 * Find DoG interest points in the given luminance image, but extract the 127 * SIFT features from the colour image. 128 * 129 * @param image 130 * the colour image to extract the SIFT features from 131 * @param luminance 132 * the luminance image to detect the interest points in 133 * @return the extracted features 134 */ 135 public LocalFeatureList<Keypoint> findFeatures(MBFImage image, FImage luminance) { 136 final MBFImage newimage = new MBFImage(ColourSpace.CUSTOM); 137 newimage.bands.add(luminance); 138 newimage.bands.addAll(image.bands); 139 140 return findFeaturesInternal(newimage); 141 } 142 143 protected LocalFeatureList<Keypoint> findFeaturesInternal(MBFImage image) { 144 final OctaveInterestPointFinder<GaussianOctave<MBFImage>, MBFImage> finder = 145 new FirstBandDoGOctaveExtremaFinder(new BasicOctaveExtremaFinder(options.magnitudeThreshold, 146 options.eigenvalueRatio)); 147 148 final Collector<GaussianOctave<MBFImage>, Keypoint, MBFImage> collector = new OctaveKeypointCollector<MBFImage>( 149 new ColourGradientFeatureExtractor( 150 new DominantOrientationExtractor( 151 options.peakThreshold, 152 new OrientationHistogramExtractor( 153 options.numOriHistBins, 154 options.scaling, 155 options.smoothingIterations, 156 options.samplingSize 157 ) 158 ), 159 new SIFTFeatureProvider( 160 options.numOriBins, 161 options.numSpatialBins, 162 options.valueThreshold, 163 options.gaussianSigma 164 ), 165 options.magnificationFactor * options.numSpatialBins 166 ) 167 ); 168 169 finder.setOctaveInterestPointListener(collector); 170 171 options.setOctaveProcessor(finder); 172 173 final GaussianPyramid<MBFImage> pyr = new GaussianPyramid<MBFImage>(options); 174 pyr.process(image); 175 176 return collector.getFeatures(); 177 } 178 179 /** 180 * @return the current options used by the engine 181 */ 182 public DoGSIFTEngineOptions<MBFImage> getOptions() { 183 return options; 184 } 185}