public double RMSE(PoseEstimate other) { if (other == null) { throw new ArgumentNullException("other"); } double result = this.MSE(other); result = Math.Sqrt(result); return(result); }
public double MSE(PoseEstimate other) { if (other == null) { throw new ArgumentNullException("other"); } double result = Math.Pow(this.Dx - other.Dx, 2); result += Math.Pow(this.Dy - other.Dy, 2); result += Math.Pow(this.Ds - other.Ds, 2); result += Math.Pow(this.Do - other.Do, 2); result /= 4.0; return(result); }
private List <MDMatch> clusterBasedOnPoseEstimation(List <MDMatch> matches, KeyPoints queryKeyPoints, PreProcessedImage trainingData) { // If no training data is provided then we cannot compute pose (LeafAnalysisV1), hence just return back the original set if (trainingData == null || matches == null || !matches.Any()) { return(matches); } Dictionary <MDMatch, List <MDMatch> > clusters = new Dictionary <MDMatch, List <MDMatch> >(matches.Count); List <PoseEstimate> poseEstimates = new List <PoseEstimate>(matches.Count); foreach (MDMatch match in matches) { MKeyPoint queryKeyPoint = queryKeyPoints.Points[match.QueryIdx]; MKeyPoint trainingKeyPoint = trainingData.KeyPoints.Points[match.TrainIdx]; PoseEstimate estimate = new PoseEstimate(); estimate.Match = match; estimate.Dx = trainingKeyPoint.Point.X - queryKeyPoint.Point.X; estimate.Dy = trainingKeyPoint.Point.Y - queryKeyPoint.Point.Y; estimate.Ds = trainingKeyPoint.Octave / queryKeyPoint.Octave; estimate.Do = trainingKeyPoint.Angle - queryKeyPoint.Angle; poseEstimates.Add(estimate); // Initialize clusters for each individual match // Next we will add other matches which belong to this cluster clusters.Add(match, new List <MDMatch>(new MDMatch[] { match })); } const double errorThreshold = 5; // Compute cluster membership foreach (PoseEstimate estimate in poseEstimates) { foreach (PoseEstimate otherEstimate in poseEstimates) { // Ignore self if (estimate == otherEstimate) { continue; } double error = estimate.RMSE(otherEstimate); //Console.WriteLine("Error: " + trainingData.Category + ": " + error); if (error < errorThreshold) { clusters[estimate.Match].Add(otherEstimate.Match); } } } // Finally pick the largest cluster List <MDMatch> result = null; int sizeOfCluster = -1;; foreach (KeyValuePair <MDMatch, List <MDMatch> > cluster in clusters) { if (cluster.Value.Count == sizeOfCluster) { // Tie breaker: choose the cluster with smaller overall distances if (result.Sum(item => item.Distance) > cluster.Value.Sum(item => item.Distance)) { result = cluster.Value; } } else if (cluster.Value.Count > sizeOfCluster) { sizeOfCluster = cluster.Value.Count; result = cluster.Value; } } return(result); }