/* * Copyright 2013 Alibaba.com All right reserved. This software is the * confidential and proprietary information of Alibaba.com ("Confidential * Information"). You shall not disclose such Confidential Information and shall * use it only in accordance with the terms of the license agreement you entered * into with Alibaba.com. */ package com.alibaba.simpleimage.analyze.sift.match; import java.util.Comparator; import com.alibaba.simpleimage.analyze.sift.scale.KDFeaturePoint; /** * * @author axman 2013-4-3 上午 11:28:04 */ public class Match { int slopeArc; public KDFeaturePoint fp1; public KDFeaturePoint fp2; public float dist1; public float dist2; // dist1: distance between fp1/kp2, // dist2: distance between fp1 and kp3, where kp3 is the next closest // match public Match(KDFeaturePoint fp1, KDFeaturePoint fp2, float dist1, float dist2){ this.fp1 = fp1; this.fp2 = fp2; this.dist1 = dist1; this.dist2 = dist2; } public static class MatchWeighter implements Comparator<Match> { private float distExp; private float quotExp; public MatchWeighter(){ this(1.0f, 1.0f); } // The formula goes like this, with lowest weight being best matches: // w(kp) = kp.dist1^{distExp} * // {\frac{1}{kp.dist2 - kp.dist1}}^{quotExp} // // This means, as both dist1 and dist2 are in [0.0 ; 1.0], that a high // distExp exponent (and distExp > quotExp) will make the absolute // distance for the best match more important. A high value for // quotExp will make the difference between the best and second best // match more important (as in "how many other candidates are likely // matches?"). public MatchWeighter(float distExp, float quotExp){ this.distExp = distExp; this.quotExp = quotExp; } public float OverallFitness(Match m) { float fitness = (float)(Math.pow(m.dist1, distExp) * Math.pow(1.0 / (m.dist2 - m.dist1), quotExp)); return (fitness); } public int compare(Match o1, Match o2) { float fit1 = OverallFitness(o1); float fit2 = OverallFitness(o2); if (fit1 < fit2) return (-1); else if (fit1 > fit2) return (1); return (0); } } }