
org.openimaj.feature.local.matcher.VotingKeypointMatcher Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of image-local-features Show documentation
Show all versions of image-local-features Show documentation
Methods for the extraction of local features. Local features
are descriptions of regions of images (SIFT, ...) selected by
detectors (Difference of Gaussian, Harris, ...).
/**
* Copyright (c) 2011, The University of Southampton and the individual contributors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the University of Southampton nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.openimaj.feature.local.matcher;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.openimaj.image.feature.local.keypoints.Keypoint;
import org.openimaj.util.pair.Pair;
/**
* Matcher rejects matches with no local support
*
* @author Jonathon Hare
* @param
*
*/
public class VotingKeypointMatcher extends FastBasicKeypointMatcher implements LocalFeatureMatcher {
int neighbours;
List> consistentMatches = new ArrayList>();
protected int minVote;
protected float singularityDistance;
/**
* @param threshold threshold for determining matching keypoints
*/
public VotingKeypointMatcher(int threshold) {
this(threshold, 15, 1, 200.0f); //default to 15 as in VideoGoogle paper
}
/**
* @param threshold threshold for determining matching keypoints
* @param neighbours number of neighbours within which to check for local support
* @param minVote
* @param singularityDistance
*/
public VotingKeypointMatcher(int threshold, int neighbours, int minVote, float singularityDistance) {
super(threshold);
this.neighbours = neighbours;
this.minVote = minVote;
this.singularityDistance = singularityDistance;
}
/**
* @return a list of consistent matching keypoints according
* to the estimated model parameters.
*/
@Override
public List> getMatches() {
return consistentMatches;
}
/**
* @return a list of all matches irrespective of whether they fit the model
*/
public List> getAllMatches() {
return matches;
}
@Override
public boolean findMatches(List keys1) {
super.findMatches(keys1);
consistentMatches = new ArrayList>();
//filter dups
//matches = ConsistentKeypointMatcher.filterColinear(matches, 1);
//filter spurious matches by voting
for (Pair match : matches) {
int vote = vote(match);
if (vote > minVote)
consistentMatches.add(match);
}
if (consistentMatches.size() == 0)
return false;
//reject mappings to very close points
if (checkSingularity()) {
consistentMatches.clear();
return false;
}
return true;
}
protected float [] getCentroid() {
float mx = consistentMatches.get(0).secondObject().x;
float my = consistentMatches.get(0).secondObject().y;
for (int i=1; i p : consistentMatches) {
if (euclideanSqr(p.secondObject(), k) > singularityDistance) return false;
}
return true;
}
protected int vote(Pair match) {
List nn = findModelNeighbours(match.secondObject());
int vote = 0;
for (Pair m : matches) {
for (Keypoint k : nn) {
if (m.secondObject() == k) {
vote++;
break;
}
}
}
return vote;
}
protected float euclideanSqr(Keypoint k1, Keypoint k2) {
return ((k1.x - k2.x) * (k1.x - k2.x)) +
((k1.y - k2.y)*(k1.y - k2.y));
}
protected List findModelNeighbours(final T kp) {
class KpDist implements Comparable> {
float distance;
T keypoint;
KpDist(T keypoint) {
this.keypoint = keypoint;
distance = euclideanSqr(keypoint, kp);
}
@Override
public int compareTo(KpDist o) {
if (distance > o.distance) return 1;
if (distance < o.distance) return -1;
return 0;
}
}
List> list = new ArrayList>();
for (T k : modelKeypoints) {
list.add(new KpDist(k));
}
Collections.sort(list);
List keys = new ArrayList();
for (int i=0; i
© 2015 - 2025 Weber Informatics LLC | Privacy Policy