sclass CheesyRecognizer { BWIntegralImage inputImage; new L prototypes; new Map scaledInputImages; // key = width class Prototype { BWIntegralImage image; new Map scaledPrototypes; // key = width ScaledPrototype scaledPrototype(int width) { ret mapGetOrCreate(scaledPrototypes, width, () -> new ScaledPrototype(this, scaleDownUsingIntegralImageBW(image, width))); } } class ScaledInputImage { BWImage image; *(BWImage *image) {} } class ScaledPrototype { Prototype prototype; BWImage image; *(Prototype *prototype, BWImage *image) {} } *(BWImage inputImage) { this.inputImage = bwIntegralImage(inputImage); } *(BufferedImage inputImage) { this(BWImage(inputImage)); } void fullScan(ScaledInputImage img, ScaledPrototype proto, float minSimilarity, IVF2 onFound) { bwImageSearch_onFound(img.image, proto.image, minSimilarity, onFound); } // compare scaled prototype to scaled image at some location Pair singleCheck(ScaledInputImage img, ScaledPrototype prototype, int x, int y, float minSimilarity) { BWImage proto = prototype.image, image = img.image; int wp = proto.getWidth(), hp = proto.getHeight(); float maxError = (1f-minSimilarity)*wp*hp; float diff = bwImageSectionsSimilarity(image, proto, x, y, maxError); ret diff > maxError ? null : pair(new Rect(x, y, wp, hp), (1-(double) diff)/(wp*hp)); } ScaledInputImage scaledInputImage(int width) { ret mapGetOrCreate(scaledInputImages, width, () -> new ScaledInputImage(scaleDownUsingIntegralImageBW(inputImage, width))); } }