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.ipd.finder; 031 032import java.util.List; 033 034import org.apache.log4j.BasicConfigurator; 035import org.apache.log4j.Logger; 036import org.openimaj.image.FImage; 037import org.openimaj.image.analysis.pyramid.OctaveProcessor; 038import org.openimaj.image.analysis.pyramid.gaussian.GaussianOctave; 039import org.openimaj.image.analysis.pyramid.gaussian.GaussianPyramid; 040import org.openimaj.image.feature.local.detector.ipd.collector.InterestPointFeatureCollector; 041import org.openimaj.image.feature.local.interest.IPDSelectionMode; 042import org.openimaj.image.feature.local.interest.InterestPointData; 043import org.openimaj.image.feature.local.interest.MultiscaleInterestPointDetector; 044 045/** 046 * Finder with a specified detector which finds interest points at a given 047 * gaussian octave. This is often used in conjunction with a 048 * {@link GaussianPyramid} which provides {@link GaussianOctave} instances. 049 * 050 * This finder calls a specified {@link InterestPointFeatureCollector} which 051 * does something with the features located at a given octave. 052 * 053 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk) 054 * @author Sina Samangooei (ss@ecs.soton.ac.uk) 055 * @param <T> 056 * The type of {@link InterestPointData} 057 * 058 */ 059public class OctaveInterestPointFinder<T extends InterestPointData> 060implements 061 OctaveProcessor<GaussianOctave<FImage>, FImage> 062{ 063 064 protected MultiscaleInterestPointDetector<T> detector; 065 protected InterestPointFeatureCollector<T> listener; 066 protected IPDSelectionMode selectionMode; 067 static Logger logger = Logger.getLogger(OctaveInterestPointFinder.class); 068 static { 069 BasicConfigurator.configure(); 070 } 071 072 /** 073 * @param detector 074 * the detector with which features are found 075 * @param selectionMode 076 * the detector's feature selection mode 077 */ 078 public OctaveInterestPointFinder(MultiscaleInterestPointDetector<T> detector, IPDSelectionMode selectionMode) { 079 this.detector = detector; 080 this.selectionMode = selectionMode; 081 } 082 083 @Override 084 public void process(GaussianOctave<FImage> octave) { 085 for (int currentScaleIndex = 0; currentScaleIndex < octave.images.length; currentScaleIndex++) { 086 final FImage fImage = octave.images[currentScaleIndex]; 087 final float currentScale = (float) (octave.options.getInitialSigma() * Math.pow(2, (float) currentScaleIndex 088 / octave.options.getScales())); 089 detector.setDetectionScale(currentScale); 090 detector.findInterestPoints(fImage); 091 final List<T> points = this.selectionMode.selectPoints(detector); 092 processOctaveLevelPoints(fImage, points, currentScale, octave.octaveSize); 093 } 094 095 } 096 097 protected void processOctaveLevelPoints(FImage fImage, List<T> points, float currentScale, float octaveSize) { 098 logger.info(String.format("At octave scale %4.2f (absolute scale %4.2f) %d points detected", currentScale, 099 currentScale * octaveSize, points.size())); 100 for (final T point : points) { 101 this.listener.foundInterestPoint(fImage, point, octaveSize); 102 } 103 } 104 105 /** 106 * @param listener 107 * to be informed on detection of new interest points 108 */ 109 public void setOctaveInterestPointListener(InterestPointFeatureCollector<T> listener) { 110 this.listener = listener; 111 } 112 113 /** 114 * Once all the features have been detected, do something (default: nothing) 115 */ 116 public void finish() { 117 } 118 119}