docs: public void process(I image, D derivX, D derivY, D derivXX, D derivYY, D derivXY) {
  		intensity.process(image, derivX, derivY, derivXX, derivYY, derivXY);
  		GrayF32 intensityImage = intensity.getIntensity();
  
  		int numSelectMin = -1;
  		int numSelectMax = -1;
  		if( maxFeatures > 0 ) {
  			if( intensity.localMinimums() )
  				numSelectMin = excludeMinimum == null ? maxFeatures : maxFeatures - excludeMinimum.size;
  			if( intensity.localMaximums() )
  				numSelectMax = excludeMaximum == null ? maxFeatures : maxFeatures - excludeMaximum.size;
  
  			// return without processing if there is no room to detect any more features
  			if( numSelectMin <= 0 && numSelectMax <= 0 )
  				return;
  		}
  
  		// mark pixels that should be excluded
  		if( excludeMinimum != null ) {
  			for( int i = 0; i < excludeMinimum.size; i++ ) {
  				Point2D_I16 p = excludeMinimum.get(i);
  				intensityImage.set(p.x,p.y,-Float.MAX_VALUE);
  			}
  		}
  		if( excludeMaximum != null ) {
  			for( int i = 0; i < excludeMaximum.size; i++ ) {
  				Point2D_I16 p = excludeMaximum.get(i);
  				intensityImage.set(p.x,p.y,Float.MAX_VALUE);
  			}
  		}
  
  		foundMinimum.reset();
  		foundMaximum.reset();
  		if (intensity.hasCandidates()) {
  			extractor.process(intensityImage, intensity.getCandidatesMin(), intensity.getCandidatesMax(),foundMinimum, foundMaximum);
  		} else {
  			extractor.process(intensityImage, null, null,foundMinimum, foundMaximum);
  		}
  
  		// optionally select the most intense features only
  		selectBest(intensityImage, foundMinimum, numSelectMin, false);
  		selectBest(intensityImage, foundMaximum, numSelectMax, true);
  	}