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.analysis.pyramid.gaussian;
031
032import org.openimaj.image.FImage;
033import org.openimaj.image.Image;
034import org.openimaj.image.analysis.pyramid.PyramidOptions;
035import org.openimaj.image.processing.convolution.FGaussianConvolve;
036import org.openimaj.image.processor.SinglebandImageProcessor;
037
038/**
039 * Options for constructing a Gaussian pyramid in the style of Lowe's SIFT
040 * paper.
041 * 
042 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk)
043 * 
044 * @param <IMAGE>
045 *            type of underlying image.
046 */
047public class GaussianPyramidOptions<IMAGE extends Image<?, IMAGE> & SinglebandImageProcessor.Processable<Float, FImage, IMAGE>>
048                extends
049                PyramidOptions<GaussianOctave<IMAGE>, IMAGE>
050{
051        /**
052         * Number of pixels of border for processors to ignore. Also used in
053         * calculating the minimum image size for the last octave.
054         */
055        protected int borderPixels = 5;
056
057        /**
058         * Should the starting image of the pyramid be stretched to twice its size?
059         */
060        protected boolean doubleInitialImage = true;
061
062        /**
063         * The number of extra scale steps taken beyond scales.
064         */
065        protected int extraScaleSteps = 2; // number of extra steps to take beyond
066                                                                                // doubling sigma
067
068        /**
069         * Assumed initial scale of the first image in each octave. For SIFT, Lowe
070         * suggested 1.6 (for optimal repeatability; see Lowe's IJCV paper, P.10).
071         */
072        protected float initialSigma = 1.6f;
073
074        /**
075         * The number of scales in this octave minus extraScaleSteps. Levels are
076         * constructed so that level[scales] has twice the sigma of level[0].
077         */
078        protected int scales = 3;
079
080        /**
081         * Default constructor.
082         */
083        public GaussianPyramidOptions() {
084
085        }
086
087        /**
088         * Construct the pyramid options by copying the non-processor options from
089         * the given options object.
090         * 
091         * @param options
092         *            options to copy from
093         */
094        public GaussianPyramidOptions(GaussianPyramidOptions<?> options) {
095                this.borderPixels = options.borderPixels;
096                this.doubleInitialImage = options.doubleInitialImage;
097                this.extraScaleSteps = options.extraScaleSteps;
098                this.initialSigma = options.initialSigma;
099                this.keepOctaves = options.keepOctaves;
100                this.scales = options.scales;
101        }
102
103        /**
104         * Get the number of pixels used for a border that processors shouldn't
105         * touch.
106         * 
107         * @return number of border pixels.
108         */
109        public int getBorderPixels() {
110                return borderPixels;
111        }
112
113        /**
114         * Get the number of extra scale steps taken beyond scales.
115         * 
116         * @see #getScales()
117         * 
118         * @return the extraScaleSteps
119         */
120        public int getExtraScaleSteps() {
121                return extraScaleSteps;
122        }
123
124        /**
125         * Get the assumed initial scale of the first image in each octave.
126         * 
127         * @return the initialSigma
128         */
129        public float getInitialSigma() {
130                return initialSigma;
131        }
132
133        /**
134         * Get the number of scales in this octave minus extraScaleSteps. Levels of
135         * each octave are constructed so that level[scales] has twice the sigma of
136         * level[0].
137         * 
138         * @return the scales
139         */
140        public int getScales() {
141                return scales;
142        }
143
144        /**
145         * Should the starting image of the pyramid be stretched to twice its size?
146         * 
147         * @return the doubleInitialImage
148         */
149        public boolean isDoubleInitialImage() {
150                return doubleInitialImage;
151        }
152
153        /**
154         * Set the number of pixels used for a border that processors shouldn't
155         * touch. Also affects the minimum image size for the last octave, which
156         * must be at least 2 + 2*borderPixels.
157         * 
158         * @param borderPixels
159         *            number of pixels to leave as border
160         */
161        public void setBorderPixels(int borderPixels) {
162                if (borderPixels < 2)
163                        throw new IllegalArgumentException("BorderDistance must be >= 2");
164                this.borderPixels = borderPixels;
165        }
166
167        /**
168         * Set whether starting image of the pyramid be stretched to twice its size?
169         * 
170         * @param doubleInitialImage
171         *            the doubleInitialImage to set
172         */
173        public void setDoubleInitialImage(boolean doubleInitialImage) {
174                this.doubleInitialImage = doubleInitialImage;
175        }
176
177        /**
178         * Set the number of extra scale steps taken beyond scales.
179         * 
180         * @see #setScales(int)
181         * 
182         * @param extraScaleSteps
183         *            the extraScaleSteps to set
184         */
185        public void setExtraScaleSteps(int extraScaleSteps) {
186                this.extraScaleSteps = extraScaleSteps;
187        }
188
189        /**
190         * Set the assumed initial scale of the first image in each octave. For
191         * SIFT, Lowe suggested 1.6 (for optimal repeatability; see Lowe's IJCV
192         * paper, P.10).
193         * 
194         * @param initialSigma
195         *            the initialSigma to set
196         */
197        public void setInitialSigma(float initialSigma) {
198                this.initialSigma = initialSigma;
199        }
200
201        /**
202         * Set the number of scales in this octave minus extraScaleSteps. Levels of
203         * each octave are constructed so that level[scales] has twice the sigma of
204         * level[0].
205         * 
206         * @param scales
207         *            the scales to set
208         */
209        public void setScales(int scales) {
210                this.scales = scales;
211        }
212
213        /**
214         * Create a {@link SinglebandImageProcessor} that performs a Gaussian
215         * blurring with a standard deviation given by sigma. This method is used by
216         * the {@link GaussianOctave} and {@link GaussianPyramid} to create filters
217         * for performing the blurring. By overriding in subclasses, you can control
218         * the exact filter implementation (i.e. for speed).
219         * 
220         * @param sigma
221         *            the gaussian standard deviation
222         * @return the image processor to apply the blur
223         */
224        public SinglebandImageProcessor<Float, FImage> createGaussianBlur(float sigma) {
225                return new FGaussianConvolve(sigma);
226        }
227}