private void addFeatureOrientations(GaussianScaleSpacePyramid i_pyramid, DogFeaturePoint dfp, DogFeaturePointStack i_ot_fps) { double[] tmp = this._addFeatureOrientations_tmp; double x, y, s; // Down sample the point to the detected octave bilinear_downsample_point(tmp, dfp.x, dfp.y, dfp.sigma, dfp.octave); x = tmp[0]; y = tmp[1]; s = tmp[2]; // Downsampling the point can cause (x,y) to leave the image bounds // by // a tiny amount. Here we just clip it to be within the image // bounds. x = ClipScalar(x, 0, i_pyramid.get(dfp.octave, 0).getWidth() - 1); y = ClipScalar(y, 0, i_pyramid.get(dfp.octave, 0).getHeight() - 1); // Compute dominant orientations int num_angles = mOrientationAssignment.compute(dfp.octave, dfp.scale, x, y, s, this.mOrientations); // Create a feature point for each angle for (int j = 0; j < num_angles; j++) { // Copy the feature point DogFeaturePoint fp = i_ot_fps.prePush(); if (fp == null) { //中断 // prepush_warning(); break; } fp.x = dfp.x; fp.y = dfp.y; fp.octave = dfp.octave; fp.scale = dfp.scale; fp.sp_scale = dfp.sp_scale; fp.score = dfp.score; fp.sigma = dfp.sigma; fp.edge_score = dfp.edge_score; fp.angle = mOrientations[j]; } return; }
/** * Extract the minima/maxima. */ private void extractFeatures(GaussianScaleSpacePyramid pyramid, DoGPyramid laplacian, DogFeaturePointStack i_dog_fp) { double laplacianSqrThreshold = (this.mLaplacianThreshold * this.mLaplacianThreshold); for (int i = 1; i < mLaplacianPyramid.size() - 1; i++) { LaplacianImage im0 = laplacian.get(i - 1); LaplacianImage im1 = laplacian.get(i); LaplacianImage im2 = laplacian.get(i + 1); double[] im0b = (double[])im0.getBuffer(); double[] im1b = (double[])im1.getBuffer(); double[] im2b = (double[])im2.getBuffer(); int octave = laplacian.octaveFromIndex((int)i); int scale = laplacian.scaleFromIndex((int)i); if (im0.getWidth() == im1.getWidth() && im0.getWidth() == im2.getWidth()) { // All images are the // same size // ASSERT(im0.height() == im1.height(), "Height is inconsistent"); // ASSERT(im0.height() == im2.height(), "Height is inconsistent"); int width_minus_1 = im1.getWidth() - 1; int heigh_minus_1 = im1.getHeight() - 1; for (int row = 1; row < heigh_minus_1; row++) { int im0_ym1 = im0.get(row - 1); int im0_y = im0.get(row); int im0_yp1 = im0.get(row + 1); int im1_ym1 = im1.get(row - 1); int im1_y = im1.get(row); int im1_yp1 = im1.get(row + 1); int im2_ym1 = im2.get(row - 1); int im2_y = im2.get(row); int im2_yp1 = im2.get(row + 1); for (int col = 1; col < width_minus_1; col++) { double value = im1b[im1_y + col]; // Check laplacian score if ((value * value) < laplacianSqrThreshold) { continue; } bool extrema = false; if (value > im0b[im0_ym1 + col - 1] && value > im0b[im0_ym1 + col] && value > im0b[im0_ym1 + col + 1] && value > im0b[im0_y + col - 1] && value > im0b[im0_y + col] && value > im0b[im0_y + col + 1] && value > im0b[im0_yp1 + col - 1] && value > im0b[im0_yp1 + col] && value > im0b[im0_yp1 + col + 1] && /* im1 - 8 evaluations */ value > im1b[im1_ym1 + col - 1] && value > im1b[im1_ym1 + col] && value > im1b[im1_ym1 + col + 1] && value > im1b[im1_y + col - 1] && value > im1b[im1_y + col + 1] && value > im1b[im1_yp1 + col - 1] && value > im1b[im1_yp1 + col] && value > im1b[im1_yp1 + col + 1] && /* im2 - 9 evaluations */ value > im2b[im2_ym1 + col - 1] && value > im2b[im2_ym1 + col] && value > im2b[im2_ym1 + col + 1] && value > im2b[im2_y + col - 1] && value > im2b[im2_y + col] && value > im2b[im2_y + col + 1] && value > im2b[im2_yp1 + col - 1] && value > im2b[im2_yp1 + col] && value > im2b[im2_yp1 + col + 1]) { extrema = true; } else if (value < im0b[im0_ym1 + col - 1] && value < im0b[im0_ym1 + col] && value < im0b[im0_ym1 + col + 1] && value < im0b[im0_y + col - 1] && value < im0b[im0_y + col] && value < im0b[im0_y + col + 1] && value < im0b[im0_yp1 + col - 1] && value < im0b[im0_yp1 + col] && value < im0b[im0_yp1 + col + 1] && /* im1 - 8 evaluations */ value < im1b[im1_ym1 + col - 1] && value < im1b[im1_ym1 + col] && value < im1b[im1_ym1 + col + 1] && value < im1b[im1_y + col - 1] && value < im1b[im1_y + col + 1] && value < im1b[im1_yp1 + col - 1] && value < im1b[im1_yp1 + col] && value < im1b[im1_yp1 + col + 1] && /* im2 - 9 evaluations */ value < im2b[im2_ym1 + col - 1] && value < im2b[im2_ym1 + col] && value < im2b[im2_ym1 + col + 1] && value < im2b[im2_y + col - 1] && value < im2b[im2_y + col] && value < im2b[im2_y + col + 1] && value < im2b[im2_yp1 + col - 1] && value < im2b[im2_yp1 + col] && value < im2b[im2_yp1 + col + 1]) { extrema = true; } if (extrema) { DogFeaturePoint fp = i_dog_fp.prePush(); if (fp == null) { prepush_warning(); break; } fp.octave = octave; fp.scale = scale; fp.score = value; fp.sigma = pyramid.effectiveSigma(octave, scale); double[] tmp = new double[2]; bilinear_upsample_point(tmp, col, row, octave); fp.x = tmp[0]; fp.y = tmp[1]; } } } } else if (im0.getWidth() == im1.getWidth() && (im1.getWidth() >> 1) == im2.getWidth()) { int end_x = (int)Math.Floor(((im2.getWidth() - 1) - 0.5f) * 2.0f + 0.5f); int end_y = (int)Math.Floor(((im2.getHeight() - 1) - 0.5f) * 2.0f + 0.5f); for (int row = 2; row < end_y; row++) { int im0_ym1 = im0.get(row - 1); int im0_y = im0.get(row); int im0_yp1 = im0.get(row + 1); int im1_ym1 = im1.get(row - 1); int im1_y = im1.get(row); int im1_yp1 = im1.get(row + 1); for (int col = 2; col < end_x; col++) { double value = im1b[im1_y + col]; // Check laplacian score if ((value * value) < laplacianSqrThreshold) { continue; } // Compute downsampled point location double ds_x = col * 0.5f - 0.25f; double ds_y = row * 0.5f - 0.25f; bool extrema = false; if ( /* im0 - 9 evaluations */ value > im0b[im0_ym1 + col - 1] && value > im0b[im0_ym1 + col] && value > im0b[im0_ym1 + col + 1] && value > im0b[im0_y + col - 1] && value > im0b[im0_y + col] && value > im0b[im0_y + col + 1] && value > im0b[im0_yp1 + col - 1] && value > im0b[im0_yp1 + col] && value > im0b[im0_yp1 + col + 1] && /* im1 - 8 evaluations */ value > im1b[im1_ym1 + col - 1] && value > im1b[im1_ym1 + col] && value > im1b[im1_ym1 + col + 1] && value > im1b[im1_y + col - 1] && value > im1b[im1_y + col + 1] && value > im1b[im1_yp1 + col - 1] && value > im1b[im1_yp1 + col] && value > im1b[im1_yp1 + col + 1] && /* im2 - 9 evaluations */ value > im2.bilinearInterpolation(ds_x - 0.5f, ds_y - 0.5f) && value > im2.bilinearInterpolation(ds_x, ds_y - 0.5f) && value > im2.bilinearInterpolation(ds_x + 0.5f, ds_y - 0.5f) && value > im2.bilinearInterpolation(ds_x - 0.5f, ds_y) && value > im2.bilinearInterpolation(ds_x, ds_y) && value > im2.bilinearInterpolation(ds_x + 0.5f, ds_y) && value > im2.bilinearInterpolation(ds_x - 0.5f, ds_y + 0.5f) && value > im2.bilinearInterpolation(ds_x, ds_y + 0.5f) && value > im2.bilinearInterpolation(ds_x + 0.5f, ds_y + 0.5f)) { extrema = true; } else if ( /* im0 - 9 evaluations */ value < im0b[im0_ym1 + col - 1] && value < im0b[im0_ym1 + col] && value < im0b[im0_ym1 + col + 1] && value < im0b[im0_y + col - 1] && value < im0b[im0_y + col] && value < im0b[im0_y + col + 1] && value < im0b[im0_yp1 + col - 1] && value < im0b[im0_yp1 + col] && value < im0b[im0_yp1 + col + 1] && /* im1 - 8 evaluations */ value < im1b[im1_ym1 + col - 1] && value < im1b[im1_ym1 + col] && value < im1b[im1_ym1 + col + 1] && value < im1b[im1_y + col - 1] && value < im1b[im1_y + col + 1] && value < im1b[im1_yp1 + col - 1] && value < im1b[im1_yp1 + col] && value < im1b[im1_yp1 + col + 1] && /* im2 - 9 evaluations */ value < im2.bilinearInterpolation(ds_x - 0.5f, ds_y - 0.5f) && value < im2.bilinearInterpolation(ds_x, ds_y - 0.5f) && value < im2.bilinearInterpolation(ds_x + 0.5f, ds_y - 0.5f) && value < im2.bilinearInterpolation(ds_x - 0.5f, ds_y) && value < im2.bilinearInterpolation(ds_x, ds_y) && value < im2.bilinearInterpolation(ds_x + 0.5f, ds_y) && value < im2.bilinearInterpolation(ds_x - 0.5f, ds_y + 0.5f) && value < im2.bilinearInterpolation(ds_x, ds_y + 0.5f) && value < im2.bilinearInterpolation(ds_x + 0.5f, ds_y + 0.5f)) { extrema = true; } if (extrema) { DogFeaturePoint fp = i_dog_fp.prePush(); if (fp == null) { prepush_warning(); break; } fp.octave = octave; fp.scale = scale; fp.score = value; fp.sigma = pyramid.effectiveSigma(octave, scale); double[] tmp = new double[2]; bilinear_upsample_point(tmp, col, row, octave); fp.x = tmp[0]; fp.y = tmp[1]; } } } } else if ((im0.getWidth() >> 1) == im1.getWidth() && (im0.getWidth() >> 1) == im2.getWidth()) { int width_minus_1 = im1.getWidth() - 1; int height_minus_1 = im1.getHeight() - 1; for (int row = 1; row < height_minus_1; row++) { int im1_ym1 = im1.get(row - 1); int im1_y = im1.get(row); int im1_yp1 = im1.get(row + 1); int im2_ym1 = im2.get(row - 1); int im2_y = im2.get(row); int im2_yp1 = im2.get(row + 1); for (int col = 1; col < width_minus_1; col++) { double value = im1b[im1_y + col]; // Check laplacian score if ((value * value) < laplacianSqrThreshold) { continue; } double us_x = (col << 1) + 0.5f; double us_y = (row << 1) + 0.5f; bool extrema = false; if (value > im1b[im1_ym1 + col - 1] && value > im1b[im1_ym1 + col] && value > im1b[im1_ym1 + col + 1] && value > im1b[im1_y + col - 1] && value > im1b[im1_y + col + 1] && value > im1b[im1_yp1 + col - 1] && value > im1b[im1_yp1 + col] && value > im1b[im1_yp1 + col + 1] && /* im2 - 9 evaluations */ value > im2b[im2_ym1 + col - 1] && value > im2b[im2_ym1 + col] && value > im2b[im2_ym1 + col + 1] && value > im2b[im2_y + col - 1] && value > im2b[im2_y + col] && value > im2b[im2_y + col + 1] && value > im2b[im2_yp1 + col - 1] && value > im2b[im2_yp1 + col] && value > im2b[im2_yp1 + col + 1] && /* im2 - 9 evaluations */ value > im0.bilinearInterpolation(us_x - 2.0f, us_y - 2.0f) && value > im0.bilinearInterpolation(us_x, us_y - 2.0f) && value > im0.bilinearInterpolation(us_x + 2.0f, us_y - 2.0f) && value > im0.bilinearInterpolation(us_x - 2.0f, us_y) && value > im0.bilinearInterpolation(us_x, us_y) && value > im0.bilinearInterpolation(us_x + 2.0f, us_y) && value > im0.bilinearInterpolation(us_x - 2.0f, us_y + 2.0f) && value > im0.bilinearInterpolation(us_x, us_y + 2.0f) && value > im0.bilinearInterpolation(us_x + 2.0f, us_y + 2.0f)) { extrema = true; } else if (value < im1b[im1_ym1 + col - 1] && value < im1b[im1_ym1 + col] && value < im1b[im1_ym1 + col + 1] && value < im1b[im1_y + col - 1] && value < im1b[im1_y + col + 1] && value < im1b[im1_yp1 + col - 1] && value < im1b[im1_yp1 + col] && value < im1b[im1_yp1 + col + 1] && /* im2 - 9 evaluations */ value < im2b[im2_ym1 + col - 1] && value < im2b[im2_ym1 + col] && value < im2b[im2_ym1 + col + 1] && value < im2b[im2_y + col - 1] && value < im2b[im2_y + col] && value < im2b[im2_y + col + 1] && value < im2b[im2_yp1 + col - 1] && value < im2b[im2_yp1 + col] && value < im2b[im2_yp1 + col + 1] && /* im2 - 9 evaluations */ value < im0.bilinearInterpolation(us_x - 2.0f, us_y - 2.0f) && value < im0.bilinearInterpolation(us_x, us_y - 2.0f) && value < im0.bilinearInterpolation(us_x + 2.0f, us_y - 2.0f) && value < im0.bilinearInterpolation(us_x - 2.0f, us_y) && value < im0.bilinearInterpolation(us_x, us_y) && value < im0.bilinearInterpolation(us_x + 2.0f, us_y) && value < im0.bilinearInterpolation(us_x - 2.0f, us_y + 2.0f) && value < im0.bilinearInterpolation(us_x, us_y + 2.0f) && value < im0.bilinearInterpolation(us_x + 2.0f, us_y + 2.0f)) { extrema = true; } if (extrema) { DogFeaturePoint fp = i_dog_fp.prePush(); if (fp == null) { prepush_warning(); break; } fp.octave = octave; fp.scale = scale; fp.score = value; fp.sigma = pyramid.effectiveSigma(octave, scale); double[] tmp = new double[2]; bilinear_upsample_point(tmp, col, row, octave); fp.x = tmp[0]; fp.y = tmp[1]; } } } } } return; }