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