#!/usr/bin/env python3 """Full digitization on samples/board.png (i10): exact Preprocess grid (with the 3rd-from-bottom line removed) + exact bbox+90 crop + classify, vs known FEN.""" import cv2 as cv import numpy as np import onnxruntime as ort import hough_pipeline as hp TRUE = "rn1qkb1r/pb2pppp/5n2/1ppp4/8/3P1NP1/PPP1PPBP/RNBQ1RK1" IDX2SYM = {0:"K",1:"Q",2:"R",3:"B",4:"N",5:"P",6:"k",7:"q",8:"r",9:"b",10:"n",11:"p"} def get_casas(path): im = hp.crop_image(cv.imread(path)) board = hp.filter_board_lines(hp.group_lines(hp.detect_lines(hp.detect_edges(im)))) rows = hp.compute_intersections(board) by_y = sorted(rows, key=lambda r: np.mean([p[1] for p in r]), reverse=True) rows = [r for r in rows if r is not by_y[2]] return im, hp.build_squares(rows) def crop_square(im, p): xs = [pt[0] for pt in p]; ys = [pt[1] for pt in p] x_min, x_max = min(xs), max(xs); y_min, y_max = min(ys), max(ys) return im[max(0, y_min - 90):y_max, x_min:x_max] def true_grid(): g = [] for row in TRUE.split("/"): r = [] for ch in row: r += ["."] * int(ch) if ch.isdigit() else [ch] g.append(r) return np.array(g) def main(): im, casas = get_casas("samples/board.png") print("squares:", len(casas)) if len(casas) != 64: return crops = [crop_square(im, p) for p in casas[:64]] sess = ort.InferenceSession("models_onnx/digitizer.fp32.onnx", providers=["CPUExecutionProvider"]) T = true_grid(); occ = (T != "."); n = int(occ.sum()) for nm, fn in [("/255", lambda r: r/255.0), ("imagenet", lambda r: (r/255.0-[0.485,0.456,0.406])/[0.229,0.224,0.225]), ("[-1,1]", lambda r: r/127.5-1)]: syms = [] for c in crops: if c.size == 0: syms.append("?"); continue rgb = cv.cvtColor(cv.resize(c, (96, 96)), cv.COLOR_BGR2RGB).astype(np.float32) x = np.asarray(fn(rgb), np.float32).transpose(2, 0, 1)[None] out = sess.run(None, {"input": x})[0].flatten() syms.append(IDX2SYM[int(out.argmax())]) P = np.array(syms, object).reshape(8, 8) best = max( (int(((Q == T) & occ).sum()), k) for k, Q in [("id", P), ("rot90", np.rot90(P)), ("rot180", np.rot90(P, 2)), ("rot270", np.rot90(P, 3)), ("flipUD", np.flipud(P)), ("flipLR", np.fliplr(P)), ("T", P.T), ("anti", np.fliplr(np.rot90(P)))] ) print(f"[{nm:9s}] best occupied-match {best[0]:2d}/{n} ({best[1]})") if __name__ == "__main__": main()