/** * Detect scale-invariant feature points given a pyramid. * @param _i_dog_feature_points * 検出したDOG特徴点 */ public void detect(GaussianScaleSpacePyramid i_pyramid, DogFeaturePointStack i_dog_feature_points) { //clean up 1st feature stack DogFeaturePointStack tmp_fp = this._tmp_fps; tmp_fp.clear(); // Compute Laplacian images (DoG) this.mLaplacianPyramid.compute(i_pyramid); // Detect minima and maximum in Laplacian images this.extractFeatures(i_pyramid, this.mLaplacianPyramid, tmp_fp); // Sub-pixel refinement this.findSubpixelLocations(i_pyramid, tmp_fp); // Compute the gradient pyramid this.mOrientationAssignment.computeGradients(i_pyramid); AreaBuckit abuckit = this.mBuckets; if (tmp_fp.getLength() <= abuckit._buckit.Length) { //特徴点の数が要求数以下なら全てのポイントを使う。 for (int i = 0; i < tmp_fp.getLength(); i++) { this.addFeatureOrientations(i_pyramid, tmp_fp.getItem(i), i_dog_feature_points); } } else { //特徴点を選別(Prune features) // Clear the previous state abuckit.clear(); // Insert each features into a bucket for (int i = 0; i < tmp_fp.getLength(); i++) { DogFeaturePoint p = tmp_fp.getItem(i); abuckit.put(p.x, p.y, i, Math.Abs(p.score)); } // Compute an orientation for each feature point for (int i = 0; i < abuckit._buckit.Length; i++) { if (abuckit._buckit[i].first == 0) { continue; } this.addFeatureOrientations(i_pyramid, tmp_fp.getItem(abuckit._buckit[i].second), i_dog_feature_points); } } return; }
/** * Sub-pixel refinement. */ private void findSubpixelLocations(GaussianScaleSpacePyramid pyramid, DogFeaturePointStack i_dog_fp) { int num_points; double laplacianSqrThreshold; double hessianThreshold; num_points = 0; laplacianSqrThreshold = (this.mLaplacianThreshold * this.mLaplacianThreshold); double te = (mEdgeThreshold + 1); hessianThreshold = ((te * te) / mEdgeThreshold); for (int i = 0; i < i_dog_fp.getLength(); i++) { DogFeaturePoint kp = i_dog_fp.getItem(i); //assert kp.scale < mLaplacianPyramid.numScalePerOctave(); // ASSERT(kp.scale < mLaplacianPyramid.numScalePerOctave(), // "Feature point scale is out of bounds"); int lap_index = kp.octave * mLaplacianPyramid.numScalePerOctave() + kp.scale; // Get Laplacian images LaplacianImage lap0 = mLaplacianPyramid.get(lap_index - 1); LaplacianImage lap1 = mLaplacianPyramid.get(lap_index); LaplacianImage lap2 = mLaplacianPyramid.get(lap_index + 1); // Compute the Hessian if (!this.updateLocation(kp, lap0, lap1, lap2)) { continue; } if (Math.Abs(kp.edge_score) < hessianThreshold && (kp.score * kp.score) >= laplacianSqrThreshold && kp.x >= 0 && kp.x < mLaplacianPyramid.get(0).getWidth() && kp.y >= 0 && kp.y < mLaplacianPyramid.get(0).getHeight()) { // Update the sigma kp.sigma = pyramid.effectiveSigma(kp.octave, kp.sp_scale); i_dog_fp.swap(i, num_points++); } } i_dog_fp.setLength(num_points); }
/** * Extract the descriptors for all the feature points. */ private void ExtractFREAK84(FreakFeaturePointStack store, GaussianScaleSpacePyramid pyramid, DogFeaturePointStack points, double[] points_ring0, double[] points_ring1, double[] points_ring2, double[] points_ring3, double[] points_ring4, double[] points_ring5, double sigma_center, double sigma_ring0, double sigma_ring1, double sigma_ring2, double sigma_ring3, double sigma_ring4, double sigma_ring5, double expansion_factor) { // ASSERT(pyramid, "Pyramid is NULL"); // ASSERT(store.size() == points.size(), // "Feature store has not been allocated"); for (int i = 0; i < points.getLength(); i++) { FreakFeaturePoint sp = store.prePush(); if (sp == null) { prepush_wawning(); break; } DogFeaturePoint pt = points.getItem(i); if (!ExtractFREAK84(sp.descripter, pyramid, pt, points_ring0, points_ring1, points_ring2, points_ring3, points_ring4, points_ring5, sigma_center, sigma_ring0, sigma_ring1, sigma_ring2, sigma_ring3, sigma_ring4, sigma_ring5, expansion_factor )) { store.pop(); continue; } sp.angle = pt.angle; sp.x = pt.x; sp.y = pt.y; sp.scale = pt.sigma; sp.maxima = pt.score > 0; // store.point(num_points).set(points[i]); } }