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.detector.pyramid; 031 032import org.openimaj.citation.annotation.Reference; 033import org.openimaj.citation.annotation.ReferenceType; 034import org.openimaj.citation.annotation.References; 035import org.openimaj.image.FImage; 036import org.openimaj.image.analysis.pyramid.gaussian.GaussianOctave; 037 038/** 039 * <p> 040 * A basic concrete implementation of an {@link AbstractOctaveExtremaFinder} 041 * that searches for local extrema in scale space. If detected extrema pass a 042 * series of tests (namely those described in 043 * {@link AbstractOctaveExtremaFinder}) and a final test that tests the absolute 044 * value of the interest point pixel against a threshold, then the listener 045 * object will be informed that a point has been detected. 046 * </p> 047 * 048 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk) 049 * 050 */ 051@References(references = { 052 @Reference( 053 type = ReferenceType.Article, 054 author = { "David Lowe" }, 055 title = "Distinctive image features from scale-invariant keypoints", 056 year = "2004", 057 journal = "IJCV", 058 pages = { "91", "110" }, 059 month = "January", 060 number = "2", 061 volume = "60"), 062 @Reference( 063 type = ReferenceType.Inproceedings, 064 author = { "David Lowe" }, 065 title = "Object recognition from local scale-invariant features", 066 year = "1999", 067 booktitle = "Proc. of the International Conference on Computer Vision {ICCV}", 068 pages = { "1150", "1157" } 069 ) 070}) 071public class BasicOctaveExtremaFinder extends AbstractOctaveExtremaFinder<GaussianOctave<FImage>> { 072 /** 073 * The default threshold for the magnitude of interest points 074 */ 075 public static final float DEFAULT_MAGNITUDE_THRESHOLD = 0.04f; // Lowe's 076 // IJCV 077 // suggests 078 // 0.03, 079 // but the 080 // open SIFT 081 // implementation 082 // uses 0.04 083 084 // Threshold on the magnitude of detected points (Lowe IJCV, p.11) 085 protected float magnitudeThreshold = DEFAULT_MAGNITUDE_THRESHOLD; 086 087 protected float scales; 088 protected float normMagnitudeScales; 089 090 /** 091 * Default constructor using {@link #DEFAULT_MAGNITUDE_THRESHOLD} for the 092 * magnitude threshold and {@link #DEFAULT_EIGENVALUE_RATIO} for the 093 * Eigenvalue ratio threshold. 094 */ 095 public BasicOctaveExtremaFinder() { 096 } 097 098 /** 099 * Construct with the given magnitude threshold and 100 * {@link #DEFAULT_EIGENVALUE_RATIO} for the Eigenvalue ratio threshold. 101 * 102 * @param magnitudeThreshold 103 * the magnitude threshold 104 */ 105 public BasicOctaveExtremaFinder(float magnitudeThreshold) { 106 this(magnitudeThreshold, DEFAULT_EIGENVALUE_RATIO); 107 } 108 109 /** 110 * Construct with the given magnitude and Eigenvalue thresholds 111 * 112 * @param magnitudeThreshold 113 * the magnitude threshold 114 * @param eigenvalueRatio 115 * the Eigenvalue threshold 116 */ 117 public BasicOctaveExtremaFinder(float magnitudeThreshold, float eigenvalueRatio) { 118 super(eigenvalueRatio); 119 this.magnitudeThreshold = magnitudeThreshold; 120 } 121 122 @Override 123 protected void beforeProcess(GaussianOctave<FImage> octave) { 124 scales = octave.options.getScales(); 125 126 // the magnitude threshold must be adjusted based on the number of 127 // scales, 128 // as more scales will result in smaller differences between scales 129 normMagnitudeScales = magnitudeThreshold / octave.options.getScales(); 130 } 131 132 @Override 133 protected boolean firstCheck(float val, int x, int y, int s, FImage[] dogs) { 134 // perform magnitude check 135 if (Math.abs(dogs[s].pixels[y][x]) > normMagnitudeScales) { 136 return true; 137 } 138 return false; 139 } 140 141 @Override 142 protected void processExtrema(FImage[] dogs, int s, int x, int y, float octSize) { 143 // calculate the actual scale within the octave 144 final float octaveScale = octave.options.getInitialSigma() * (float) Math.pow(2.0, s / scales); 145 146 // fire the listener 147 if (listener != null) 148 listener.foundInterestPoint(this, x, y, octaveScale); 149 } 150}