// type parameter is rect + FEN // not persistable sclass ChessOCR_TwoStageRecognizer extends SteppableAndBest> { replace Segmenter with IF1>. // input BufferedImage inputImage; Iterator segmenterStream; ChessPieceRecognizer pieceRecognizer; bool verbose; // internal L rectQueue = syncLinkedList(); new Set rectsTried; *() {} *(ChessPieceRecognizer *pieceRecognizer, BufferedImage *inputImage, Iterator *segmenterStream) {} public bool step() { if (nempty(rectQueue)) ret true with tryRect(popFirst(rectQueue)); if (segmenterStream.hasNext()) { Segmenter seg = segmenterStream.next(); if (seg == null) true; L rects = seg.get(inputImage); addAll(rectQueue, rects); if (verbose) print("Segmenter " + seg + " returned: " + rects); true; } false; } // returns true if rect not seen before bool tryRect(Rect r) { r = rectSetHeightToWidth(r); // square it if (!rectsTried.add(r)) false; // seen BufferedImage board = clipBufferedImage(inputImage, r); S fen, double score = unpair chessOCR_recognizeBoard_FENAndScore(board, pieceRecognizer); if (verbose) print("Score " + score + " for rect: " + r); best.put(pair(r, fen), score); true; } void verbose(bool verbose) { best.verboseNewBest = this.verbose = verbose; } Rect bestBoardLocation() { ret pairA(best!); } Pair boardLocationAndScore() { ret pair(pairA(best!), score()); } }