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 java.lang.reflect.Array; 033 034import org.openimaj.image.FImage; 035import org.openimaj.image.Image; 036import org.openimaj.image.analysis.pyramid.Octave; 037import org.openimaj.image.processor.SinglebandImageProcessor; 038 039/** 040 * This class represents a Gaussian octave in the style of Lowe's SIFT paper. 041 * 042 * The size of the image stack is controlled by the parameters scales and 043 * extraScaleSteps. The stack is constructed such that images[0] is the initial 044 * image, and images[scales] has twice the blur of the initial image. The sigma 045 * of the initial image is the parameter initialSigma. 046 * 047 * Octaves are Iterable for easy access to each of the images in turn. 048 * 049 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk) 050 * 051 * @param <IMAGE> 052 * Type of underlying image 053 */ 054public class GaussianOctave<IMAGE extends Image<?, IMAGE> & SinglebandImageProcessor.Processable<Float, FImage, IMAGE>> 055 extends 056 Octave<GaussianPyramidOptions<IMAGE>, GaussianPyramid<IMAGE>, IMAGE> 057{ 058 059 /** 060 * Construct a Gaussian octave with the provided parent Pyramid and 061 * octaveSize. The octaveSize parameter is the size of the octave's images 062 * compared to the original image used to construct the pyramid. An 063 * octaveSize of 1 means the same size as the original, 2 means half size, 4 064 * means quarter size, etc. 065 * 066 * @param parent 067 * the pyramid that this octave belongs to 068 * @param octaveSize 069 * the size of the octave relative to the original image. 070 */ 071 public GaussianOctave(GaussianPyramid<IMAGE> parent, float octaveSize) { 072 super(parent, octaveSize); 073 } 074 075 /* 076 * (non-Javadoc) 077 * 078 * @see 079 * org.openimaj.image.processing.pyramid.AbstractOctave#process(org.openimaj 080 * .image.Image) 081 */ 082 @Override 083 @SuppressWarnings("unchecked") 084 public void process(IMAGE image) { 085 images = (IMAGE[]) Array.newInstance(image.getClass(), options.scales + options.extraScaleSteps + 1); 086 087 // we want to each level to be separated by a constant factor 088 // k=2^(1/scales) 089 final float k = (float) Math.pow(2.0, 1.0 / options.scales); 090 091 // image[0] of the octave is the input image 092 images[0] = image; 093 094 // the intial (input) image is considered to have sigma initialSigma. 095 float prevSigma = options.initialSigma; 096 097 for (int i = 1; i < options.scales + options.extraScaleSteps + 1; i++) { 098 images[i] = images[i - 1].clone(); 099 100 // compute the amount to increase from prevSigma to prevSigma*k 101 final float increase = prevSigma * (float) Math.sqrt(k * k - 1.0); 102 103 images[i].processInplace(options.createGaussianBlur(increase)); 104 105 prevSigma *= k; 106 } 107 108 // if a processor is defined, apply it 109 if (options.getOctaveProcessor() != null) 110 options.getOctaveProcessor().process(this); 111 } 112 113 /* 114 * (non-Javadoc) 115 * 116 * @see 117 * org.openimaj.image.processing.pyramid.AbstractOctave#getNextOctaveImage() 118 */ 119 @Override 120 public IMAGE getNextOctaveImage() { 121 return images[options.scales]; 122 } 123}