1 /**
2 * Copyright (c) 2011, The University of Southampton and the individual contributors.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * * Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * * Neither the name of the University of Southampton nor the names of its
16 * contributors may be used to endorse or promote products derived from this
17 * software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30 package org.openimaj.image.analysis.pyramid.gaussian;
31
32 import org.openimaj.image.FImage;
33 import org.openimaj.image.Image;
34 import org.openimaj.image.analysis.pyramid.PyramidOptions;
35 import org.openimaj.image.processing.convolution.FGaussianConvolve;
36 import org.openimaj.image.processor.SinglebandImageProcessor;
37
38 /**
39 * Options for constructing a Gaussian pyramid in the style of Lowe's SIFT
40 * paper.
41 *
42 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk)
43 *
44 * @param <IMAGE>
45 * type of underlying image.
46 */
47 public class GaussianPyramidOptions<IMAGE extends Image<?, IMAGE> & SinglebandImageProcessor.Processable<Float, FImage, IMAGE>>
48 extends
49 PyramidOptions<GaussianOctave<IMAGE>, IMAGE>
50 {
51 /**
52 * Number of pixels of border for processors to ignore. Also used in
53 * calculating the minimum image size for the last octave.
54 */
55 protected int borderPixels = 5;
56
57 /**
58 * Should the starting image of the pyramid be stretched to twice its size?
59 */
60 protected boolean doubleInitialImage = true;
61
62 /**
63 * The number of extra scale steps taken beyond scales.
64 */
65 protected int extraScaleSteps = 2; // number of extra steps to take beyond
66 // doubling sigma
67
68 /**
69 * Assumed initial scale of the first image in each octave. For SIFT, Lowe
70 * suggested 1.6 (for optimal repeatability; see Lowe's IJCV paper, P.10).
71 */
72 protected float initialSigma = 1.6f;
73
74 /**
75 * The number of scales in this octave minus extraScaleSteps. Levels are
76 * constructed so that level[scales] has twice the sigma of level[0].
77 */
78 protected int scales = 3;
79
80 /**
81 * Default constructor.
82 */
83 public GaussianPyramidOptions() {
84
85 }
86
87 /**
88 * Construct the pyramid options by copying the non-processor options from
89 * the given options object.
90 *
91 * @param options
92 * options to copy from
93 */
94 public GaussianPyramidOptions(GaussianPyramidOptions<?> options) {
95 this.borderPixels = options.borderPixels;
96 this.doubleInitialImage = options.doubleInitialImage;
97 this.extraScaleSteps = options.extraScaleSteps;
98 this.initialSigma = options.initialSigma;
99 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 }