/** * Match two feature stores. * * @return Number of matches */ public virtual int match(FreakFeaturePointStack i_query, Keyframe i_key_frame, FeaturePairStack i_maches) { FreakMatchPointSetStack ref_ = i_key_frame.getFeaturePointSet(); if (i_query.getLength() == 0 || ref_.getLength() == 0) { return(0); } // mMatches.reserve(features1.size()); for (int i = 0; i < i_query.getLength(); i++) { int first_best = int.MaxValue; int second_best = int.MaxValue; int best_index = int.MaxValue; // Search for 1st and 2nd best match FreakFeaturePoint p1 = i_query.getItem(i); for (int j = 0; j < ref_.getLength(); j++) { // Both points should be a MINIMA or MAXIMA if (p1.maxima != ref_.getItem(j).maxima) { continue; } // ASSERT(FEATURE_SIZE == 96, "Only 96 bytes supported now"); int d = i_query.getItem(i).descripter.hammingDistance(ref_.getItem(j).descripter); if (d < first_best) { second_best = first_best; first_best = d; best_index = (int)j; } else if (d < second_best) { second_best = d; } } // Check if FIRST_BEST has been set if (first_best != int.MaxValue) { // If there isn't a SECOND_BEST, then always choose the FIRST_BEST. // Otherwise, do a ratio test. if (second_best == int.MaxValue) { // mMatches.push_back(match_t((int)i, best_index)); FeaturePairStack.Item t = i_maches.prePush(); t.query = i_query.getItem(i); t.ref_ = ref_.getItem(best_index); } else { // Ratio test double r = (double)first_best / (double)second_best; if (r < mThreshold) { FeaturePairStack.Item t = i_maches.prePush(); t.query = i_query.getItem(i); t.ref_ = ref_.getItem(best_index); // mMatches.push_back(match_t((int)i, best_index)); } } } } // ASSERT(mMatches.size() <= features1->size(), "Number of matches should be lower"); return(i_maches.getLength()); }
/** * Match two feature stores with an index on features2. * * @return Number of matches */ override public int match(FreakFeaturePointStack i_query, Keyframe i_key_frame, FeaturePairStack i_maches) { //indexが無いときはベースクラスを使う。 BinaryHierarchicalNode index2 = i_key_frame.getIndex(); if (index2 == null) { return(base.match(i_query, i_key_frame, i_maches)); } FreakMatchPointSetStack ref_ = i_key_frame.getFeaturePointSet(); if (i_query.getLength() * ref_.getLength() == 0) { return(0); } FreakFeaturePoint[] query_buf = i_query.getArray(); int q_len = i_query.getLength(); for (int i = 0; i < q_len; i++) { int first_best = int.MaxValue; // std::numeric_limits<unsigned int>::max(); int second_best = int.MaxValue; // std::numeric_limits<unsigned int>::max(); FreakMatchPointSetStack.Item best_index = null; // std::numeric_limits<int>::max(); // Perform an indexed nearest neighbor lookup FreakFeaturePoint fptr1 = query_buf[i]; int num_of_fp = this._selector.query(index2, fptr1.descripter); // Search for 1st and 2nd best match FreakMatchPointSetStack.Item[] v = this._selector._result; for (int j = 0; j < num_of_fp; j++) { FreakFeaturePoint fptr2 = v[j]; // Both points should be a MINIMA or MAXIMA if (fptr1.maxima != fptr2.maxima) { continue; } int d = fptr1.descripter.hammingDistance(fptr2.descripter); if (d < first_best) { second_best = first_best; first_best = d; best_index = v[j]; } else if (d < second_best) { second_best = d; } } // Check if FIRST_BEST has been set if (first_best != int.MaxValue) { // If there isn't a SECOND_BEST, then always choose the FIRST_BEST. // Otherwise, do a ratio test. if (second_best == int.MaxValue) { FeaturePairStack.Item t = i_maches.prePush(); t.query = fptr1; t.ref_ = best_index; } else { // Ratio test double r = (double)first_best / (double)second_best; if (r < mThreshold) { // mMatches.push_back(match_t((int)i, best_index)); FeaturePairStack.Item t = i_maches.prePush(); t.query = fptr1; t.ref_ = best_index; } } } } return(i_maches.getLength()); }