public Keyframe(int width, int height, FreakMatchPointSetStack i_binaryFeatureStore) { this.mWidth = width; this.mHeight = height; this.mStore = i_binaryFeatureStore; BinaryHierarchicalClusterBuilder bhi = new BinaryHierarchicalClusterBuilder(i_binaryFeatureStore.getLength(), 128, 8, 16); this.mIndex = bhi.build(this.mStore); }
/** * Match two feature stores given a homography from the features in store 1 to store 2. The THRESHOLD is a spatial * threshold in pixels to restrict the number of feature comparisons. * * @return Number of matches */ public int match(FreakFeaturePointStack i_query, FreakMatchPointSetStack i_ref, InverseHomographyMat i_hinv, double tr, FeaturePairStack i_maches) { if (i_query.getLength() * i_ref.getLength() == 0) { return(0); } double tr_sqr = tr * tr; FreakFeaturePoint[] query_buf = i_query.getArray(); FreakMatchPointSetStack.Item[] ref_buf = i_ref.getArray(); int q_len = i_query.getLength(); int r_len = i_ref.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(); int best_index = int.MaxValue; // std::numeric_limits<int>::max(); FreakFeaturePoint fptr1 = query_buf[i]; // Map p1 to p2 space through H //i_hinv.multiplyPointHomographyInhomogenous(fptr1.x, fptr1.y, tmp); double qx, qy; { double w = i_hinv.m20 * fptr1.x + i_hinv.m21 * fptr1.y + i_hinv.m22; qx = (i_hinv.m00 * fptr1.x + i_hinv.m01 * fptr1.y + i_hinv.m02) / w; // XP qy = (i_hinv.m10 * fptr1.x + i_hinv.m11 * fptr1.y + i_hinv.m12) / w; // YP } // Search for 1st and 2nd best match for (int j = 0; j < r_len; j++) { FreakFeaturePoint fptr2 = ref_buf[j]; // Both points should be a MINIMA or MAXIMA if (fptr1.maxima != fptr2.maxima) { continue; } double tx = (qx - fptr2.x); double ty = (qy - fptr2.y); // Check spatial constraint if ((tx * tx) + (ty * ty) > tr_sqr) { continue; } int d = fptr1.descripter.hammingDistance(fptr2.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) { FeaturePairStack.Item t = i_maches.prePush(); t.query = fptr1; t.ref_ = ref_buf[best_index]; } else { // Ratio test double r = (double)first_best / (double)second_best; if (r < this.mThreshold) { FeaturePairStack.Item t = i_maches.prePush(); t.query = fptr1; t.ref_ = ref_buf[best_index]; } } } } return(i_maches.getLength()); }
/** * 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()); }