docs: protected void detectionCascade( FastQueue<ImageRectangle> cascadeRegions ) {
  
  		// initialize data structures
  		success = false;
  		ambiguous = false;
  		best = null;
  		candidateDetections.reset();
  		localMaximums.reset();
  		ambiguousRegions.clear();
  
  		storageMetric.reset();
  		storageIndexes.reset();
  		storageRect.clear();
  		fernRegions.clear();
  
  		fernInfo.reset();
  
  		int totalP = 0;
  		int totalN = 0;
  
  		// Run through all candidate regions, ignore ones without enough variance, compute
  		// the fern for each one
  		TldRegionFernInfo info = fernInfo.grow();
  		for( int i = 0; i < cascadeRegions.size; i++ ) {
  			ImageRectangle region = cascadeRegions.get(i);
  
  			if( !variance.checkVariance(region)) {
  				continue;
  			}
  
  			info.r = region;
  
  			if( fern.lookupFernPN(info)) {
  				totalP += info.sumP;
  				totalN += info.sumN;
  				info = fernInfo.grow();
  			}
  		}
  		fernInfo.removeTail();
  
  		// avoid overflow errors in the future by re-normalizing the Fern detector
  		if( totalP > 0x0fffffff)
  			fern.renormalizeP();
  		if( totalN > 0x0fffffff)
  			fern.renormalizeN();
  
  		// Select the ferns with the highest likelihood
  		selectBestRegionsFern(totalP, totalN);
  
  		// From the remaining regions, score using the template algorithm
  		computeTemplateConfidence();
  
  		if( candidateDetections.size == 0 ) {
  			return;
  		}
  
  		// use non-maximum suppression to reduce the number of candidates
  		nonmax.process(candidateDetections, localMaximums);
  
  		best = selectBest();
  		if( best != null ) {
  			ambiguous = checkAmbiguous(best);
  
  			success = true;
  		}
  	}