/**
   * Detects Shi-Tomasi corners.
   *
   * @param configDetector Configuration for feature detector.
   * @param weighted Is a Gaussian weight applied to the sample region? False is much faster.
   * @param derivType Type of derivative image.
   * @see boofcv.alg.feature.detect.intensity.ShiTomasiCornerIntensity
   */
  public static <T extends ImageSingleBand, D extends ImageSingleBand>
      GeneralFeatureDetector<T, D> createShiTomasi(
          ConfigGeneralDetector configDetector, boolean weighted, Class<D> derivType) {
    if (configDetector == null) configDetector = new ConfigGeneralDetector();

    GradientCornerIntensity<D> cornerIntensity =
        FactoryIntensityPointAlg.shiTomasi(configDetector.radius, weighted, derivType);
    return createGeneral(cornerIntensity, configDetector);
  }
  public IntensityFeatureScaleSpacePyramidApp(Class<T> imageType, Class<D> derivType) {
    super(1);
    this.imageType = imageType;

    addAlgorithm(
        0,
        "Hessian Det",
        new WrapperHessianBlobIntensity<T, D>(HessianBlobIntensity.Type.DETERMINANT, derivType));
    addAlgorithm(
        0,
        "Laplacian",
        new WrapperHessianBlobIntensity<T, D>(HessianBlobIntensity.Type.TRACE, derivType));
    addAlgorithm(
        0,
        "Harris",
        new WrapperGradientCornerIntensity<T, D>(
            FactoryIntensityPointAlg.harris(2, 0.4f, false, derivType)));
    addAlgorithm(
        0,
        "Shi Tomasi",
        new WrapperGradientCornerIntensity<T, D>(
            FactoryIntensityPointAlg.shiTomasi(2, false, derivType)));
    addAlgorithm(
        0,
        "FAST 12",
        new WrapperFastCornerIntensity<T, D>(FactoryIntensityPointAlg.fast12(5, 11, imageType)));
    addAlgorithm(0, "KitRos", new WrapperKitRosCornerIntensity<T, D>(derivType));
    addAlgorithm(
        0,
        "Median",
        new WrapperMedianCornerIntensity<T, D>(FactoryBlurFilter.median(imageType, 2), imageType));

    setMainGUI(gui);

    double scales[] = new double[25];
    for (int i = 0; i < scales.length; i++) {
      scales[i] = Math.exp(i * 0.15);
    }
    pyramid = new ScaleSpacePyramid<T>(imageType, scales);

    anyDerivative =
        GImageDerivativeOps.createDerivatives(imageType, FactoryImageGenerator.create(derivType));
  }
  /**
   * Creates a Fast corner detector.
   *
   * @param configFast Configuration for FAST feature detector
   * @param configDetector Configuration for feature extractor.
   * @param imageType Type of input image.
   * @see FastCornerIntensity
   */
  @SuppressWarnings("UnnecessaryLocalVariable")
  public static <T extends ImageSingleBand, D extends ImageSingleBand>
      GeneralFeatureDetector<T, D> createFast(
          ConfigFast configFast, ConfigGeneralDetector configDetector, Class<T> imageType) {

    if (configFast == null) configFast = new ConfigFast();
    configFast.checkValidity();

    ConfigGeneralDetector d = configDetector;

    FastCornerIntensity<T> alg =
        FactoryIntensityPointAlg.fast(configFast.pixelTol, configFast.minContinuous, imageType);
    GeneralFeatureIntensity<T, D> intensity = new WrapperFastCornerIntensity<T, D>(alg);
    ConfigGeneralDetector configExtract =
        new ConfigGeneralDetector(d.maxFeatures, d.radius, d.threshold, 0, true, false, true);
    return createGeneral(intensity, configExtract);
  }