/**
   * Use the feature detector to find candidate features in each level. Only compute the needed
   * image derivatives.
   */
  private void detectCandidateFeatures(GaussianScaleSpace<T, D> ss, double scale) {
    // adjust corner intensity threshold based upon the current scale factor
    float scaleThreshold = (float) (baseThreshold / Math.pow(scale, scalePower));
    detector.setThreshold(scaleThreshold);

    D derivX = null, derivY = null;
    D derivXX = null, derivYY = null, derivXY = null;

    if (detector.getRequiresGradient()) {
      derivX = ss.getDerivative(true);
      derivY = ss.getDerivative(false);
    }
    if (detector.getRequiresHessian()) {
      derivXX = ss.getDerivative(true, true);
      derivYY = ss.getDerivative(false, false);
      derivXY = ss.getDerivative(true, false);
    }

    T image = ss.getScaledImage();
    detector.process(image, derivX, derivY, derivXX, derivYY, derivXY);
    List<Point2D_I16> m = maximums[spaceIndex];
    m.clear();
    QueueCorner q = detector.getFeatures();
    for (int i = 0; i < q.size; i++) {
      m.add(q.get(i).copy());
    }
  }
  /**
   * Create a feature detector.
   *
   * @param detector Point feature detector which is used to find candidates in each scale level
   * @param scalePower Used to adjust feature intensity in each level to make them comparable.
   *     Feature dependent, but most common features should use a value of 2.
   */
  public FeatureLaplaceScaleSpace(
      GeneralFeatureDetector<T, D> detector,
      ImageFunctionSparse<T> sparseLaplace,
      double scalePower) {
    this.detector = detector;
    this.sparseLaplace = sparseLaplace;
    this.baseThreshold = detector.getThreshold();
    this.scalePower = scalePower;

    localSpace = (T[]) new ImageSingleBand[3];

    maximums = new List[3];
    maximums[0] = new ArrayList<Point2D_I16>();
    maximums[1] = new ArrayList<Point2D_I16>();
    maximums[2] = new ArrayList<Point2D_I16>();
  }