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}