sclass BWII_MultiPatternFinder implements Iterable<FoundImg> {
  new L<BWImage> patternImages;
  L<Int> scaleWidths = ll(25, 35, 50, 75, 100); // widths to scale input image to
  
  transient BWIntegralImage ii;
  transient IBWImage scaled;
  transient BWImage pattern;
  transient FoundImg found;
  transient int currentScaleWidth;
  
  *() {}
  *(L<BWImage> *patternImages, BWIntegralImage *ii) {}
  
  // only call once
  public Iterator<FoundImg> iterator() {
    ret nonNullIterator(nestedIterator(scaleWidths, func(int scaleWidth) -> Iterator<FoundImg> {
      currentScaleWidth = scaleWidth;
      ret mapI(patternImages, func(BWImage pat) {
        pattern = pat;
        FoundImg lastFound = found;
        if (scaled == null || scaled.getWidth() != scaleWidth)
          scaled = virtualScaledIntegralImageBW(ii, scaleWidth);
        FoundImg found2 = bwImageSearch_best_virtualBig(scaled, pat, found == null ? 0f : found.sim);
        if (found2 != null)
          ret found = found2;
        null;
      });
    }));
  }
}