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.examples.image.feature.local; 031 032import java.io.IOException; 033import java.util.List; 034 035import org.openimaj.feature.local.list.LocalFeatureList; 036import org.openimaj.feature.local.matcher.FastBasicKeypointMatcher; 037import org.openimaj.feature.local.matcher.LocalFeatureMatcher; 038import org.openimaj.feature.local.matcher.MatchingUtilities; 039import org.openimaj.feature.local.matcher.consistent.ConsistentLocalFeatureMatcher2d; 040import org.openimaj.image.DisplayUtilities; 041import org.openimaj.image.FImage; 042import org.openimaj.image.ImageUtilities; 043import org.openimaj.image.MBFImage; 044import org.openimaj.image.colour.RGBColour; 045import org.openimaj.image.feature.local.engine.asift.ASIFTEngine; 046import org.openimaj.image.feature.local.keypoints.Keypoint; 047import org.openimaj.math.geometry.transforms.HomographyRefinement; 048import org.openimaj.math.geometry.transforms.estimation.RobustHomographyEstimator; 049import org.openimaj.math.model.fit.RANSAC; 050import org.openimaj.util.pair.Pair; 051 052/** 053 * Example showing how to extract ASIFT features and match them. 054 * 055 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk) 056 * @author Sina Samangooei (ss@ecs.soton.ac.uk) 057 * 058 */ 059public class ASIFTMatchingExample { 060 /** 061 * Main method 062 * 063 * @param args 064 * ignored 065 * @throws IOException 066 * if the image can't be read 067 */ 068 public static void main(String[] args) throws IOException { 069 // Read the images from two streams 070 final String input_1Str = "/org/openimaj/examples/image/input_0.png"; 071 final String input_2Str = "/org/openimaj/examples/image/input_1.png"; 072 final FImage input_1 = ImageUtilities.readF(ASIFTMatchingExample.class.getResourceAsStream(input_1Str)); 073 final FImage input_2 = ImageUtilities.readF(ASIFTMatchingExample.class.getResourceAsStream(input_2Str)); 074 075 // Prepare the engine to the parameters in the IPOL demo 076 final ASIFTEngine engine = new ASIFTEngine(false, 7); 077 078 // Extract the keypoints from both images 079 final LocalFeatureList<Keypoint> input1Feats = engine.findKeypoints(input_1); 080 System.out.println("Extracted input1: " + input1Feats.size()); 081 final LocalFeatureList<Keypoint> input2Feats = engine.findKeypoints(input_2); 082 System.out.println("Extracted input2: " + input2Feats.size()); 083 084 // Prepare the matcher, uncomment this line to use a basic matcher as 085 // opposed to one that enforces homographic consistency 086 // LocalFeatureMatcher<Keypoint> matcher = createFastBasicMatcher(); 087 final LocalFeatureMatcher<Keypoint> matcher = createConsistentRANSACHomographyMatcher(); 088 089 // Find features in image 1 090 matcher.setModelFeatures(input1Feats); 091 // ... against image 2 092 matcher.findMatches(input2Feats); 093 094 // Get the matches 095 final List<Pair<Keypoint>> matches = matcher.getMatches(); 096 System.out.println("NMatches: " + matches.size()); 097 098 // Display the results 099 final MBFImage inp1MBF = input_1.toRGB(); 100 final MBFImage inp2MBF = input_2.toRGB(); 101 DisplayUtilities.display(MatchingUtilities.drawMatches(inp1MBF, inp2MBF, matches, RGBColour.RED)); 102 } 103 104 /** 105 * @return a matcher with a homographic constraint 106 */ 107 private static LocalFeatureMatcher<Keypoint> createConsistentRANSACHomographyMatcher() { 108 final ConsistentLocalFeatureMatcher2d<Keypoint> matcher = new ConsistentLocalFeatureMatcher2d<Keypoint>( 109 createFastBasicMatcher()); 110 matcher.setFittingModel(new RobustHomographyEstimator(10.0, 1000, new RANSAC.BestFitStoppingCondition(), 111 HomographyRefinement.NONE)); 112 113 return matcher; 114 } 115 116 /** 117 * @return a basic matcher 118 */ 119 private static LocalFeatureMatcher<Keypoint> createFastBasicMatcher() { 120 return new FastBasicKeypointMatcher<Keypoint>(8); 121 } 122}