Libraryless. Click here for Pure Java version (7473L/50K).
1 | // thread-safe except for analysis output fields |
2 | sclass ChessPieceRecognizer { |
3 | MultiMap<S, ChessPieceProfile1> profiles; |
4 | double magicCombineFactor = 0.0012589254117941495; |
5 | int version = 1; |
6 | |
7 | // for analysis |
8 | transient Pair<Pair<S, ChessPieceProfile1>, Double> best, runnerUp; |
9 | |
10 | void load { |
11 | long time = sysNow(); |
12 | profiles = agiBlue_chessPieceProfiles(agiBlue_chessPieceImages_loadedMultiMap(), +version); |
13 | compact(); |
14 | done2("Loading " + n2(l(profiles), "piece profile"), time); |
15 | } |
16 | |
17 | void compact { |
18 | int n = l(profiles); |
19 | profiles = uniquifyMultiMapValues(profiles); |
20 | int m = l(profiles); |
21 | if (m < n) |
22 | print("Compacted ChessPieceRecognizer " + n + " => " + m); |
23 | internByteArrayField sideProfile(values(profiles)); |
24 | } |
25 | |
26 | Pair<S, Double> recognize(BufferedImage img) { |
27 | ChessPieceProfile1 profile = chessOCR_pieceProfileFromRawImage_1(img); |
28 | new Lowest_withRunnerUp<Pair<S, ChessPieceProfile1>> lowest; |
29 | |
30 | for (unpair S piece, ChessPieceProfile1 p : multiMapToPairs(profiles)) { |
31 | float sideProfileDiff = floatRatio(byteArraysTotalDiff(profile.sideProfile, p.sideProfile), l(p.sideProfile)); |
32 | float fillGradeDiff = abs(profile.fillGrade-p.fillGrade); |
33 | double score = magicCombine(sideProfileDiff, fillGradeDiff); |
34 | lowest.put(pair(piece, p), score); |
35 | } |
36 | best = lowest.pair(); |
37 | runnerUp = lowest.runnerUpPair(); |
38 | ret !lowest.has() ? null : pair(pairA(lowest!), errorToPercent(lowest.score())); |
39 | } |
40 | |
41 | // for humans |
42 | double errorToPercent(double d) { |
43 | ret 100-d; |
44 | } |
45 | |
46 | double magicCombine(double sideProfileScore, double fillGradeScore) { |
47 | double sum = sideProfileScore+fillGradeScore/magicCombineFactor; |
48 | //print("magicCombine " + sideProfileScore + "*" + magicCombineFactor + "+" + fillGradeScore + " = " + sum); |
49 | ret sum; |
50 | } |
51 | |
52 | toString { |
53 | ret shortClassName(this) + "(v" + version + ", " + nProfiles(l(profiles)) + ")"; |
54 | } |
55 | |
56 | ChessOCR_RecognizedBoard recognizeBoard(BufferedImage board) { |
57 | new ChessOCR_RecognizedBoard out; |
58 | LL<BufferedImage> squareImages = bufferedImageMNGrid(board, 8, 8); |
59 | out.pieces = new L; |
60 | for (BufferedImage img : concatLists(squareImages)) |
61 | out.pieces.add(recognize(img)); |
62 | out.score = doubleAvg(pairsB(out.pieces)); |
63 | out.fen = chess_makeFEN(listToChunks(8, pairsA(out.pieces))); |
64 | ret out; |
65 | } |
66 | } |
download show line numbers debug dex old transpilations
Travelled to 6 computer(s): bhatertpkbcr, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tvejysmllsmz, vouqrxazstgt
No comments. add comment
Snippet ID: | #1024689 |
Snippet name: | ChessPieceRecognizer |
Eternal ID of this version: | #1024689/47 |
Text MD5: | 93d99af4deaacecb1663a2d71a8344d5 |
Transpilation MD5: | 435cb478305a5a3887093a8a4c9cae64 |
Author: | stefan |
Category: | javax / image recognition |
Type: | JavaX fragment (include) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2019-08-28 16:45:35 |
Source code size: | 2433 bytes / 66 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 473 / 1007 |
Version history: | 46 change(s) |
Referenced in: | [show references] |