├── .prettierignore ├── .eslintrc.yml ├── run ├── .eslintrc.yml ├── listInstalledFonts.js ├── testOCR.js ├── fontAnalysis.js ├── testMRZ.js ├── createFontFingerprint.js └── testRotation.js ├── demo ├── id1.jpg ├── id2.jpg ├── id3.jpg ├── id4.jpg ├── id5.jpg ├── id6.jpg ├── iwona.png ├── ocrb.png ├── test.odt ├── dejavusans.png ├── driving_CH.jpg ├── passport1.jpg ├── passport2.jpg ├── passport3.jpg ├── passport4.jpg ├── passport5.jpg ├── passport6.jpg ├── passport7.jpg ├── passport8.jpg └── passport9.jpg ├── .gitignore ├── .travis.yml ├── src ├── util │ ├── byteArrayToBinary.js │ ├── loadFontData.js │ ├── setFingerprintDataOnRoi.js │ ├── saveFontData.js │ ├── getFontDataFilename.js │ ├── loadAllFontData.js │ ├── getInstalledRegularFonts.js │ ├── bestMatch.js │ ├── symbolClasses.js │ ├── appendFingerprints.js │ ├── groupRoisPerLine.js │ ├── tanimotoSimilarity.js │ ├── generateSymbolImage.js │ ├── ambiguitySolver.js │ ├── doOcrOnLines.js │ └── getLinesFromImage.js ├── index.js ├── runOCR.js ├── runFontAnalysis.js ├── getRotation.js └── createFontFingerprint.js ├── History.md ├── LICENSE ├── README.md └── package.json /.prettierignore: -------------------------------------------------------------------------------- 1 | package*.json -------------------------------------------------------------------------------- /.eslintrc.yml: -------------------------------------------------------------------------------- 1 | extends: cheminfo 2 | -------------------------------------------------------------------------------- /run/.eslintrc.yml: -------------------------------------------------------------------------------- 1 | rules: 2 | no-console: off 3 | -------------------------------------------------------------------------------- /demo/id1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-js/ocr-tools/HEAD/demo/id1.jpg -------------------------------------------------------------------------------- /demo/id2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-js/ocr-tools/HEAD/demo/id2.jpg -------------------------------------------------------------------------------- /demo/id3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-js/ocr-tools/HEAD/demo/id3.jpg -------------------------------------------------------------------------------- /demo/id4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-js/ocr-tools/HEAD/demo/id4.jpg -------------------------------------------------------------------------------- /demo/id5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-js/ocr-tools/HEAD/demo/id5.jpg -------------------------------------------------------------------------------- /demo/id6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-js/ocr-tools/HEAD/demo/id6.jpg -------------------------------------------------------------------------------- /demo/iwona.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-js/ocr-tools/HEAD/demo/iwona.png -------------------------------------------------------------------------------- /demo/ocrb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-js/ocr-tools/HEAD/demo/ocrb.png -------------------------------------------------------------------------------- /demo/test.odt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-js/ocr-tools/HEAD/demo/test.odt -------------------------------------------------------------------------------- /demo/dejavusans.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-js/ocr-tools/HEAD/demo/dejavusans.png -------------------------------------------------------------------------------- /demo/driving_CH.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-js/ocr-tools/HEAD/demo/driving_CH.jpg -------------------------------------------------------------------------------- /demo/passport1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-js/ocr-tools/HEAD/demo/passport1.jpg -------------------------------------------------------------------------------- /demo/passport2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-js/ocr-tools/HEAD/demo/passport2.jpg -------------------------------------------------------------------------------- /demo/passport3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-js/ocr-tools/HEAD/demo/passport3.jpg -------------------------------------------------------------------------------- /demo/passport4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-js/ocr-tools/HEAD/demo/passport4.jpg -------------------------------------------------------------------------------- /demo/passport5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-js/ocr-tools/HEAD/demo/passport5.jpg -------------------------------------------------------------------------------- /demo/passport6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-js/ocr-tools/HEAD/demo/passport6.jpg -------------------------------------------------------------------------------- /demo/passport7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-js/ocr-tools/HEAD/demo/passport7.jpg -------------------------------------------------------------------------------- /demo/passport8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-js/ocr-tools/HEAD/demo/passport8.jpg -------------------------------------------------------------------------------- /demo/passport9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/image-js/ocr-tools/HEAD/demo/passport9.jpg -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .idea 3 | logs 4 | *.log 5 | npm-debug.log* 6 | coverage 7 | /png 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 10 4 | - 8 5 | script: "npm run test-travis " 6 | after_script: "npm install coveralls@2 && cat ./coverage/lcov.info | coveralls" 7 | -------------------------------------------------------------------------------- /run/listInstalledFonts.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var getInstalledRegularFonts = require('../src/util/getInstalledRegularFonts'); 4 | 5 | 6 | var names = getInstalledRegularFonts(); 7 | 8 | 9 | names = names.filter((a) => a.toLowerCase().indexOf('ocr') >= 0); 10 | 11 | console.log(names); 12 | 13 | -------------------------------------------------------------------------------- /src/util/byteArrayToBinary.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const zero = '0'.repeat(10); 4 | module.exports = function byteArrayToBinary(array) { 5 | const result = []; 6 | for (const element of array) { 7 | const binary = element.toString(2); 8 | result.push(zero.substring(0, 8 - binary.length) + binary); 9 | } 10 | return result.join(''); 11 | }; 12 | -------------------------------------------------------------------------------- /src/util/loadFontData.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const fs = require('fs'); 4 | const { join } = require('path'); 5 | 6 | var getFontDataFilename = require('./getFontDataFilename'); 7 | 8 | module.exports = function loadFontData(options = {}) { 9 | var file = getFontDataFilename(options); 10 | return JSON.parse(fs.readFileSync(join(file.folder, file.name))); 11 | }; 12 | -------------------------------------------------------------------------------- /src/util/setFingerprintDataOnRoi.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = function (lines, options) { 4 | for (let line of lines) { 5 | for (let roi of line.rois) { 6 | var small = roi.getMask().scale({ 7 | width: options.width, 8 | height: options.height 9 | }); 10 | roi.data = Array.from(small.data); 11 | } 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | getLinesFromImage: require('./util/getLinesFromImage'), 5 | doOcrOnLines: require('./util/doOcrOnLines'), 6 | groupRoisPerLine: require('./util/groupRoisPerLine'), 7 | runFontAnalysis: require('./runFontAnalysis'), 8 | loadAllFontData: require('./util/loadAllFontData'), 9 | loadFontData: require('./util/loadFontData'), 10 | generateSymbolImage: require('./util/generateSymbolImage') 11 | }; 12 | -------------------------------------------------------------------------------- /src/runOCR.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const getLinesFromImage = require('./util/getLinesFromImage'); 4 | const doOcrOnLines = require('./util/doOcrOnLines'); 5 | const setFingerprintDataOnRoi = require('./util/setFingerprintDataOnRoi'); 6 | 7 | module.exports = function runOCR(image, fontFingerprint, options = {}) { 8 | const lines = getLinesFromImage(image, options); 9 | setFingerprintDataOnRoi(lines, options.fingerprintOptions); 10 | return doOcrOnLines(lines, fontFingerprint, options.fingerprintOptions); 11 | }; 12 | -------------------------------------------------------------------------------- /src/util/saveFontData.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | 4 | const fs = require('fs'); 5 | 6 | const mkdirp = require('mkdirp'); 7 | 8 | const getFingerprintName = require('./getFontDataFilename'); 9 | 10 | module.exports = function saveFingerprint(fingerprint, options = {}) { 11 | const file = getFingerprintName(options); 12 | mkdirp.sync(file.folder); 13 | 14 | fs.writeFileSync( 15 | file.folder + file.name, 16 | JSON.stringify({ 17 | font: options.fontName, 18 | fingerprint 19 | }) 20 | ); 21 | }; 22 | -------------------------------------------------------------------------------- /src/util/getFontDataFilename.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const { join } = require('path'); 4 | 5 | module.exports = function getFingerprintsName(options = {}) { 6 | var { 7 | width = 8, 8 | height = 8, 9 | category = '', 10 | fontName = 'helvetica', 11 | baseDir = 'fontFingerprint' 12 | } = options; 13 | 14 | fontName = fontName.toLowerCase().replace(/[^a-zA-Z0-9]/g, '_'); 15 | fontName = fontName.replace(/_?regular$/, ''); 16 | 17 | const kind = `${width}x${height}`; 18 | return { 19 | folder: join(baseDir, kind, category), 20 | name: `${fontName}.json` 21 | }; 22 | }; 23 | -------------------------------------------------------------------------------- /src/util/loadAllFontData.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const fs = require('fs'); 4 | const { join } = require('path'); 5 | 6 | var getFontDataFilename = require('./getFontDataFilename'); 7 | 8 | module.exports = function loadAllFontData(options = {}) { 9 | var fingerprints = []; 10 | 11 | var folder = getFontDataFilename(options).folder; 12 | 13 | var dir = fs.readdirSync(folder); 14 | 15 | for (var file of dir) { 16 | var fontData = JSON.parse(fs.readFileSync(join(folder, file))); 17 | fontData.filneme = folder + file; 18 | fingerprints.push(fontData); 19 | } 20 | 21 | return fingerprints; 22 | }; 23 | -------------------------------------------------------------------------------- /src/util/getInstalledRegularFonts.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // eslint-disable-next-line 4 | const fontManager = require('font-manager'); 5 | 6 | module.exports = function getInstalledRegularFonts() { 7 | const fonts = fontManager.getAvailableFontsSync(); 8 | const regular = fonts.filter((a) => a.style === 'Regular'); 9 | 10 | let names = regular.map((a) => a.postscriptName); 11 | // this is not really enough ... and we get rid of the font that contains some Bold, Italic or other 12 | names = names.filter(function (a) { 13 | return !a 14 | .toLowerCase() 15 | .match(/(condensed|light|bold|extra|black|narrow|medium)/); 16 | }); 17 | 18 | return names.sort(); 19 | }; 20 | -------------------------------------------------------------------------------- /src/util/bestMatch.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const tanimotoSimilarity = require('./tanimotoSimilarity'); 4 | 5 | module.exports = function bestMatch(targetFingerprint, fontData) { 6 | const bestMatch = { 7 | similarity: 0 8 | }; 9 | 10 | for (const symbolFingerprint of fontData.fingerprint) { 11 | for (const fingerprint of symbolFingerprint.fingerprints) { 12 | const similarity = tanimotoSimilarity(fingerprint, targetFingerprint); 13 | if (similarity >= bestMatch.similarity) { 14 | bestMatch.similarity = similarity; 15 | bestMatch.fingerprintOptions = fingerprint; 16 | bestMatch.symbol = symbolFingerprint.symbol; 17 | } 18 | } 19 | } 20 | return bestMatch; 21 | }; 22 | -------------------------------------------------------------------------------- /src/util/symbolClasses.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const LETTERS_NUMBERS = { symbols: [], label: 'lettersNumbers' }; 4 | const NUMBERS = { symbols: [], label: 'numbers' }; 5 | const MRZ = { symbols: [], label: 'numbers' }; 6 | 7 | for (let i = '0'.charCodeAt(0); i <= '9'.charCodeAt(0); i++) { 8 | LETTERS_NUMBERS.symbols.push(i); 9 | NUMBERS.symbols.push(i); 10 | MRZ.symbols.push(i); 11 | } 12 | for (let i = 'A'.charCodeAt(0); i <= 'Z'.charCodeAt(0); i++) { 13 | LETTERS_NUMBERS.symbols.push(i); 14 | MRZ.symbols.push(i); 15 | } 16 | for (let i = 'a'.charCodeAt(0); i <= 'z'.charCodeAt(0); i++) { 17 | LETTERS_NUMBERS.symbols.push(i); 18 | } 19 | 20 | MRZ.symbols.push('<'.charCodeAt(0)); 21 | 22 | module.exports = { 23 | LETTERS_NUMBERS, 24 | NUMBERS, 25 | MRZ 26 | }; 27 | -------------------------------------------------------------------------------- /src/util/appendFingerprints.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const tanimotoSimilarity = require('./tanimotoSimilarity'); 4 | 5 | module.exports = function appendFingerprints(lines, options = {}) { 6 | const { 7 | maxSimilarity = 1 // over this value we don't add the fingerprintOptions 8 | } = options; 9 | for (const line of lines.lines) { 10 | if (!line.fingerprints) line.fingerprints = []; 11 | for (const roi of line.rois) { 12 | let isNew = true; 13 | for (const fingerprint of line.fingerprints) { 14 | if (tanimotoSimilarity(fingerprint, roi.data) >= maxSimilarity) { 15 | isNew = false; 16 | break; 17 | } 18 | } 19 | if (isNew) { 20 | line.fingerprints.push(roi.data); 21 | } 22 | } 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /src/runFontAnalysis.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const doOcrOnLines = require('./util/doOcrOnLines'); 4 | const getLinesFromImage = require('./util/getLinesFromImage'); 5 | const setFingerprintDataOnRoi = require('./util/setFingerprintDataOnRoi'); 6 | 7 | module.exports = function runFontAnalysis(image, allFontData, options = {}) { 8 | const lines = getLinesFromImage(image, options).lines; 9 | setFingerprintDataOnRoi(lines, options.fingerprintOptions); 10 | var fingerprintOptions = Object.assign({}, options.fingerprintOptions, { 11 | minSimilarity: 0.9 12 | }); 13 | 14 | const results = []; 15 | for (const fontData of allFontData) { 16 | var result = doOcrOnLines(lines, fontData, fingerprintOptions); 17 | result.fontName = fontData.font; 18 | results.push(result); 19 | } 20 | 21 | return results.sort((a, b) => b.totalSimilarity - a.totalSimilarity); 22 | }; 23 | -------------------------------------------------------------------------------- /History.md: -------------------------------------------------------------------------------- 1 | 2 | # [0.2.0](https://github.com/cheminfo-js/ocr/compare/v0.1.1...v0.2.0) (2018-07-26) 3 | 4 | 5 | 6 | 7 | ## [0.1.1](https://github.com/cheminfo-js/ocr/compare/v0.1.0...v0.1.1) (2018-05-23) 8 | 9 | 10 | ### Bug Fixes 11 | 12 | * install missing eslint plugin ([4780696](https://github.com/cheminfo-js/ocr/commit/4780696)) 13 | 14 | 15 | 16 | 17 | # [0.1.0](https://github.com/cheminfo-js/ocr/compare/v0.0.5...v0.1.0) (2018-04-13) 18 | 19 | 20 | 21 | 22 | ## [0.0.5](https://github.com/cheminfo-js/ocr/compare/v0.0.4...v0.0.5) (2018-03-20) 23 | 24 | 25 | 26 | 27 | ## [0.0.4](https://github.com/cheminfo-js/ocr/compare/v0.0.3...v0.0.4) (2018-03-15) 28 | 29 | 30 | 31 | 32 | ## [0.0.3](https://github.com/cheminfo-js/ocr/compare/v0.0.2...v0.0.3) (2018-01-29) 33 | 34 | 35 | 36 | 37 | ## 0.0.2 (2017-01-19) 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /src/getRotation.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const runOCR = require('./runOCR'); 4 | 5 | module.exports = function getRotation(image, fontFingerprint, options = {}) { 6 | var similarities = []; 7 | var result = runOCR(image, fontFingerprint, options); 8 | similarities.push({ 9 | rotation: 0, 10 | similarity: result.totalSimilarity 11 | }); 12 | for (var rotation = 90; rotation < 360; rotation += 90) { 13 | var rotated = image.rotate(rotation); 14 | result = runOCR(rotated, fontFingerprint, options); 15 | similarities.push({ 16 | rotation: rotation, 17 | similarity: result.totalSimilarity 18 | }); 19 | } 20 | similarities.sort(function (a, b) { 21 | return b.similarity - a.similarity; 22 | }); 23 | return { 24 | rotation: similarities[0].rotation, 25 | reliability: 26 | (similarities[0].similarity - similarities[1].similarity) / 27 | similarities[0].similarity * 28 | 100, 29 | similarities 30 | }; 31 | }; 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 image-js 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/util/groupRoisPerLine.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // we will sort the rois per line 4 | // we need to regroup per line 5 | module.exports = function groupRoisPerLine(rois, options = {}) { 6 | let { allowedShift } = options; 7 | rois = rois.slice(); 8 | 9 | if (!allowedShift) { 10 | // we take the average height / 5 11 | let total = 0; 12 | rois.forEach((a) => (total += a.height)); 13 | allowedShift = Math.round(total / rois.length / 2); 14 | } 15 | 16 | rois.sort(function (a, b) { 17 | return a.minX - b.minX; 18 | }); 19 | 20 | const lines = []; 21 | for (const roi of rois) { 22 | const x = roi.minX; 23 | const y = roi.minY; 24 | // is there a close line ? 25 | let currentLine; 26 | for (const line of lines) { 27 | if (Math.abs(line.y - y) <= allowedShift) { 28 | currentLine = line; 29 | break; 30 | } 31 | } 32 | if (!currentLine) { 33 | currentLine = { rois: [] }; 34 | lines.push(currentLine); 35 | } 36 | currentLine.y = y; 37 | currentLine.x = x; 38 | currentLine.rois.push(roi); 39 | } 40 | lines.sort((a, b) => a.y - b.y); 41 | 42 | return lines; 43 | }; 44 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ocr-tools 2 | 3 | [![NPM version][npm-imageoptions]][npm-url] 4 | [![build status][travis-imageoptions]][travis-url] 5 | [![Test coverage][coveralls-imageoptions]][coveralls-url] 6 | [![David deps][david-imageoptions]][david-url] 7 | [![npm download][download-imageoptions]][download-url] 8 | 9 | Various tools for OCR 10 | 11 | ## Installation 12 | 13 | `$ npm install ocr-tools` 14 | 15 | ## [API Documentation](https://image-js.github.io/ocr-tools/) 16 | 17 | ## Example 18 | 19 | ```js 20 | const ocr = require('ocr-tools'); 21 | ``` 22 | 23 | ## License 24 | 25 | [MIT](./LICENSE) 26 | 27 | [npm-imageoptions]: https://img.shields.io/npm/v/ocr-tools.svg?style=flat-square 28 | [npm-url]: https://npmjs.org/package/ocr-tools 29 | [travis-imageoptions]: https://img.shields.io/travis/image-js/ocr-tools/master.svg?style=flat-square 30 | [travis-url]: https://travis-ci.org/image-js/ocr-tools 31 | [coveralls-imageoptions]: https://img.shields.io/coveralls/image-js/ocr-tools.svg?style=flat-square 32 | [coveralls-url]: https://coveralls.io/github/image-js/ocr-tools 33 | [david-imageoptions]: https://img.shields.io/david/image-js/ocr-tools.svg?style=flat-square 34 | [david-url]: https://david-dm.org/image-js/ocr-tools 35 | [download-imageoptions]: https://img.shields.io/npm/dm/ocr-tools.svg?style=flat-square 36 | [download-url]: https://npmjs.org/package/ocr-tools 37 | -------------------------------------------------------------------------------- /run/testOCR.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | 4 | const runOCR = require('../src/runOCR'); 5 | 6 | const Image = require('image-js').default; 7 | 8 | const loadFontFingerprint = require('../src/util/loadFontData'); 9 | const symbols = require('../src/util/symbolClasses').MRZ; // SYMBOLS MRZ NUMBERS 10 | 11 | var options = { 12 | roiOptions: { 13 | minSurface: 30, 14 | positive: true, 15 | negative: false, 16 | greyThreshold: 0.5 17 | }, 18 | fingerprintOptions: { 19 | height: 12, 20 | width: 12, 21 | minSimilarity: 0.7, 22 | fontName: 'ocrb', 23 | category: symbols.label 24 | }, 25 | }; 26 | 27 | 28 | var fontFingerprint = loadFontFingerprint(options.fingerprintOptions); 29 | 30 | 31 | Image.load('demo/ocrb.png').then(function (image) { 32 | var result = runOCR(image, fontFingerprint, options); 33 | console.log(result); 34 | 35 | for (var line of result.lines) { 36 | console.log(line.text, line.similarity, ' Found:', line.found, ' Not found:', line.notFound); 37 | } 38 | console.log('Total similarity', result.totalSimilarity); 39 | console.log('Total found', result.totalFound); 40 | console.log('Total not found', result.totalNotFound); 41 | 42 | // for the first line we just show the roiOptions 43 | // for (var roi of result.lines[1].rois) { 44 | // console.log(JSON.stringify(roiOptions)); 45 | // } 46 | }); 47 | -------------------------------------------------------------------------------- /src/util/tanimotoSimilarity.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const bitsSetTable256 = [ 4 | 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 5 | 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 6 | 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 7 | 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 8 | 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 9 | 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 10 | 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 11 | 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 12 | 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 13 | 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 14 | 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 15 | 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 16 | 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 17 | 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 18 | 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 19 | 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 20 | ]; 21 | 22 | // in our case we have 2 arrays of bytes 23 | module.exports = function tanimotoSimilarity(a, b) { 24 | if (a.length !== b.length) { 25 | throw Error(`tanimotoSimilarity: not same length: ${a}, ${b}`); 26 | } 27 | let totalAnd = 0; 28 | let totalOr = 0; 29 | for (let i = 0; i < a.length; i++) { 30 | totalAnd += bitsSetTable256[a[i] & b[i]]; 31 | totalOr += bitsSetTable256[a[i] | b[i]]; 32 | } 33 | return totalAnd / totalOr; 34 | }; 35 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ocr-tools", 3 | "version": "0.2.0", 4 | "description": "Various tools for OCR", 5 | "main": "./src/index.js", 6 | "files": [ 7 | "src" 8 | ], 9 | "scripts": { 10 | "eslint": "eslint src run", 11 | "eslint-fix": "npm run eslint -- --fix", 12 | "test": "npm run test-only && npm run eslint", 13 | "test-cov": "npm run test-only -- --coverage", 14 | "test-travis": "npm run test-cov && npm run eslint", 15 | "test-only": "echo 'No test for now...'" 16 | }, 17 | "repository": { 18 | "type": "git", 19 | "url": "https://github.com/cheminfo-js/ocr-tools.git" 20 | }, 21 | "keywords": [ 22 | "ocr", 23 | "image", 24 | "optical", 25 | "character", 26 | "recognition" 27 | ], 28 | "license": "MIT", 29 | "bugs": { 30 | "url": "https://github.com/cheminfo-js/ocr-tools/issues" 31 | }, 32 | "homepage": "https://github.com/cheminfo-js/ocr-tools#readme", 33 | "optionalDependencies": { 34 | "font-manager": "^0.2.2" 35 | }, 36 | "devDependencies": { 37 | "eslint": "^4.16.0", 38 | "eslint-config-cheminfo": "^1.14.1", 39 | "eslint-plugin-import": "^2.12.0", 40 | "eslint-plugin-jest": "^21.7.0", 41 | "image-js": "^0.21.0", 42 | "jest": "^22.1.4" 43 | }, 44 | "dependencies": { 45 | "mkdirp": "^0.5.1", 46 | "ml-array-mean": "^1.0.1", 47 | "ml-array-median": "^1.0.1", 48 | "ml-distance": "^2.1.1", 49 | "ml-kmeans": "^4.0.0" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/util/generateSymbolImage.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const IJS = require('image-js').Image; 4 | 5 | const SYMBOLS = require('./symbolClasses').MRZ; 6 | 7 | function generateSymbolImage(options = {}) { 8 | let { 9 | fontSize = 24, 10 | fontName = 'Helvetica', 11 | numberPerLine = 11, 12 | allowedRotation = 2, 13 | backgroundColor = 255, 14 | symbols = SYMBOLS.symbols 15 | } = options; 16 | 17 | const grid = Math.floor(fontSize * 1.2); 18 | fontName = `${fontSize}px ${fontName}`; 19 | 20 | // default RGBA 8bits 21 | const image = new IJS( 22 | (numberPerLine + 2) * grid, 23 | (symbols.length + 2) * grid 24 | ); 25 | 26 | // the imageOptions is now white 27 | const data = image.data; 28 | for (let i = 0; i < data.length; i++) { 29 | if (i % 4 === 3) continue; 30 | data[i] = backgroundColor; 31 | } 32 | 33 | const rotate = []; 34 | const paintOptions = { 35 | font: fontName, 36 | color: 'black', 37 | rotate: rotate 38 | }; 39 | 40 | const labels = []; 41 | const positions = []; 42 | 43 | for (let y = 0; y < symbols.length; y++) { 44 | const text = String.fromCharCode(symbols[y]); 45 | for (let x = 0; x < numberPerLine; x++) { 46 | const position = [x * grid + grid, y * grid + grid]; 47 | positions.push(position); 48 | labels.push(text); 49 | rotate.push( 50 | 2 * allowedRotation * x / (numberPerLine - 1) - allowedRotation 51 | ); 52 | } 53 | } 54 | image.paintLabels(labels, positions, paintOptions); 55 | return { image, chars: labels }; 56 | } 57 | 58 | module.exports = generateSymbolImage; 59 | -------------------------------------------------------------------------------- /run/fontAnalysis.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var IJS = require('image-js').Image; 4 | 5 | var loadFingerprints = require('../src/util/loadAllFontData'); 6 | var runFontAnalysis = require('../src/runFontAnalysis'); 7 | var symbols = require('../src/util/symbolClasses').MRZ; // SYMBOLS MRZ NUMBERS 8 | 9 | var options = { 10 | roiOptions: { 11 | minSurface: 30, 12 | positive: true, 13 | negative: false, 14 | greyThreshold: 0.5 15 | }, 16 | fingerprintOptions: { 17 | height: 12, 18 | width: 12, 19 | category: symbols.label, 20 | maxSimilarity: 0.7 // we store all the different fontFingerprint 21 | }, 22 | imageOptions: { 23 | symbols: symbols.symbols, 24 | fontSize: 48, // font size we use at the beginning 25 | allowedRotation: 5, // we may rotate the font 26 | numberPerLine: 11, // better to have a odd number 27 | fontName: '' 28 | } 29 | }; 30 | 31 | var allFontFingerprints = loadFingerprints(options.fingerprintOptions); 32 | 33 | console.log('Analysing', allFontFingerprints.length, 'different fonts'); 34 | 35 | IJS.load('demo/test.png').then(function (image) { 36 | var results = runFontAnalysis(image, allFontFingerprints, options); 37 | 38 | results = results.slice(0, 5); 39 | 40 | for (var result of results) { 41 | console.log( 42 | '----------', 43 | result.fontName, 44 | '--', 45 | 'Total similarity: ', 46 | result.totalSimilarity / result.totalFound, 47 | '-', 48 | 'Total found: ', 49 | result.totalFound, 50 | '-', 51 | 'Total not found: ', 52 | result.totalNotFound 53 | ); 54 | } 55 | }); 56 | -------------------------------------------------------------------------------- /run/testMRZ.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // eslint-disable-next-line 4 | const runMRZ = require('../src/runMRZ'); 5 | 6 | const IJS = require('image-js').default; 7 | 8 | const loadFontFingerprint = require('../src/util/loadFontData'); 9 | const symbols = require('../src/util/symbolClasses').MRZ; // SYMBOLS MRZ NUMBERS 10 | 11 | var options = { 12 | roiOptions: { 13 | minSurface: 20, 14 | positive: true, 15 | negative: false, 16 | maxWidth: 50, 17 | greyThreshold: 0.5, 18 | level: true // we recalculate the greyThreshold based 19 | // on min / max values of the grey image 20 | }, 21 | fingerprintOptions: { 22 | height: 12, 23 | width: 12, 24 | minSimilarity: 0.7, 25 | fontName: 'ocrb', 26 | category: symbols.label 27 | } 28 | }; 29 | 30 | var fontFingerprint = loadFontFingerprint(options.fingerprintOptions); 31 | IJS.load('../output/image.png').then(function (image) { 32 | console.log('Image size: ', image.width, image.height); 33 | console.time('full OCR process'); 34 | 35 | var result = runMRZ(image, fontFingerprint, options).ocrResult; 36 | 37 | console.timeEnd('full OCR process'); 38 | 39 | for (var line of result.lines) { 40 | console.log( 41 | line.text, 42 | line.similarity, 43 | ' Found:', 44 | line.found, 45 | ' Not found:', 46 | line.notFound 47 | ); 48 | } 49 | console.log('Total similarity', result.totalSimilarity); 50 | console.log('Total found', result.totalFound); 51 | console.log('Total not found', result.totalNotFound); 52 | 53 | // for the first line we just show the roiOptions 54 | for (var roi of result.lines[1].rois) { 55 | console.log(JSON.stringify(roi)); 56 | } 57 | }); 58 | -------------------------------------------------------------------------------- /src/util/ambiguitySolver.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const kmeans = require('ml-kmeans'); 4 | 5 | const variablesForClust = ['height']; 6 | // if you want to add a new ambiguity to solver just add a new string to the array to be analysed 7 | const IS_LETTER = { 8 | 0: 'O' 9 | }; 10 | 11 | const IS_NUMBER = { 12 | O: '0' 13 | }; 14 | 15 | function ambiguitySolver(report) { 16 | var positions = new Array(report.length); 17 | var dataset = []; 18 | for (let i = 0; i < report.length; ++i) { 19 | positions[i] = []; 20 | var text = report[i].text; 21 | for (let j = 0; j < text.length; ++j) { 22 | var letter = text[j]; 23 | const datasetElement = []; 24 | if (letter === '<') { 25 | continue; 26 | } 27 | 28 | variablesForClust.forEach((elem) => 29 | datasetElement.push(report[i].rois[j][elem]) 30 | ); 31 | dataset.push(datasetElement); 32 | } 33 | } 34 | 35 | var { centroids, clusters } = kmeans(dataset, 2); 36 | 37 | var isNumber = centroids[0].centroid[0] < centroids[1].centroid[0] ? 1 : 0; 38 | var k = 0; 39 | for (let i = 0; i < report.length; ++i) { 40 | text = report[i].text; 41 | var toReplace = ''; 42 | for (let j = 0; j < text.length; ++j) { 43 | letter = text[j]; 44 | if (letter === '<') { 45 | toReplace += letter; 46 | continue; 47 | } 48 | 49 | var prediction = clusters[k]; 50 | k++; 51 | var replace = 52 | isNumber === prediction ? IS_NUMBER[letter] : IS_LETTER[letter]; 53 | toReplace += replace !== undefined ? replace : letter; 54 | } 55 | report[i].text = toReplace; 56 | } 57 | 58 | return report; 59 | } 60 | 61 | module.exports = ambiguitySolver; 62 | -------------------------------------------------------------------------------- /src/createFontFingerprint.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 'use strict'; 3 | 4 | const generateSymbolImage = require('../src/util/generateSymbolImage'); 5 | const appendFingerprints = require('../src/util/appendFingerprints'); 6 | const setFingerprintDataOnRoi = require('../src/util/setFingerprintDataOnRoi'); 7 | 8 | const getLinesFromImage = require('./util/getLinesFromImage'); 9 | 10 | module.exports = function createFontFingerprint(options = {}) { 11 | const { image } = generateSymbolImage(options.imageOptions); 12 | image.save( 13 | `png/${options.imageOptions.fontName}_${ 14 | options.roiOptions.greyThreshold 15 | }.jpg` 16 | ); 17 | const lines = getLinesFromImage(image, options); 18 | setFingerprintDataOnRoi(lines, options.fingerprintOptions); 19 | const symbols = options.imageOptions.symbols; 20 | 21 | let valid = true; 22 | // we have the lines in the correct order, it should match directly the font 23 | for (let i = 0; i < lines.length; i++) { 24 | const line = lines[i]; 25 | line.symbol = String.fromCharCode(symbols[i]); 26 | if (line.rois.length !== options.imageOptions.numberPerLine) { 27 | console.log( 28 | `Number of symbol on the line not correct for: ${line.symbol}` 29 | ); 30 | valid = false; 31 | } 32 | } 33 | if (lines.lines.length !== symbols.length) { 34 | console.log('Number of lines not correct: ', lines.length, symbols.length); 35 | valid = false; 36 | } 37 | 38 | appendFingerprints(lines, { 39 | maxSimilarity: options.fingerprintOptions.maxSimilarity 40 | }); 41 | 42 | const results = lines.lines.map(function (line) { 43 | return { 44 | symbol: line.symbol, 45 | fingerprints: line.fingerprints 46 | }; 47 | }); 48 | 49 | return { 50 | valid, 51 | results, 52 | fontName: options.imageOptions.fontName 53 | }; 54 | }; 55 | -------------------------------------------------------------------------------- /src/util/doOcrOnLines.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const bestMatch = require('./bestMatch'); 4 | const ambiguitySolver = require('./ambiguitySolver'); 5 | 6 | module.exports = function doOcrOnLines(lines, fontData, options = {}) { 7 | var { 8 | minSimilarity = 0.8, 9 | maxNotFound = Number.MIN_SAFE_INTEGER, 10 | ambiguity = false 11 | } = options; 12 | 13 | // we try to analyse each line 14 | var totalSimilarity = 0; 15 | var totalFound = 0; 16 | var totalNotFound = 0; 17 | for (var line of lines) { 18 | line.text = ''; 19 | line.similarity = 0; 20 | line.found = 0; 21 | line.notFound = 0; 22 | var rois = line.rois; 23 | for (var roi of rois) { 24 | // TODO: get roi.mask() for matrix 25 | var roiData = roi.data; 26 | var match = bestMatch(roiData, fontData); 27 | if (match.similarity > minSimilarity) { 28 | line.text += match.symbol; 29 | line.similarity += match.similarity; 30 | line.found++; 31 | } else { 32 | line.text += '?'; 33 | line.notFound++; 34 | } 35 | } 36 | totalSimilarity += line.similarity; 37 | totalFound += line.found; 38 | totalNotFound += line.notFound; 39 | } 40 | 41 | const report = []; 42 | for (const line of lines) { 43 | if (line.notFound < maxNotFound) { 44 | const rois = []; 45 | for (const roi of line.rois) { 46 | rois.push({ 47 | meanX: roi.meanX, 48 | meanY: roi.meanY, 49 | width: roi.width, 50 | height: roi.height 51 | }); 52 | } 53 | report.push({ 54 | text: line.text, 55 | found: line.found, 56 | notFound: line.notFound, 57 | similarity: line.similarity, 58 | rois: rois 59 | }); 60 | } 61 | } 62 | 63 | if (ambiguity) { 64 | ambiguitySolver(report); 65 | } 66 | 67 | return { 68 | lines: report, 69 | totalSimilarity, 70 | totalFound, 71 | totalNotFound 72 | }; 73 | }; 74 | -------------------------------------------------------------------------------- /run/createFontFingerprint.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const tanimotoSimilarity = require('../src/util/tanimotoSimilarity'); 4 | var createFontFingerprint = require('../src/createFontFingerprint'); 5 | var symbols = require('../src/util/symbolClasses').MRZ; // SYMBOLS MRZ NUMBERS 6 | var saveFingerprint = require('../src/util/saveFontData'); 7 | var getInstalledRegularFonts = require('../src/util/getInstalledRegularFonts'); 8 | 9 | var fonts = getInstalledRegularFonts(); // .filter(elem => elem === 'OCRB-Regular'); 10 | 11 | // fonts=fonts.filter(a=>a.toLowerCase().indexOf('ocr')>=0).slice(0,3); 12 | // fonts=fonts.slice(0,1); 13 | 14 | var greyThresholds = [0.3, 0.5, 0.7]; 15 | 16 | var options = { 17 | roiOptions: { 18 | minSurface: 30, 19 | positive: true, 20 | negative: false, 21 | greyThreshold: 0.5 22 | }, 23 | fingerprintOptions: { 24 | height: 64, 25 | width: 45, 26 | category: symbols.label, 27 | maxSimilarity: 0.95 // we store all the different fontFingerprint 28 | }, 29 | imageOptions: { 30 | symbols: symbols.symbols, 31 | fontSize: 48, // font size we use at the beginning 32 | allowedRotation: 5, // we may rotate the font 33 | numberPerLine: 11, // better to have a odd number 34 | fontName: '' 35 | } 36 | }; 37 | 38 | for (var font of fonts) { 39 | console.log('-----------------> Processing:', font); 40 | 41 | options.imageOptions.fontName = font; 42 | 43 | var fontFingerprintPerThreshold = []; 44 | for (var greyThreshold of greyThresholds) { 45 | console.log('Grey threshold', greyThreshold); 46 | options.roiOptions.greyThreshold = greyThreshold; 47 | var fontFingerprint = createFontFingerprint(options); 48 | if (fontFingerprint.valid) { 49 | fontFingerprintPerThreshold.push(fontFingerprint); 50 | } 51 | } 52 | 53 | fontFingerprint = joinFontFingerprints(fontFingerprintPerThreshold, { 54 | maxSimilarity: options.fingerprintOptions.maxSimilarity 55 | }); 56 | if (fontFingerprint.length > 0) { 57 | saveFingerprint(fontFingerprint, options.fingerprintOptions); 58 | } 59 | } 60 | 61 | /* 62 | We have an array of fontFingerprint and we flatten it 63 | */ 64 | function joinFontFingerprints(allFingerprints, options = {}) { 65 | const { maxSimilarity } = options; 66 | var symbols = {}; 67 | for (var oneFingerprint of allFingerprints) { 68 | var results = oneFingerprint.results; 69 | for (var result of results) { 70 | // result is composed of a symbol and the related fontFingerprint 71 | if (!symbols[result.symbol]) { 72 | symbols[result.symbol] = []; 73 | } 74 | for (const newFingerprint of result.fingerprints) { 75 | var isNew = true; 76 | for (const existingFingerprint of symbols[result.symbol]) { 77 | if ( 78 | tanimotoSimilarity(existingFingerprint, newFingerprint) >= 79 | maxSimilarity 80 | ) { 81 | isNew = false; 82 | break; 83 | } 84 | } 85 | if (isNew) { 86 | symbols[result.symbol].push(newFingerprint); 87 | } 88 | } 89 | } 90 | } 91 | var toReturn = []; 92 | for (var symbol of Object.keys(symbols)) { 93 | toReturn.push({ 94 | symbol: symbol, 95 | fingerprints: symbols[symbol] 96 | }); 97 | } 98 | 99 | return toReturn; 100 | } 101 | -------------------------------------------------------------------------------- /src/util/getLinesFromImage.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const Image = require('image-js').Image; 4 | const mean = require('ml-array-mean'); 5 | const median = require('ml-array-median'); 6 | 7 | var groupRoisPerLine = require('./groupRoisPerLine'); 8 | 9 | module.exports = function getLinesFromImage(image, roiOptions = {}) { 10 | var grey = image.grey({ allowGrey: true }); 11 | 12 | // we should allow to make a level without making a level ... 13 | let maskOptions = { 14 | invert: true 15 | }; 16 | if (roiOptions.algorithm) { 17 | maskOptions.algorithm = roiOptions.algorithm; 18 | } else if (roiOptions.greyThreshold) { 19 | let greyThreshold = roiOptions.greyThreshold; 20 | if (roiOptions.level) { 21 | // we simulate the level by changing the threshold 22 | greyThreshold = 23 | (grey.min[0] + (grey.max[0] - grey.min[0]) * greyThreshold) / 24 | grey.maxValue; 25 | } 26 | maskOptions.threshold = greyThreshold; 27 | } else { 28 | throw new Error('no algorithm or greyThreshold provided to apply.'); 29 | } 30 | 31 | var mask = grey.mask(maskOptions); 32 | var manager = image.getRoiManager(); 33 | manager.fromMask(mask); 34 | var rois = manager.getRois(roiOptions); 35 | rois = filterRois(rois); 36 | 37 | if (rois.length < 60) { 38 | mask = getMask(grey, maskOptions); 39 | manager = image.getRoiManager(); 40 | manager.fromMask(mask); 41 | rois = manager.getRois(roiOptions); 42 | rois = filterRois(rois); 43 | } 44 | 45 | var averageSurface = mean(rois.map((elem) => elem.surface)); 46 | 47 | var painted = manager.paint(roiOptions); 48 | 49 | rois.forEach(function (roi) { 50 | // draw bounding boxes 51 | var mask = roi.getMask(); 52 | var mbr = mask.minimalBoundingRectangle(); 53 | roi.mbr = mbr; 54 | roi.mbrWidth = getDistance(mbr[0], mbr[1]); 55 | roi.mbrHeight = getDistance(mbr[1], mbr[2]); 56 | roi.mbrSurface = roi.mbrWidth * roi.mbrHeight; 57 | roi.fillingFactor = roi.surface / roi.mbrSurface; 58 | 59 | mbr = mbr.map((point) => [ 60 | point[0] + mask.position[0], 61 | point[1] + mask.position[1] 62 | ]); 63 | painted.paintPolyline(mbr, { color: [255, 0, 0] }); 64 | }); 65 | 66 | return { 67 | lines: groupRoisPerLine(rois, roiOptions), 68 | painted, 69 | mask, 70 | averageSurface 71 | }; 72 | }; 73 | 74 | function getDistance(p1, p2) { 75 | return Math.sqrt((p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2); 76 | } 77 | 78 | function getMask(image, maskOptions) { 79 | let mask = new Image(image.width, image.height, { kind: 'BINARY' }); 80 | const partsY = 1; 81 | const partsX = 30; 82 | const h = Math.floor(image.height / partsY); 83 | const w = Math.floor(image.width / partsX); 84 | for (let i = 0; i < partsX; i++) { 85 | for (let j = 0; j < partsY; j++) { 86 | let x = i * w; 87 | let y = j * h; 88 | let width = w; 89 | let height = h; 90 | if (i === partsX - 1) { 91 | width += image.width % partsX; 92 | } 93 | if (j === partsY - 1) { 94 | height += image.height % partsY; 95 | } 96 | const params = { 97 | x, 98 | y, 99 | width, 100 | height 101 | }; 102 | const imagePart = image.crop(params).mask(maskOptions); 103 | mask.insert(imagePart, { inPlace: true, x: x, y: y }); 104 | } 105 | } 106 | return mask; 107 | } 108 | 109 | function filterRois(rois) { 110 | rois = rois.filter((roi) => roi.width !== 1 || roi.height !== 1); 111 | var medianSurface = median(rois.map((elem) => elem.surface)); 112 | rois = rois.filter( 113 | (roi) => roi.surface * 3 > medianSurface && roi.surface / 3 < medianSurface 114 | ); 115 | 116 | return rois; 117 | } 118 | -------------------------------------------------------------------------------- /run/testRotation.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const FS = require('fs'); 4 | 5 | const IJS = require('image-js'); 6 | 7 | const getRotation = require('../src/getRotation'); 8 | const runOCR = require('../src/runOCR'); 9 | 10 | 11 | const fontFingerprint = { font: 'OcrB-Regular', fingerprint: [{ symbol: '0', fingerprints: [[63, 199, 14, 96, 110, 6, 224, 62, 3, 96, 54, 3, 96, 54, 3, 48, 225, 252], [63, 135, 28, 224, 108, 6, 192, 108, 6, 192, 124, 7, 96, 118, 6, 112, 227, 252], [63, 135, 156, 96, 110, 6, 192, 108, 7, 224, 62, 3, 96, 118, 6, 63, 225, 248], [31, 135, 254, 96, 102, 6, 224, 54, 3, 96, 54, 3, 96, 54, 7, 56, 225, 252], [63, 199, 14, 224, 108, 3, 192, 60, 3, 192, 60, 3, 224, 54, 7, 112, 227, 252], [63, 135, 14, 96, 110, 6, 224, 124, 7, 192, 124, 7, 224, 102, 6, 112, 227, 252], [31, 135, 158, 96, 102, 3, 96, 62, 3, 224, 62, 3, 96, 118, 6, 127, 225, 248], [31, 135, 254, 96, 126, 3, 192, 60, 3, 192, 60, 3, 192, 126, 6, 120, 227, 252], [63, 199, 14, 96, 102, 7, 224, 124, 7, 192, 124, 6, 192, 110, 6, 112, 227, 248], [31, 199, 14, 96, 118, 3, 96, 62, 3, 224, 60, 7, 192, 110, 6, 112, 227, 252], [31, 131, 190, 112, 54, 3, 96, 54, 3, 224, 62, 7, 224, 102, 6, 125, 225, 248], [63, 143, 28, 192, 236, 6, 192, 108, 6, 192, 108, 7, 224, 118, 6, 113, 227, 252], [63, 135, 156, 224, 108, 6, 192, 108, 7, 192, 126, 7, 224, 118, 6, 127, 225, 248], [63, 135, 254, 224, 110, 6, 224, 126, 7, 224, 126, 7, 96, 118, 7, 127, 225, 252], [31, 135, 254, 96, 110, 7, 224, 126, 3, 224, 54, 3, 96, 118, 7, 127, 225, 252], [63, 199, 14, 224, 110, 6, 192, 108, 7, 192, 124, 7, 224, 110, 6, 113, 227, 252], [63, 199, 158, 96, 110, 7, 224, 126, 7, 224, 126, 7, 224, 118, 6, 127, 225, 248], [31, 199, 254, 96, 102, 7, 224, 62, 3, 224, 62, 7, 224, 118, 6, 127, 225, 248], [31, 135, 254, 96, 110, 6, 224, 108, 7, 192, 108, 6, 192, 110, 14, 127, 227, 248], [31, 135, 254, 96, 102, 7, 224, 126, 7, 192, 124, 7, 192, 110, 6, 112, 227, 248], [31, 199, 158, 96, 118, 3, 224, 62, 7, 224, 126, 7, 224, 110, 6, 127, 225, 248], [31, 135, 254, 96, 110, 7, 224, 124, 6, 192, 108, 6, 192, 108, 14, 127, 195, 248], [63, 135, 252, 224, 236, 6, 192, 108, 6, 192, 126, 7, 224, 118, 6, 127, 225, 248], [63, 143, 252, 224, 238, 6, 192, 108, 7, 224, 126, 7, 224, 118, 7, 127, 225, 248], [63, 135, 252, 224, 238, 6, 192, 108, 6, 192, 124, 7, 224, 110, 6, 127, 227, 248], [63, 199, 254, 96, 126, 7, 224, 126, 7, 224, 126, 7, 224, 118, 6, 127, 227, 252], [63, 135, 254, 224, 110, 6, 224, 124, 7, 192, 124, 6, 224, 110, 14, 127, 227, 248], [31, 135, 254, 96, 110, 7, 224, 126, 7, 224, 126, 7, 224, 110, 14, 127, 225, 248], [63, 199, 254, 112, 118, 7, 224, 126, 7, 224, 126, 7, 224, 110, 14, 127, 227, 248], [63, 135, 254, 96, 110, 7, 224, 124, 7, 192, 108, 6, 192, 238, 14, 255, 195, 248]] }, { symbol: '1', fingerprints: [[7, 193, 252, 121, 198, 28, 1, 224, 14, 0, 224, 14, 0, 224, 15, 0, 112, 7], [3, 193, 252, 125, 238, 14, 0, 224, 14, 0, 224, 14, 0, 240, 15, 0, 112, 7], [3, 224, 254, 60, 231, 14, 0, 224, 14, 0, 240, 15, 0, 112, 7, 0, 112, 7], [1, 225, 255, 126, 254, 15, 0, 240, 7, 0, 112, 7, 0, 112, 7, 0, 112, 7], [3, 241, 255, 124, 118, 7, 0, 112, 7, 0, 112, 7, 0, 112, 7, 0, 112, 7], [3, 241, 255, 252, 254, 15, 0, 224, 14, 0, 224, 14, 0, 224, 14, 0, 224, 14], [1, 241, 255, 126, 118, 7, 0, 112, 7, 0, 240, 15, 0, 224, 14, 0, 224, 14], [3, 241, 255, 248, 240, 14, 0, 224, 14, 0, 224, 14, 1, 224, 28, 1, 192, 28], [3, 241, 255, 252, 112, 7, 0, 240, 14, 0, 224, 14, 0, 224, 30, 1, 192, 28], [3, 241, 255, 252, 244, 14, 0, 224, 30, 1, 224, 28, 1, 192, 28, 3, 128, 56], [1, 241, 255, 252, 118, 15, 0, 224, 14, 1, 224, 28, 1, 192, 28, 3, 128, 56], [3, 192, 252, 127, 207, 30, 1, 224, 30, 1, 224, 14, 0, 240, 15, 0, 240, 7], [3, 193, 254, 125, 238, 30, 0, 224, 14, 0, 224, 15, 0, 240, 15, 0, 240, 7], [3, 225, 254, 124, 239, 14, 0, 240, 15, 0, 240, 15, 0, 240, 15, 0, 112, 7], [3, 225, 255, 126, 254, 15, 0, 240, 15, 0, 240, 15, 0, 112, 7, 0, 112, 7], [1, 240, 255, 63, 127, 7, 0, 112, 7, 0, 112, 7, 0, 112, 7, 0, 112, 7], [3, 241, 255, 252, 254, 15, 0, 240, 15, 0, 240, 15, 0, 240, 14, 0, 224, 14], [1, 241, 255, 126, 126, 7, 0, 240, 15, 0, 240, 15, 0, 240, 15, 0, 224, 14], [1, 240, 255, 126, 247, 15, 0, 224, 14, 0, 224, 30, 1, 224, 30, 1, 224, 28], [3, 227, 254, 252, 228, 30, 1, 224, 30, 1, 192, 28, 3, 192, 60, 3, 192, 60], [3, 241, 255, 124, 242, 14, 0, 224, 30, 1, 224, 28, 3, 192, 60, 3, 192, 60], [3, 225, 255, 252, 228, 30, 1, 224, 28, 3, 192, 60, 3, 192, 60, 3, 192, 56], [3, 224, 254, 127, 231, 30, 1, 224, 31, 0, 240, 15, 0, 240, 15, 0, 240, 15], [3, 225, 254, 125, 255, 15, 0, 240, 15, 0, 240, 15, 0, 240, 15, 0, 240, 7], [3, 240, 255, 62, 247, 143, 0, 240, 15, 0, 240, 15, 0, 240, 15, 0, 240, 7], [3, 224, 255, 127, 255, 31, 1, 240, 31, 1, 240, 31, 1, 240, 15, 0, 240, 14], [3, 241, 255, 124, 247, 15, 0, 240, 15, 0, 240, 15, 0, 240, 15, 0, 240, 14], [3, 225, 255, 253, 238, 30, 1, 224, 30, 1, 224, 30, 1, 224, 30, 1, 224, 28], [3, 240, 255, 126, 247, 15, 0, 240, 31, 1, 224, 30, 1, 224, 30, 1, 224, 28], [3, 225, 255, 127, 239, 30, 1, 224, 30, 1, 224, 60, 3, 192, 60, 3, 192, 60], [3, 241, 255, 252, 246, 15, 1, 224, 30, 1, 224, 30, 3, 192, 60, 3, 192, 60], [3, 241, 255, 253, 238, 30, 1, 224, 60, 3, 192, 60, 3, 192, 60, 3, 192, 56]] }, { symbol: '2', fingerprints: [[63, 143, 28, 0, 96, 6, 0, 192, 56, 7, 1, 192, 56, 3, 0, 51, 243, 254], [63, 143, 28, 0, 224, 14, 1, 192, 56, 15, 1, 192, 48, 3, 0, 113, 231, 254], [63, 143, 28, 0, 96, 6, 0, 224, 56, 15, 1, 192, 48, 6, 0, 96, 103, 254], [63, 143, 252, 0, 96, 6, 0, 224, 60, 15, 129, 224, 48, 6, 0, 96, 7, 255], [127, 206, 30, 0, 96, 6, 0, 224, 124, 15, 3, 192, 96, 6, 0, 127, 231, 254], [63, 207, 30, 0, 112, 7, 0, 224, 60, 15, 131, 192, 112, 6, 0, 96, 7, 255], [63, 207, 30, 0, 48, 3, 0, 224, 60, 15, 131, 192, 112, 12, 0, 192, 15, 255], [63, 143, 190, 0, 96, 7, 0, 96, 60, 31, 3, 128, 96, 12, 0, 255, 207, 254], [127, 198, 14, 0, 48, 3, 0, 224, 60, 15, 131, 192, 96, 12, 0, 255, 15, 254], [63, 199, 30, 0, 48, 3, 0, 112, 60, 15, 131, 192, 96, 14, 0, 248, 15, 254], [63, 135, 30, 0, 112, 3, 0, 96, 60, 31, 3, 128, 96, 12, 0, 255, 131, 254], [31, 15, 252, 192, 192, 14, 0, 192, 56, 15, 1, 192, 48, 7, 0, 127, 231, 254], [63, 143, 28, 0, 224, 14, 1, 192, 56, 15, 1, 192, 48, 7, 0, 119, 231, 254], [63, 143, 188, 0, 224, 6, 0, 224, 60, 15, 1, 192, 48, 7, 0, 127, 243, 254], [63, 143, 252, 0, 96, 6, 0, 224, 60, 15, 3, 192, 112, 6, 0, 127, 231, 254], [31, 143, 254, 64, 96, 6, 0, 224, 28, 15, 3, 192, 112, 6, 0, 127, 231, 255], [127, 207, 30, 0, 112, 7, 0, 224, 60, 15, 131, 192, 112, 6, 0, 255, 231, 255], [63, 207, 190, 0, 112, 3, 0, 112, 60, 7, 131, 192, 112, 6, 0, 96, 7, 255], [63, 143, 254, 0, 112, 7, 0, 96, 60, 31, 7, 128, 96, 12, 0, 255, 239, 254], [63, 143, 254, 0, 112, 3, 0, 112, 62, 31, 131, 192, 96, 14, 0, 255, 207, 254], [63, 135, 30, 0, 96, 7, 0, 224, 124, 31, 7, 128, 96, 14, 0, 255, 195, 254], [63, 135, 158, 0, 112, 7, 0, 96, 60, 31, 3, 128, 96, 14, 0, 255, 199, 254], [63, 15, 252, 192, 192, 14, 1, 192, 56, 30, 3, 128, 112, 7, 0, 127, 243, 248], [31, 15, 252, 192, 224, 14, 0, 224, 60, 15, 3, 192, 48, 7, 0, 127, 247, 254], [63, 143, 252, 64, 224, 6, 0, 224, 60, 15, 3, 192, 48, 7, 0, 127, 247, 254], [63, 143, 254, 64, 112, 7, 0, 112, 62, 15, 131, 192, 112, 6, 0, 255, 239, 255], [63, 143, 254, 0, 96, 6, 0, 224, 124, 31, 3, 128, 112, 6, 0, 255, 231, 254], [63, 135, 254, 0, 112, 7, 0, 224, 60, 31, 3, 192, 112, 6, 0, 255, 231, 254], [31, 135, 254, 0, 112, 7, 0, 112, 30, 15, 131, 192, 112, 6, 0, 255, 199, 254], [31, 135, 254, 0, 96, 7, 0, 96, 30, 31, 3, 192, 112, 6, 0, 255, 231, 254], [63, 199, 254, 0, 112, 7, 0, 240, 60, 15, 3, 192, 112, 6, 0, 255, 199, 254]] }, { symbol: '3', fingerprints: [[255, 207, 220, 3, 128, 112, 15, 0, 252, 0, 224, 3, 0, 48, 7, 33, 231, 248], [255, 207, 252, 3, 128, 112, 14, 0, 252, 0, 224, 6, 0, 96, 6, 65, 199, 248], [127, 207, 252, 3, 128, 112, 14, 0, 252, 0, 224, 7, 0, 112, 6, 127, 195, 240], [127, 224, 14, 3, 128, 112, 15, 0, 252, 0, 224, 7, 0, 48, 6, 115, 199, 240], [255, 224, 14, 1, 192, 112, 15, 0, 252, 0, 224, 7, 0, 48, 7, 97, 231, 248], [127, 231, 254, 1, 192, 120, 15, 0, 252, 0, 224, 3, 0, 48, 7, 97, 231, 248], [127, 231, 254, 1, 192, 56, 14, 0, 252, 1, 224, 6, 0, 112, 6, 97, 231, 248], [127, 224, 14, 1, 192, 112, 15, 0, 124, 0, 224, 6, 0, 112, 6, 255, 195, 240], [127, 240, 31, 1, 192, 56, 15, 0, 124, 0, 224, 7, 0, 48, 6, 243, 227, 248], [127, 240, 127, 0, 224, 56, 15, 0, 252, 0, 224, 7, 0, 48, 7, 225, 231, 248], [127, 224, 255, 0, 224, 56, 14, 0, 252, 1, 192, 6, 0, 96, 6, 225, 199, 248], [31, 207, 252, 1, 192, 112, 14, 0, 252, 0, 224, 7, 0, 48, 7, 33, 231, 248], [255, 207, 252, 3, 128, 112, 14, 1, 252, 0, 224, 7, 0, 112, 14, 127, 199, 240], [127, 231, 254, 1, 192, 120, 14, 0, 252, 0, 224, 7, 0, 112, 6, 127, 231, 248], [255, 231, 254, 1, 192, 112, 31, 0, 252, 0, 224, 7, 0, 48, 7, 247, 231, 248], [127, 231, 254, 1, 192, 112, 14, 0, 252, 1, 224, 6, 0, 112, 6, 227, 231, 248], [127, 231, 254, 1, 224, 56, 15, 0, 252, 0, 224, 7, 0, 112, 6, 255, 231, 248], [127, 240, 63, 1, 224, 56, 15, 0, 252, 0, 224, 7, 0, 112, 6, 255, 231, 248], [127, 225, 255, 1, 224, 56, 15, 0, 252, 0, 224, 6, 0, 96, 14, 255, 195, 240], [63, 207, 254, 1, 192, 112, 14, 1, 252, 0, 112, 3, 0, 112, 7, 127, 227, 240], [255, 239, 254, 3, 192, 112, 14, 1, 252, 0, 224, 7, 0, 112, 6, 127, 231, 248], [255, 231, 254, 3, 128, 112, 31, 1, 252, 1, 224, 6, 0, 96, 14, 255, 199, 248], [255, 231, 254, 3, 192, 112, 14, 0, 252, 0, 224, 7, 0, 112, 14, 255, 199, 240], [127, 227, 255, 0, 224, 60, 15, 0, 252, 0, 224, 7, 0, 112, 7, 255, 231, 248], [127, 199, 255, 1, 224, 60, 15, 0, 248, 1, 224, 6, 0, 96, 14, 255, 199, 248]] }, { symbol: '4', fingerprints: [[12, 0, 192, 28, 1, 128, 48, 3, 24, 113, 134, 24, 255, 246, 24, 1, 192, 8], [6, 0, 192, 12, 1, 128, 56, 3, 24, 113, 134, 24, 255, 247, 152, 1, 192, 12], [6, 0, 224, 28, 1, 128, 48, 7, 24, 97, 142, 24, 255, 255, 252, 1, 192, 12], [6, 0, 224, 28, 1, 128, 48, 7, 24, 97, 142, 28, 255, 240, 28, 0, 192, 12], [7, 0, 224, 12, 1, 128, 56, 3, 8, 113, 198, 28, 255, 240, 12, 0, 192, 12], [6, 0, 96, 12, 1, 192, 24, 3, 24, 113, 134, 24, 255, 240, 24, 1, 128, 24], [3, 0, 96, 14, 1, 192, 24, 3, 8, 113, 134, 24, 255, 240, 24, 1, 128, 24], [7, 0, 224, 14, 1, 128, 56, 7, 8, 97, 206, 24, 255, 240, 24, 1, 128, 24], [3, 0, 112, 14, 1, 192, 56, 3, 12, 112, 206, 28, 255, 240, 28, 1, 128, 24], [3, 0, 112, 14, 1, 192, 24, 3, 12, 96, 206, 12, 255, 240, 24, 1, 128, 24], [1, 128, 112, 7, 0, 224, 24, 3, 8, 112, 206, 12, 255, 240, 28, 1, 128, 24], [14, 0, 192, 28, 1, 128, 56, 3, 24, 113, 134, 24, 255, 247, 156, 1, 192, 12], [6, 0, 224, 12, 1, 192, 56, 3, 24, 113, 134, 24, 255, 247, 252, 1, 192, 28], [6, 0, 224, 28, 1, 128, 56, 3, 24, 97, 206, 28, 255, 240, 28, 1, 192, 12], [6, 0, 224, 12, 1, 192, 56, 3, 24, 113, 142, 24, 255, 240, 24, 1, 128, 24], [3, 0, 96, 14, 1, 192, 24, 3, 152, 113, 142, 24, 255, 240, 24, 1, 128, 24], [3, 0, 112, 14, 0, 192, 24, 3, 136, 113, 198, 28, 255, 240, 28, 1, 128, 24], [3, 128, 112, 14, 1, 224, 24, 3, 12, 112, 206, 28, 255, 240, 28, 1, 128, 24], [3, 0, 112, 14, 0, 192, 24, 3, 136, 113, 206, 24, 255, 240, 24, 1, 128, 24], [12, 0, 192, 28, 1, 128, 56, 3, 24, 113, 142, 24, 255, 247, 220, 1, 192, 28], [14, 0, 224, 28, 1, 128, 56, 3, 24, 113, 134, 24, 255, 247, 252, 1, 192, 28], [6, 0, 224, 12, 1, 192, 56, 3, 24, 113, 198, 30, 255, 240, 28, 1, 192, 12], [6, 0, 224, 28, 1, 128, 56, 7, 24, 113, 142, 24, 255, 240, 24, 1, 128, 24], [7, 0, 112, 14, 1, 192, 24, 3, 152, 113, 206, 28, 255, 240, 24, 1, 128, 24], [3, 0, 112, 14, 1, 192, 56, 3, 152, 97, 143, 248, 255, 240, 24, 3, 128, 24], [3, 0, 112, 14, 1, 192, 56, 3, 24, 113, 143, 152, 255, 240, 24, 1, 128, 24], [3, 0, 112, 14, 0, 192, 28, 3, 136, 113, 207, 24, 255, 240, 30, 1, 128, 24]] }, { symbol: '5', fingerprints: [[255, 239, 128, 192, 12, 0, 255, 128, 30, 0, 96, 7, 0, 112, 14, 63, 199, 128], [255, 239, 224, 224, 14, 0, 255, 128, 30, 0, 112, 7, 0, 112, 14, 31, 207, 192], [127, 239, 252, 224, 14, 0, 255, 132, 62, 0, 112, 7, 0, 112, 14, 31, 207, 192], [127, 230, 0, 96, 14, 0, 255, 192, 14, 0, 112, 7, 0, 112, 15, 15, 239, 224], [127, 231, 0, 96, 6, 0, 127, 128, 30, 0, 224, 7, 0, 112, 14, 7, 207, 224], [127, 231, 254, 112, 7, 0, 127, 128, 30, 0, 224, 3, 0, 112, 14, 7, 239, 240], [63, 247, 0, 112, 7, 0, 127, 128, 30, 0, 112, 3, 0, 112, 14, 3, 239, 240], [63, 227, 0, 112, 7, 0, 127, 128, 30, 0, 96, 6, 0, 96, 14, 127, 199, 192], [63, 243, 142, 48, 3, 0, 127, 128, 30, 0, 96, 6, 0, 96, 14, 127, 199, 224], [63, 227, 126, 48, 3, 0, 63, 128, 28, 0, 224, 6, 0, 96, 14, 15, 199, 240], [31, 227, 255, 48, 3, 0, 63, 128, 28, 0, 224, 6, 0, 96, 14, 7, 199, 240], [63, 207, 252, 224, 14, 0, 255, 7, 254, 0, 112, 7, 0, 112, 30, 63, 199, 192], [127, 239, 248, 224, 14, 0, 255, 196, 30, 0, 112, 7, 0, 112, 14, 63, 199, 224], [127, 239, 252, 224, 14, 0, 255, 134, 62, 0, 112, 7, 0, 112, 15, 63, 239, 192], [127, 231, 254, 224, 14, 0, 255, 7, 254, 0, 224, 7, 0, 96, 14, 31, 207, 224], [127, 231, 224, 112, 6, 0, 127, 192, 30, 0, 224, 7, 0, 112, 14, 15, 207, 224], [63, 247, 255, 112, 7, 0, 127, 128, 30, 0, 112, 3, 0, 112, 14, 127, 207, 224], [63, 243, 2, 112, 7, 0, 127, 192, 30, 0, 96, 6, 0, 96, 30, 127, 207, 224], [63, 243, 191, 48, 7, 0, 127, 192, 30, 0, 96, 7, 0, 96, 14, 127, 207, 224], [63, 227, 255, 48, 3, 0, 63, 128, 28, 0, 224, 6, 0, 96, 14, 127, 207, 240], [127, 239, 252, 224, 14, 0, 255, 15, 254, 0, 240, 7, 0, 112, 30, 127, 199, 224], [127, 239, 252, 224, 14, 0, 255, 199, 62, 0, 112, 7, 0, 112, 14, 127, 231, 224], [255, 239, 252, 224, 14, 0, 255, 135, 254, 0, 224, 15, 0, 224, 30, 127, 207, 224], [127, 239, 254, 224, 14, 0, 255, 135, 254, 0, 224, 7, 0, 240, 14, 63, 207, 224], [127, 231, 252, 112, 7, 0, 255, 192, 30, 0, 240, 7, 0, 240, 30, 255, 207, 128], [127, 247, 254, 112, 7, 0, 127, 192, 30, 0, 112, 7, 0, 112, 30, 127, 207, 192], [127, 247, 255, 112, 7, 0, 127, 194, 62, 0, 112, 7, 0, 112, 14, 127, 239, 224], [63, 231, 255, 112, 7, 0, 127, 130, 126, 0, 96, 7, 0, 96, 30, 127, 207, 224], [63, 227, 254, 48, 7, 0, 127, 128, 30, 0, 224, 6, 0, 224, 14, 127, 207, 240], [63, 227, 254, 56, 3, 0, 63, 128, 60, 0, 224, 14, 0, 224, 12, 127, 207, 240]] }, { symbol: '6', fingerprints: [[3, 0, 96, 28, 3, 128, 48, 7, 252, 112, 238, 6, 192, 118, 6, 121, 225, 248], [3, 0, 96, 28, 3, 128, 63, 7, 254, 112, 238, 7, 224, 54, 7, 112, 225, 248], [3, 0, 240, 28, 3, 128, 127, 7, 254, 224, 108, 3, 192, 62, 6, 127, 225, 248], [1, 128, 112, 14, 3, 128, 55, 7, 254, 224, 108, 3, 192, 62, 7, 121, 225, 248], [3, 0, 112, 28, 3, 128, 63, 7, 252, 96, 236, 6, 192, 102, 6, 113, 225, 248], [3, 128, 112, 14, 1, 128, 63, 7, 252, 112, 238, 7, 192, 118, 6, 112, 225, 248], [1, 128, 112, 14, 1, 192, 63, 7, 252, 96, 110, 3, 224, 54, 6, 63, 225, 248], [1, 128, 112, 30, 3, 128, 127, 135, 254, 224, 108, 3, 192, 62, 6, 121, 225, 248], [1, 192, 120, 14, 1, 128, 63, 135, 254, 96, 108, 3, 192, 62, 7, 112, 225, 248], [0, 192, 56, 15, 1, 192, 63, 7, 254, 112, 110, 3, 192, 62, 7, 112, 225, 252], [1, 192, 120, 14, 1, 192, 63, 135, 158, 96, 108, 7, 192, 118, 6, 127, 193, 248], [3, 0, 224, 28, 3, 128, 54, 7, 252, 240, 238, 7, 224, 118, 6, 121, 225, 248], [3, 0, 112, 14, 1, 192, 56, 7, 252, 96, 110, 7, 224, 118, 6, 63, 225, 248], [3, 0, 112, 14, 1, 128, 63, 7, 254, 112, 126, 3, 224, 54, 7, 63, 225, 248], [3, 0, 112, 28, 3, 128, 127, 7, 252, 224, 236, 6, 192, 110, 6, 127, 193, 248], [3, 0, 112, 14, 1, 192, 62, 7, 252, 240, 238, 7, 192, 126, 6, 121, 225, 248], [3, 128, 112, 14, 1, 192, 63, 135, 254, 224, 110, 7, 224, 118, 6, 63, 193, 248], [1, 128, 56, 14, 1, 192, 63, 7, 254, 112, 110, 7, 224, 54, 7, 63, 225, 248], [1, 192, 120, 14, 3, 192, 63, 135, 254, 224, 124, 3, 192, 62, 7, 121, 225, 252], [1, 128, 120, 14, 1, 192, 63, 7, 252, 224, 108, 7, 192, 126, 6, 127, 193, 240], [1, 192, 56, 15, 1, 192, 63, 7, 252, 96, 110, 7, 224, 118, 6, 127, 225, 248], [3, 0, 224, 28, 3, 128, 127, 7, 252, 224, 110, 7, 224, 118, 6, 127, 225, 248], [3, 0, 112, 14, 1, 192, 58, 7, 252, 224, 126, 7, 224, 118, 7, 127, 225, 248], [7, 0, 224, 28, 3, 128, 127, 7, 252, 224, 236, 6, 192, 110, 14, 127, 193, 248], [3, 0, 112, 30, 3, 128, 127, 7, 252, 224, 238, 7, 192, 126, 6, 127, 225, 248], [3, 0, 112, 14, 1, 192, 62, 7, 252, 224, 110, 7, 224, 126, 14, 127, 193, 240], [1, 128, 120, 14, 1, 192, 62, 7, 252, 224, 110, 7, 224, 118, 6, 127, 225, 248], [1, 128, 120, 14, 1, 192, 63, 135, 254, 112, 126, 7, 224, 118, 7, 127, 225, 248], [1, 128, 112, 14, 3, 192, 63, 7, 252, 224, 236, 6, 192, 110, 14, 127, 195, 248], [1, 128, 120, 14, 1, 192, 63, 135, 254, 224, 238, 7, 224, 126, 14, 127, 193, 248]] }, { symbol: '7', fingerprints: [[127, 247, 199, 0, 224, 28, 3, 128, 48, 7, 0, 96, 14, 0, 192, 14, 0, 96], [127, 255, 243, 0, 96, 12, 1, 128, 112, 7, 0, 224, 14, 0, 224, 14, 0, 224], [255, 255, 255, 0, 96, 28, 3, 128, 112, 14, 0, 224, 12, 0, 192, 12, 0, 192], [255, 240, 3, 0, 96, 28, 3, 128, 112, 6, 0, 224, 12, 0, 192, 12, 0, 192], [255, 240, 7, 0, 224, 28, 3, 128, 112, 14, 0, 192, 24, 1, 128, 24, 1, 128], [255, 231, 254, 0, 224, 28, 3, 128, 96, 14, 0, 192, 28, 1, 128, 24, 1, 128], [255, 247, 255, 0, 96, 28, 3, 128, 112, 14, 1, 192, 24, 1, 128, 24, 1, 128], [255, 240, 6, 0, 224, 28, 3, 0, 96, 14, 1, 192, 24, 1, 128, 24, 1, 128], [255, 240, 31, 0, 96, 28, 7, 128, 224, 14, 1, 128, 24, 3, 128, 48, 3, 0], [255, 224, 255, 0, 96, 28, 7, 128, 224, 28, 1, 128, 48, 3, 0, 48, 3, 0], [255, 225, 255, 0, 112, 28, 7, 128, 240, 14, 1, 128, 56, 3, 0, 48, 3, 0], [31, 255, 255, 0, 96, 12, 1, 128, 48, 7, 0, 96, 14, 0, 224, 14, 0, 224], [127, 247, 255, 0, 96, 28, 3, 128, 112, 6, 0, 224, 12, 0, 192, 12, 0, 192], [127, 239, 255, 0, 224, 28, 3, 128, 112, 14, 0, 192, 12, 1, 192, 28, 0, 192], [255, 247, 247, 0, 224, 28, 7, 128, 112, 14, 0, 224, 28, 1, 128, 24, 1, 128], [255, 247, 255, 0, 224, 28, 3, 128, 112, 14, 0, 192, 28, 1, 128, 24, 1, 128], [255, 240, 127, 0, 96, 28, 7, 128, 240, 14, 1, 128, 24, 3, 128, 48, 3, 0], [255, 225, 255, 0, 224, 28, 3, 128, 224, 14, 1, 192, 24, 3, 128, 56, 3, 0], [63, 255, 255, 0, 96, 14, 3, 192, 56, 6, 0, 224, 14, 0, 224, 14, 0, 96], [63, 239, 255, 0, 224, 28, 3, 128, 112, 6, 0, 224, 12, 0, 192, 12, 0, 192], [255, 247, 255, 0, 224, 28, 3, 128, 112, 6, 0, 224, 12, 1, 192, 28, 0, 192], [255, 239, 254, 0, 224, 28, 7, 128, 224, 12, 1, 192, 24, 1, 128, 24, 1, 128], [255, 239, 255, 0, 224, 28, 3, 128, 240, 12, 1, 192, 56, 3, 128, 56, 3, 0], [127, 135, 255, 0, 112, 30, 3, 128, 112, 14, 1, 192, 24, 3, 128, 56, 3, 0], [255, 231, 255, 0, 224, 28, 7, 128, 224, 28, 3, 128, 56, 3, 0, 48, 3, 0]] }, { symbol: '8', fingerprints: [[63, 135, 28, 224, 198, 28, 63, 129, 248, 59, 198, 6, 224, 126, 7, 113, 227, 248], [31, 135, 156, 96, 198, 12, 63, 129, 248, 63, 199, 6, 96, 54, 7, 112, 227, 252], [63, 135, 252, 224, 230, 12, 127, 129, 248, 121, 238, 7, 192, 60, 7, 127, 225, 248], [31, 135, 252, 96, 102, 14, 59, 193, 248, 121, 238, 7, 192, 62, 3, 121, 225, 248], [63, 135, 28, 96, 231, 12, 63, 129, 248, 59, 198, 6, 192, 110, 6, 113, 227, 248], [31, 135, 156, 96, 103, 14, 63, 193, 248, 63, 198, 6, 224, 126, 7, 112, 227, 252], [31, 131, 254, 96, 99, 14, 63, 193, 248, 57, 230, 6, 224, 54, 7, 127, 225, 248], [15, 131, 254, 48, 99, 6, 29, 192, 248, 57, 198, 6, 224, 54, 7, 121, 225, 248], [31, 195, 142, 96, 99, 6, 31, 193, 248, 121, 206, 6, 192, 60, 3, 112, 227, 252], [31, 195, 142, 48, 51, 7, 31, 225, 248, 61, 198, 6, 192, 60, 3, 112, 227, 252], [15, 195, 254, 48, 51, 7, 31, 225, 248, 121, 238, 7, 192, 62, 3, 127, 225, 252], [63, 135, 188, 96, 198, 28, 63, 129, 248, 121, 230, 7, 224, 54, 7, 127, 225, 248], [31, 135, 252, 96, 231, 12, 63, 193, 248, 57, 230, 7, 224, 54, 7, 127, 225, 248], [31, 7, 252, 96, 198, 12, 123, 129, 240, 123, 206, 6, 192, 126, 6, 127, 227, 248], [63, 135, 28, 96, 231, 12, 63, 129, 248, 59, 198, 14, 224, 126, 7, 121, 227, 248], [31, 135, 190, 96, 103, 14, 63, 193, 248, 121, 238, 6, 224, 126, 7, 127, 225, 248], [31, 131, 254, 112, 103, 14, 63, 193, 248, 121, 230, 7, 224, 126, 7, 127, 225, 248], [15, 131, 254, 112, 99, 6, 61, 192, 248, 61, 230, 7, 224, 62, 7, 127, 225, 252], [31, 195, 142, 48, 115, 134, 31, 193, 248, 61, 231, 7, 224, 54, 7, 120, 225, 252], [31, 131, 158, 112, 99, 14, 31, 193, 248, 121, 206, 6, 192, 126, 6, 127, 225, 248], [31, 131, 254, 48, 115, 6, 31, 225, 248, 121, 206, 6, 192, 126, 6, 127, 225, 248], [31, 7, 252, 224, 206, 28, 123, 129, 248, 121, 238, 7, 224, 126, 7, 127, 225, 248], [63, 135, 252, 224, 230, 28, 63, 129, 248, 121, 230, 7, 224, 126, 7, 127, 225, 248], [63, 7, 252, 224, 206, 28, 127, 129, 248, 123, 206, 14, 192, 126, 6, 127, 227, 248], [31, 7, 252, 224, 198, 12, 127, 193, 248, 123, 206, 14, 224, 126, 7, 127, 227, 248], [31, 135, 252, 96, 230, 14, 63, 193, 248, 121, 238, 7, 224, 126, 7, 127, 225, 248], [31, 131, 254, 112, 99, 6, 63, 225, 248, 125, 231, 7, 224, 126, 7, 127, 225, 252], [31, 195, 254, 112, 99, 14, 31, 193, 248, 121, 238, 6, 192, 126, 6, 127, 225, 248], [31, 195, 254, 48, 115, 135, 31, 225, 248, 121, 206, 14, 224, 126, 7, 127, 225, 248]] }, { symbol: '9', fingerprints: [[31, 7, 252, 96, 108, 7, 192, 118, 6, 127, 224, 252, 1, 192, 56, 7, 0, 192], [31, 135, 142, 96, 110, 3, 96, 55, 14, 63, 224, 254, 1, 192, 56, 7, 0, 224], [31, 135, 142, 224, 124, 3, 192, 54, 7, 63, 224, 110, 1, 192, 120, 14, 0, 192], [31, 135, 158, 96, 110, 3, 224, 118, 6, 63, 224, 124, 1, 128, 112, 14, 0, 192], [31, 135, 254, 224, 124, 3, 192, 62, 7, 127, 224, 252, 1, 192, 112, 14, 1, 128], [31, 135, 14, 96, 108, 7, 224, 119, 14, 127, 224, 252, 1, 128, 112, 14, 1, 192], [31, 135, 30, 224, 124, 3, 192, 54, 6, 127, 225, 252, 1, 128, 112, 14, 1, 128], [31, 135, 156, 96, 108, 6, 192, 102, 14, 63, 224, 252, 3, 128, 112, 28, 1, 128], [31, 131, 254, 96, 110, 3, 224, 54, 6, 63, 224, 252, 3, 128, 112, 28, 1, 128], [31, 135, 14, 224, 124, 3, 192, 54, 6, 127, 225, 252, 3, 128, 112, 30, 3, 128], [31, 135, 158, 96, 108, 3, 224, 118, 6, 127, 225, 252, 3, 128, 112, 28, 3, 128], [31, 135, 252, 96, 110, 7, 224, 118, 6, 127, 225, 252, 1, 192, 56, 7, 0, 224], [15, 131, 254, 96, 110, 7, 224, 54, 7, 63, 224, 12, 1, 192, 56, 14, 0, 192], [31, 135, 158, 224, 108, 7, 224, 118, 14, 63, 224, 252, 3, 128, 112, 14, 0, 192], [31, 135, 254, 96, 110, 7, 224, 119, 7, 63, 224, 252, 1, 128, 112, 14, 0, 192], [31, 135, 252, 224, 108, 6, 192, 110, 14, 127, 225, 252, 3, 128, 112, 14, 1, 192], [31, 135, 252, 96, 110, 7, 224, 118, 6, 127, 225, 252, 3, 128, 112, 14, 1, 192], [31, 135, 158, 96, 126, 3, 224, 119, 7, 63, 224, 124, 3, 128, 112, 14, 1, 128], [31, 135, 254, 224, 110, 7, 224, 118, 14, 127, 224, 252, 3, 128, 112, 28, 1, 128], [31, 131, 254, 96, 110, 7, 224, 118, 7, 63, 224, 252, 3, 128, 112, 30, 1, 128], [31, 7, 252, 224, 108, 6, 192, 126, 6, 127, 225, 252, 3, 128, 240, 28, 3, 128], [31, 135, 158, 96, 110, 7, 224, 119, 14, 127, 225, 252, 3, 128, 112, 28, 3, 128], [31, 135, 254, 224, 110, 7, 224, 126, 15, 63, 224, 28, 3, 128, 112, 14, 0, 192], [31, 131, 254, 112, 126, 7, 224, 118, 7, 63, 224, 124, 1, 192, 120, 14, 0, 192], [63, 135, 254, 224, 110, 7, 224, 127, 14, 127, 224, 252, 3, 128, 112, 14, 0, 192], [31, 135, 254, 96, 126, 7, 224, 119, 15, 63, 224, 252, 3, 192, 112, 14, 0, 192], [31, 135, 252, 224, 236, 7, 224, 126, 14, 127, 225, 252, 3, 128, 112, 14, 1, 192], [31, 7, 252, 224, 236, 6, 192, 126, 14, 127, 224, 252, 3, 128, 240, 28, 1, 128], [31, 135, 254, 96, 126, 7, 224, 119, 7, 127, 224, 252, 3, 128, 112, 30, 1, 128], [31, 7, 252, 224, 238, 7, 192, 126, 14, 127, 225, 252, 3, 128, 240, 28, 3, 128], [31, 135, 254, 224, 126, 7, 224, 119, 14, 63, 224, 252, 7, 128, 240, 60, 3, 0]] }, { symbol: 'A', fingerprints: [[30, 1, 224, 63, 3, 48, 49, 131, 24, 48, 199, 252, 96, 102, 6, 96, 52, 0], [30, 1, 240, 31, 3, 184, 49, 131, 28, 48, 199, 252, 96, 102, 6, 96, 52, 2], [30, 1, 224, 59, 3, 184, 49, 135, 28, 97, 199, 252, 96, 110, 6, 192, 124, 3], [30, 1, 240, 27, 3, 184, 57, 131, 28, 113, 199, 252, 112, 110, 6, 192, 124, 3], [14, 1, 240, 31, 129, 184, 57, 131, 28, 49, 199, 254, 127, 230, 6, 192, 124, 3], [15, 1, 248, 31, 129, 152, 57, 195, 156, 48, 199, 254, 127, 230, 6, 192, 60, 3], [15, 0, 248, 31, 129, 216, 57, 195, 140, 48, 199, 254, 96, 102, 6, 192, 60, 3], [7, 128, 248, 13, 129, 220, 25, 195, 140, 56, 199, 254, 96, 230, 6, 192, 60, 3], [7, 128, 120, 13, 193, 220, 29, 195, 140, 56, 103, 254, 96, 102, 6, 192, 48, 3], [7, 128, 124, 15, 193, 220, 28, 195, 142, 56, 99, 254, 96, 102, 7, 192, 52, 3], [3, 128, 124, 7, 192, 204, 28, 193, 134, 56, 99, 254, 96, 102, 7, 192, 52, 3], [30, 1, 224, 63, 3, 112, 51, 131, 24, 112, 199, 252, 96, 102, 6, 224, 124, 0], [30, 1, 240, 31, 3, 184, 49, 131, 24, 48, 199, 252, 96, 102, 6, 96, 126, 2], [31, 1, 240, 31, 1, 184, 57, 131, 28, 48, 199, 254, 112, 102, 6, 96, 126, 3], [15, 1, 240, 27, 129, 152, 57, 131, 12, 48, 195, 254, 127, 230, 6, 96, 126, 3], [15, 0, 240, 31, 129, 152, 25, 195, 140, 48, 195, 254, 127, 230, 6, 96, 126, 3], [15, 0, 240, 15, 129, 216, 25, 131, 156, 56, 195, 252, 112, 230, 6, 96, 102, 6], [7, 0, 248, 13, 129, 216, 25, 193, 140, 56, 195, 252, 119, 230, 6, 96, 102, 7], [7, 0, 248, 13, 128, 216, 29, 193, 140, 56, 195, 254, 112, 102, 6, 96, 100, 6], [7, 128, 248, 15, 129, 220, 24, 195, 140, 48, 199, 254, 96, 230, 6, 224, 108, 6], [7, 128, 248, 15, 193, 220, 24, 195, 140, 56, 231, 254, 96, 110, 6, 192, 96, 2], [30, 3, 240, 63, 3, 240, 51, 131, 24, 113, 199, 254, 96, 230, 6, 224, 126, 2], [30, 1, 224, 63, 3, 176, 59, 131, 24, 113, 199, 252, 112, 230, 14, 224, 110, 2], [30, 1, 240, 31, 3, 176, 59, 131, 24, 49, 199, 252, 124, 230, 14, 224, 110, 6], [14, 1, 240, 31, 1, 184, 59, 131, 24, 49, 199, 252, 127, 230, 14, 96, 110, 6], [15, 1, 240, 31, 1, 184, 57, 131, 156, 49, 199, 252, 112, 230, 14, 224, 102, 2], [7, 0, 240, 15, 129, 216, 25, 131, 156, 56, 195, 252, 119, 231, 6, 96, 110, 7], [7, 0, 248, 13, 129, 216, 29, 195, 156, 56, 195, 254, 112, 230, 6, 224, 116, 6], [7, 128, 248, 15, 128, 216, 29, 193, 140, 56, 195, 254, 112, 231, 6, 224, 100, 7], [7, 128, 120, 15, 192, 252, 28, 193, 140, 60, 227, 254, 112, 103, 6, 224, 112, 6]] }, { symbol: 'B', fingerprints: [[255, 143, 142, 192, 108, 6, 224, 231, 254, 120, 246, 3, 96, 54, 7, 127, 231, 224], [255, 143, 220, 192, 108, 6, 192, 239, 252, 253, 238, 7, 96, 54, 14, 127, 231, 240], [255, 143, 254, 192, 108, 6, 192, 239, 252, 255, 230, 3, 96, 54, 6, 127, 231, 248], [255, 206, 14, 224, 110, 6, 225, 231, 252, 96, 230, 3, 96, 54, 7, 127, 231, 248], [255, 140, 30, 192, 108, 6, 192, 239, 252, 224, 236, 6, 192, 124, 6, 255, 207, 248], [255, 142, 30, 192, 108, 6, 192, 239, 252, 227, 236, 7, 192, 124, 6, 255, 239, 248], [127, 135, 254, 96, 102, 7, 96, 111, 254, 255, 238, 7, 224, 62, 7, 255, 239, 252], [127, 135, 254, 96, 102, 3, 96, 103, 254, 127, 230, 7, 96, 62, 7, 255, 239, 252], [127, 134, 62, 96, 102, 7, 224, 111, 254, 195, 236, 6, 192, 108, 6, 255, 207, 248], [127, 134, 126, 96, 118, 3, 96, 119, 254, 239, 236, 6, 192, 108, 6, 255, 239, 252], [255, 207, 222, 192, 110, 6, 225, 239, 254, 124, 246, 3, 96, 54, 15, 127, 231, 240], [255, 143, 254, 192, 236, 6, 193, 239, 252, 255, 238, 7, 224, 118, 14, 127, 231, 240], [255, 143, 254, 192, 108, 6, 224, 239, 252, 255, 238, 7, 224, 54, 7, 127, 231, 248], [255, 140, 30, 192, 236, 6, 195, 207, 252, 192, 236, 6, 192, 124, 14, 255, 207, 248], [255, 142, 62, 192, 108, 6, 193, 239, 252, 241, 236, 7, 192, 126, 6, 255, 207, 248], [255, 143, 254, 224, 110, 6, 224, 239, 252, 255, 238, 7, 224, 126, 7, 255, 239, 252], [127, 7, 254, 96, 230, 7, 224, 127, 254, 255, 204, 6, 192, 124, 6, 255, 239, 252], [126, 7, 254, 96, 230, 3, 96, 127, 254, 255, 206, 6, 192, 124, 6, 249, 239, 252], [255, 207, 254, 224, 110, 6, 225, 239, 254, 255, 246, 3, 96, 54, 15, 127, 231, 240], [255, 143, 254, 192, 236, 6, 193, 239, 254, 255, 238, 7, 224, 126, 15, 255, 231, 248], [255, 143, 252, 192, 236, 6, 192, 239, 252, 255, 236, 7, 224, 126, 14, 255, 239, 248], [255, 143, 254, 192, 108, 6, 225, 239, 252, 255, 238, 7, 224, 126, 6, 255, 239, 248], [255, 143, 254, 224, 238, 7, 224, 111, 252, 255, 236, 6, 192, 124, 14, 255, 239, 248]] }, { symbol: 'C', fingerprints: [[31, 135, 222, 112, 238, 0, 224, 14, 0, 224, 14, 0, 96, 7, 7, 60, 240, 252], [31, 135, 254, 112, 230, 0, 224, 14, 0, 224, 6, 0, 112, 7, 7, 60, 113, 254], [31, 199, 142, 112, 102, 0, 224, 14, 0, 96, 6, 0, 112, 3, 135, 31, 240, 252], [31, 199, 142, 112, 110, 0, 224, 14, 0, 224, 14, 0, 96, 7, 135, 60, 241, 252], [31, 195, 255, 112, 118, 0, 224, 14, 0, 224, 14, 0, 96, 7, 7, 60, 113, 254], [15, 131, 254, 112, 102, 0, 96, 14, 0, 224, 6, 0, 112, 7, 6, 63, 224, 248], [31, 231, 143, 112, 126, 0, 224, 14, 0, 224, 14, 0, 224, 7, 7, 125, 225, 252], [31, 227, 207, 120, 118, 0, 224, 14, 0, 224, 14, 0, 224, 7, 7, 120, 225, 252], [15, 195, 254, 112, 119, 0, 224, 14, 0, 224, 14, 0, 96, 7, 6, 120, 225, 252], [15, 227, 199, 112, 119, 0, 96, 14, 0, 224, 14, 0, 96, 7, 6, 63, 224, 248], [31, 195, 206, 112, 118, 0, 224, 14, 0, 224, 14, 0, 224, 7, 14, 121, 225, 248], [31, 135, 254, 112, 110, 0, 224, 14, 0, 224, 14, 0, 112, 7, 7, 63, 240, 252], [15, 131, 254, 112, 103, 0, 224, 14, 0, 224, 6, 0, 112, 7, 7, 63, 240, 252], [31, 199, 223, 112, 126, 0, 224, 14, 0, 224, 14, 0, 224, 7, 135, 127, 241, 254], [31, 135, 254, 112, 110, 0, 224, 14, 0, 224, 14, 0, 96, 7, 7, 124, 225, 252], [15, 131, 254, 112, 103, 0, 224, 14, 0, 224, 14, 0, 112, 7, 7, 63, 224, 248], [31, 227, 207, 112, 119, 0, 96, 14, 0, 224, 6, 0, 112, 7, 7, 63, 224, 252], [31, 199, 222, 112, 126, 0, 224, 14, 0, 224, 14, 0, 224, 7, 14, 125, 225, 248], [15, 195, 255, 112, 119, 0, 224, 14, 0, 224, 14, 0, 96, 7, 6, 63, 224, 248], [15, 195, 254, 112, 103, 0, 96, 14, 0, 224, 14, 0, 96, 7, 14, 63, 225, 248], [15, 195, 239, 56, 119, 0, 112, 14, 0, 224, 14, 0, 96, 7, 14, 63, 225, 248], [31, 199, 254, 112, 231, 0, 224, 14, 0, 112, 7, 0, 112, 35, 135, 63, 224, 124], [15, 131, 254, 112, 231, 0, 224, 14, 0, 224, 15, 0, 112, 7, 6, 63, 224, 252], [31, 195, 254, 112, 231, 0, 224, 14, 0, 224, 7, 0, 112, 7, 135, 63, 224, 252], [15, 195, 255, 112, 119, 0, 240, 14, 0, 224, 14, 0, 112, 7, 7, 63, 241, 252], [15, 195, 255, 120, 119, 0, 112, 15, 0, 240, 7, 0, 112, 7, 14, 63, 225, 252], [15, 195, 255, 112, 119, 0, 224, 14, 0, 224, 14, 0, 240, 7, 14, 127, 225, 248], [15, 195, 255, 120, 119, 0, 112, 14, 0, 224, 14, 0, 112, 7, 14, 127, 225, 252]] }, { symbol: 'D', fingerprints: [[252, 15, 248, 193, 206, 14, 96, 118, 3, 96, 55, 3, 112, 103, 30, 127, 135, 224], [254, 15, 248, 97, 230, 14, 96, 118, 3, 112, 55, 3, 112, 119, 30, 127, 199, 240], [254, 15, 240, 193, 206, 14, 224, 102, 7, 96, 118, 6, 96, 230, 30, 127, 135, 224], [254, 14, 120, 97, 198, 14, 96, 118, 3, 96, 54, 7, 96, 230, 28, 127, 7, 224], [254, 14, 248, 227, 206, 14, 224, 126, 7, 224, 126, 7, 224, 110, 30, 255, 143, 224], [254, 14, 248, 225, 206, 14, 224, 110, 6, 224, 110, 6, 224, 238, 28, 255, 15, 224], [124, 7, 248, 97, 198, 14, 96, 102, 7, 96, 118, 6, 96, 230, 28, 255, 143, 224], [124, 7, 248, 113, 198, 14, 96, 102, 3, 96, 54, 7, 96, 102, 30, 127, 143, 224], [126, 7, 248, 113, 199, 14, 112, 119, 3, 96, 54, 3, 96, 102, 14, 127, 199, 240], [62, 7, 248, 97, 198, 6, 96, 102, 6, 96, 118, 6, 96, 102, 30, 127, 135, 240], [62, 3, 248, 49, 199, 6, 96, 102, 7, 96, 54, 6, 96, 102, 28, 127, 143, 224], [254, 7, 248, 99, 198, 14, 96, 118, 7, 112, 55, 7, 112, 115, 30, 63, 131, 240], [252, 15, 248, 227, 198, 14, 96, 102, 7, 96, 118, 6, 96, 230, 60, 127, 135, 192], [254, 14, 248, 225, 206, 14, 224, 110, 7, 224, 118, 6, 96, 231, 60, 127, 7, 224], [254, 14, 248, 225, 206, 14, 96, 118, 7, 96, 118, 7, 112, 231, 30, 127, 135, 224], [254, 15, 248, 227, 206, 14, 224, 238, 7, 224, 126, 6, 224, 238, 28, 255, 15, 224], [126, 7, 248, 99, 198, 14, 96, 102, 7, 224, 126, 7, 224, 238, 30, 255, 143, 224], [126, 7, 248, 115, 199, 14, 112, 119, 7, 96, 54, 7, 96, 238, 30, 255, 143, 240], [126, 7, 248, 115, 199, 14, 112, 119, 3, 112, 55, 7, 96, 118, 30, 255, 207, 240], [126, 7, 248, 113, 198, 14, 96, 102, 7, 96, 118, 6, 96, 102, 60, 255, 143, 224], [62, 3, 248, 113, 199, 6, 112, 118, 7, 96, 118, 7, 96, 102, 30, 255, 143, 224], [254, 7, 248, 99, 198, 14, 96, 103, 6, 112, 119, 6, 112, 231, 60, 63, 131, 224], [252, 15, 248, 227, 206, 30, 96, 102, 7, 96, 118, 7, 96, 231, 60, 127, 135, 224], [252, 7, 248, 99, 198, 14, 96, 102, 7, 96, 118, 7, 112, 103, 60, 127, 135, 224], [254, 15, 252, 225, 206, 14, 224, 126, 7, 112, 119, 7, 112, 231, 30, 127, 135, 224], [254, 7, 248, 99, 198, 14, 96, 102, 7, 96, 118, 6, 96, 230, 60, 127, 135, 224], [126, 7, 248, 243, 206, 14, 224, 254, 7, 224, 126, 7, 224, 238, 30, 255, 143, 240], [126, 7, 248, 115, 199, 14, 112, 119, 7, 112, 126, 7, 224, 254, 30, 255, 207, 240], [124, 7, 248, 99, 198, 30, 96, 102, 7, 96, 118, 6, 224, 238, 60, 255, 143, 224], [124, 7, 248, 115, 199, 14, 96, 102, 7, 96, 118, 7, 96, 238, 60, 255, 207, 224], [60, 7, 248, 115, 199, 14, 112, 119, 7, 96, 118, 7, 96, 102, 30, 255, 207, 224]] }, { symbol: 'E', fingerprints: [[63, 207, 248, 192, 12, 0, 224, 7, 252, 127, 134, 0, 96, 6, 0, 103, 247, 254], [255, 207, 128, 224, 6, 0, 96, 7, 252, 120, 6, 0, 96, 6, 0, 127, 247, 255], [255, 239, 224, 192, 12, 0, 224, 15, 252, 127, 6, 0, 96, 6, 0, 127, 247, 255], [255, 239, 252, 224, 6, 0, 96, 7, 252, 127, 198, 0, 96, 6, 0, 127, 247, 254], [255, 236, 0, 192, 12, 0, 192, 15, 254, 224, 12, 0, 192, 12, 0, 255, 255, 255], [255, 238, 0, 224, 14, 0, 224, 15, 254, 224, 14, 0, 224, 14, 0, 255, 255, 255], [127, 247, 254, 96, 6, 0, 96, 7, 254, 127, 198, 0, 96, 14, 0, 255, 255, 255], [127, 231, 254, 96, 6, 0, 96, 7, 252, 127, 198, 0, 96, 6, 0, 255, 239, 254], [127, 246, 6, 96, 6, 0, 96, 7, 254, 96, 70, 0, 96, 6, 0, 255, 239, 254], [127, 231, 62, 96, 6, 0, 96, 7, 252, 103, 198, 0, 96, 6, 0, 127, 207, 254], [63, 227, 127, 112, 7, 0, 96, 7, 252, 111, 198, 0, 96, 6, 0, 127, 131, 254], [127, 199, 252, 96, 6, 0, 96, 7, 252, 127, 199, 0, 112, 7, 0, 63, 243, 254], [255, 239, 224, 224, 6, 0, 96, 7, 252, 126, 6, 0, 96, 6, 0, 127, 247, 252], [255, 231, 248, 96, 6, 0, 96, 7, 252, 127, 134, 0, 96, 6, 0, 127, 247, 254], [255, 239, 254, 224, 14, 0, 224, 7, 252, 127, 198, 0, 96, 6, 0, 127, 247, 255], [255, 255, 254, 224, 14, 0, 224, 15, 254, 255, 206, 0, 224, 14, 0, 255, 255, 255], [127, 247, 255, 96, 6, 0, 224, 15, 254, 255, 238, 0, 224, 14, 0, 255, 255, 255], [127, 231, 255, 96, 6, 0, 96, 7, 254, 127, 230, 0, 96, 14, 0, 255, 207, 254], [127, 231, 126, 112, 6, 0, 96, 7, 252, 111, 198, 0, 96, 14, 0, 255, 231, 254], [63, 231, 255, 112, 7, 0, 96, 7, 252, 127, 198, 0, 96, 6, 0, 255, 199, 254], [127, 207, 252, 96, 6, 0, 96, 7, 252, 126, 7, 0, 112, 7, 0, 63, 243, 248], [255, 239, 254, 224, 6, 0, 96, 7, 254, 127, 230, 0, 96, 6, 0, 127, 247, 255], [127, 231, 255, 96, 6, 0, 96, 7, 254, 255, 206, 0, 224, 14, 0, 255, 239, 254], [127, 231, 255, 112, 7, 0, 96, 7, 252, 127, 198, 0, 224, 14, 0, 255, 239, 254], [63, 7, 255, 112, 7, 0, 112, 7, 252, 127, 198, 0, 96, 14, 0, 255, 207, 254]] }, { symbol: 'F', fingerprints: [[127, 239, 254, 224, 15, 0, 112, 7, 254, 112, 7, 0, 112, 7, 0, 112, 3, 0], [255, 247, 192, 112, 7, 0, 112, 7, 254, 124, 7, 0, 112, 7, 0, 112, 3, 0], [255, 255, 240, 224, 15, 0, 240, 7, 254, 127, 7, 0, 112, 7, 0, 112, 7, 0], [255, 247, 254, 112, 7, 0, 112, 7, 254, 127, 199, 0, 112, 7, 0, 112, 7, 0], [255, 254, 0, 224, 14, 0, 224, 15, 254, 240, 15, 0, 240, 15, 0, 240, 7, 0], [255, 255, 0, 240, 15, 0, 240, 15, 254, 240, 15, 0, 240, 15, 0, 240, 7, 0], [255, 239, 254, 224, 14, 0, 224, 15, 252, 255, 206, 0, 224, 14, 0, 224, 12, 0], [127, 255, 255, 240, 15, 0, 224, 15, 254, 255, 206, 0, 224, 14, 0, 224, 14, 0], [127, 246, 6, 96, 6, 0, 224, 15, 252, 225, 142, 0, 224, 14, 0, 224, 14, 0], [127, 247, 127, 96, 6, 0, 96, 7, 252, 231, 206, 0, 224, 14, 0, 224, 14, 0], [127, 231, 254, 112, 7, 0, 96, 7, 248, 127, 142, 0, 224, 14, 0, 224, 14, 0], [255, 255, 254, 240, 15, 0, 240, 7, 254, 124, 7, 0, 112, 7, 0, 120, 7, 0], [255, 255, 240, 240, 7, 0, 112, 7, 254, 127, 7, 0, 112, 7, 128, 120, 7, 128], [255, 255, 252, 240, 15, 0, 240, 15, 254, 255, 199, 0, 112, 7, 0, 112, 7, 0], [255, 255, 254, 240, 15, 0, 112, 7, 254, 127, 231, 0, 112, 7, 0, 112, 7, 0], [255, 255, 254, 240, 15, 0, 240, 15, 254, 255, 207, 0, 240, 15, 0, 240, 7, 0], [127, 247, 254, 96, 6, 0, 96, 7, 254, 127, 206, 0, 224, 14, 0, 224, 6, 0], [127, 247, 255, 112, 7, 0, 112, 7, 254, 127, 230, 0, 96, 14, 0, 224, 6, 0], [127, 231, 255, 112, 7, 0, 112, 7, 252, 127, 199, 0, 96, 6, 0, 224, 6, 0], [63, 227, 255, 112, 7, 0, 112, 7, 252, 127, 199, 0, 112, 6, 0, 96, 6, 0], [127, 247, 254, 112, 7, 0, 112, 7, 254, 127, 7, 128, 120, 7, 128, 56, 3, 128], [255, 255, 255, 240, 15, 0, 112, 7, 254, 127, 199, 0, 120, 7, 128, 120, 7, 128], [255, 247, 254, 112, 7, 0, 112, 7, 254, 127, 199, 128, 120, 7, 128, 120, 7, 128], [255, 239, 254, 224, 14, 0, 224, 15, 254, 127, 199, 0, 112, 7, 0, 112, 7, 0], [127, 231, 254, 112, 7, 0, 112, 7, 252, 127, 207, 0, 224, 14, 0, 224, 14, 0]] }, { symbol: 'G', fingerprints: [[31, 131, 222, 112, 78, 0, 192, 12, 30, 199, 238, 7, 96, 55, 3, 56, 113, 254], [15, 131, 252, 112, 70, 0, 224, 14, 6, 231, 230, 6, 96, 103, 6, 56, 97, 254], [31, 199, 142, 96, 78, 0, 192, 12, 126, 199, 236, 6, 96, 103, 6, 63, 241, 252], [31, 195, 142, 112, 78, 0, 192, 12, 62, 199, 238, 6, 96, 103, 7, 56, 241, 252], [15, 195, 238, 112, 102, 0, 224, 14, 2, 231, 238, 7, 96, 119, 7, 56, 113, 254], [31, 195, 254, 96, 46, 0, 192, 12, 0, 199, 252, 3, 224, 54, 3, 63, 241, 252], [31, 195, 135, 112, 46, 0, 192, 12, 63, 195, 252, 3, 96, 55, 3, 61, 241, 254], [31, 195, 207, 112, 54, 0, 224, 12, 0, 195, 254, 3, 96, 55, 3, 56, 113, 254], [15, 195, 254, 112, 102, 0, 96, 14, 0, 231, 254, 6, 96, 103, 6, 56, 97, 254], [31, 231, 135, 112, 62, 0, 192, 12, 62, 199, 252, 7, 224, 102, 6, 127, 225, 252], [31, 195, 199, 112, 54, 0, 224, 12, 48, 199, 252, 7, 224, 118, 6, 124, 225, 254], [31, 135, 252, 112, 206, 0, 224, 12, 62, 231, 238, 6, 96, 103, 6, 56, 241, 252], [15, 131, 252, 112, 6, 0, 224, 14, 30, 231, 230, 6, 96, 103, 6, 63, 240, 252], [15, 131, 254, 112, 70, 0, 96, 14, 2, 103, 230, 6, 112, 103, 7, 63, 240, 252], [31, 199, 142, 112, 110, 0, 224, 12, 62, 199, 238, 7, 96, 119, 7, 61, 241, 254], [31, 195, 254, 112, 102, 0, 224, 14, 30, 231, 254, 7, 96, 119, 7, 56, 241, 254], [15, 195, 254, 112, 38, 0, 96, 14, 0, 231, 246, 7, 96, 119, 7, 63, 240, 252], [31, 231, 207, 112, 46, 0, 224, 12, 63, 199, 254, 3, 224, 119, 7, 127, 241, 254], [31, 195, 254, 112, 102, 0, 224, 14, 62, 231, 238, 6, 224, 103, 6, 120, 225, 254], [15, 195, 254, 112, 38, 0, 96, 14, 0, 231, 254, 7, 96, 103, 6, 63, 224, 252], [15, 195, 255, 112, 55, 0, 96, 6, 0, 231, 254, 7, 96, 119, 6, 63, 224, 252], [31, 195, 206, 112, 118, 0, 224, 12, 120, 199, 236, 6, 224, 102, 6, 127, 225, 252], [31, 135, 252, 96, 14, 0, 224, 14, 62, 231, 238, 6, 112, 103, 7, 63, 240, 252], [31, 131, 252, 112, 78, 0, 224, 14, 62, 231, 238, 6, 112, 119, 7, 63, 240, 252], [15, 131, 254, 112, 70, 0, 224, 14, 14, 231, 230, 7, 112, 119, 7, 63, 240, 252], [31, 199, 254, 112, 110, 0, 224, 14, 127, 231, 254, 7, 224, 119, 7, 63, 241, 254], [31, 195, 254, 112, 46, 0, 224, 14, 63, 231, 254, 7, 96, 119, 7, 63, 240, 252], [15, 195, 254, 112, 38, 0, 224, 14, 31, 231, 254, 7, 96, 119, 7, 63, 240, 254], [15, 195, 255, 112, 39, 0, 96, 14, 0, 231, 246, 7, 96, 119, 7, 63, 241, 254], [31, 195, 254, 112, 110, 0, 224, 14, 126, 231, 254, 7, 224, 103, 6, 127, 225, 254], [15, 195, 255, 112, 38, 0, 224, 14, 56, 231, 254, 7, 96, 119, 6, 63, 224, 252], [15, 131, 254, 120, 119, 0, 96, 6, 0, 231, 238, 6, 96, 103, 6, 63, 225, 254]] }, { symbol: 'H', fingerprints: [[64, 108, 6, 192, 110, 6, 96, 103, 254, 126, 102, 6, 96, 118, 3, 96, 50, 0], [64, 110, 6, 96, 102, 6, 96, 103, 254, 127, 102, 7, 96, 54, 3, 96, 50, 2], [192, 108, 6, 192, 110, 6, 224, 103, 255, 127, 246, 3, 96, 54, 3, 96, 54, 3], [64, 110, 6, 96, 118, 7, 96, 119, 255, 127, 246, 3, 96, 54, 3, 96, 54, 3], [192, 60, 3, 192, 60, 3, 192, 63, 255, 255, 254, 3, 224, 62, 3, 224, 54, 3], [96, 62, 3, 224, 62, 3, 224, 63, 255, 255, 254, 3, 224, 62, 3, 224, 54, 3], [192, 60, 3, 192, 60, 3, 192, 63, 255, 255, 252, 7, 192, 124, 7, 192, 108, 6], [96, 62, 3, 224, 62, 3, 192, 63, 255, 255, 252, 3, 192, 124, 7, 192, 124, 6], [96, 38, 3, 96, 54, 7, 224, 111, 254, 255, 236, 6, 192, 108, 6, 192, 108, 6], [96, 38, 3, 96, 54, 3, 96, 55, 255, 239, 236, 6, 192, 108, 6, 192, 100, 6], [96, 6, 3, 96, 118, 6, 96, 103, 254, 127, 238, 6, 192, 108, 6, 192, 236, 12], [64, 236, 14, 224, 110, 6, 224, 103, 254, 127, 102, 7, 96, 118, 7, 112, 55, 2], [64, 110, 6, 224, 102, 6, 96, 103, 254, 127, 246, 7, 96, 118, 7, 112, 55, 3], [64, 108, 6, 224, 110, 6, 224, 127, 255, 255, 246, 7, 96, 118, 3, 96, 54, 3], [96, 110, 6, 224, 110, 6, 96, 103, 254, 127, 230, 6, 96, 102, 6, 96, 102, 6], [192, 108, 6, 192, 110, 6, 224, 111, 254, 255, 238, 6, 224, 110, 7, 224, 126, 6], [64, 110, 7, 224, 126, 7, 224, 127, 255, 255, 254, 7, 224, 126, 7, 224, 126, 7], [96, 54, 7, 96, 118, 7, 96, 119, 255, 127, 254, 7, 224, 126, 7, 224, 118, 6], [96, 102, 7, 96, 118, 6, 96, 103, 254, 127, 230, 6, 96, 110, 6, 224, 102, 6], [96, 54, 7, 96, 118, 7, 96, 119, 255, 111, 230, 6, 96, 102, 6, 224, 100, 6], [48, 39, 7, 112, 103, 6, 96, 103, 254, 127, 230, 6, 96, 102, 14, 224, 228, 14], [48, 3, 7, 112, 119, 7, 112, 103, 254, 127, 230, 6, 96, 102, 6, 96, 228, 14], [0, 204, 12, 224, 238, 14, 224, 239, 254, 127, 230, 6, 96, 103, 6, 112, 119, 2], [64, 206, 14, 224, 238, 14, 96, 231, 254, 127, 230, 6, 96, 103, 6, 112, 119, 6], [192, 238, 14, 224, 238, 6, 224, 111, 254, 255, 238, 6, 96, 102, 6, 96, 118, 6], [224, 110, 6, 224, 110, 6, 224, 111, 254, 127, 230, 6, 96, 118, 7, 96, 118, 6], [192, 110, 6, 224, 110, 6, 224, 111, 255, 255, 254, 7, 224, 126, 7, 224, 118, 6], [96, 54, 7, 96, 126, 7, 224, 127, 255, 255, 254, 7, 224, 126, 7, 224, 126, 7], [96, 118, 7, 96, 118, 7, 96, 119, 254, 127, 238, 6, 224, 110, 6, 224, 110, 6], [112, 55, 7, 96, 118, 7, 96, 119, 255, 127, 246, 6, 224, 110, 6, 224, 100, 6], [112, 39, 7, 112, 119, 6, 112, 103, 254, 127, 230, 6, 96, 238, 14, 224, 228, 14], [48, 39, 7, 112, 119, 7, 112, 119, 254, 127, 230, 6, 96, 238, 14, 224, 224, 12]] }, { symbol: 'I', fingerprints: [[255, 199, 192, 12, 0, 224, 14, 0, 224, 14, 0, 240, 15, 0, 112, 127, 247, 254], [255, 207, 224, 14, 0, 224, 14, 0, 224, 14, 0, 96, 6, 0, 96, 127, 247, 255], [127, 199, 240, 14, 0, 224, 14, 0, 224, 6, 0, 96, 6, 0, 96, 127, 247, 255], [255, 239, 252, 14, 0, 224, 14, 0, 224, 14, 0, 224, 14, 0, 224, 127, 239, 255], [255, 224, 224, 14, 0, 224, 14, 0, 224, 14, 0, 224, 14, 0, 224, 255, 255, 255], [127, 224, 240, 15, 0, 240, 15, 0, 240, 15, 0, 240, 15, 0, 240, 255, 255, 255], [127, 227, 254, 7, 0, 112, 7, 0, 112, 7, 0, 112, 7, 0, 240, 255, 239, 255], [127, 240, 112, 7, 0, 112, 7, 0, 96, 6, 0, 96, 6, 0, 96, 255, 239, 254], [63, 240, 126, 7, 0, 112, 7, 0, 112, 7, 0, 96, 6, 0, 96, 255, 239, 254], [63, 224, 254, 3, 0, 112, 7, 0, 112, 7, 0, 240, 14, 0, 224, 255, 199, 254], [127, 143, 248, 12, 0, 224, 14, 0, 224, 14, 0, 240, 15, 0, 112, 15, 247, 254], [127, 199, 240, 14, 0, 224, 14, 0, 240, 15, 0, 240, 15, 0, 112, 127, 247, 255], [255, 231, 248, 14, 0, 224, 14, 0, 224, 14, 0, 96, 6, 0, 96, 127, 247, 254], [255, 224, 240, 14, 0, 224, 14, 0, 224, 15, 0, 240, 15, 0, 240, 255, 255, 255], [127, 231, 254, 15, 0, 240, 15, 0, 240, 15, 0, 240, 15, 0, 240, 255, 255, 255], [63, 225, 255, 7, 0, 112, 7, 0, 112, 15, 0, 240, 15, 0, 224, 255, 199, 254], [127, 207, 248, 14, 0, 224, 14, 0, 224, 15, 0, 240, 15, 0, 240, 31, 247, 255], [255, 239, 252, 14, 0, 224, 14, 0, 224, 14, 0, 224, 15, 0, 112, 127, 247, 254], [127, 231, 254, 14, 0, 224, 14, 0, 224, 14, 0, 112, 7, 0, 112, 127, 247, 255], [127, 231, 254, 15, 0, 112, 7, 0, 112, 7, 0, 112, 7, 0, 112, 127, 247, 255], [127, 231, 254, 7, 0, 112, 7, 0, 112, 15, 0, 224, 14, 0, 224, 255, 239, 254], [127, 227, 255, 7, 0, 112, 7, 0, 112, 7, 0, 112, 14, 0, 224, 255, 239, 254], [127, 225, 254, 7, 0, 240, 15, 0, 240, 15, 0, 240, 15, 0, 224, 255, 231, 254]] }, { symbol: 'J', fingerprints: [[1, 192, 30, 1, 224, 14, 0, 224, 14, 0, 240, 7, 96, 127, 7, 112, 243, 252], [0, 224, 14, 0, 224, 14, 0, 240, 7, 0, 112, 7, 224, 119, 7, 127, 241, 252], [1, 192, 30, 1, 224, 14, 0, 224, 14, 0, 224, 14, 192, 254, 14, 241, 227, 252], [0, 224, 14, 0, 224, 14, 0, 224, 14, 0, 224, 15, 224, 254, 15, 241, 227, 252], [0, 224, 15, 0, 240, 15, 0, 240, 15, 0, 240, 7, 224, 126, 15, 113, 227, 252], [0, 112, 7, 0, 112, 7, 0, 112, 7, 0, 112, 7, 224, 127, 15, 127, 225, 248], [0, 224, 14, 0, 224, 14, 0, 224, 14, 0, 224, 14, 224, 239, 14, 127, 225, 248], [0, 112, 7, 0, 112, 7, 0, 240, 15, 0, 240, 14, 224, 239, 14, 121, 227, 248], [0, 96, 6, 0, 96, 6, 0, 96, 6, 0, 224, 14, 224, 230, 14, 127, 195, 248], [0, 112, 7, 0, 240, 15, 0, 224, 14, 0, 224, 14, 224, 238, 14, 127, 231, 248], [0, 96, 6, 0, 96, 6, 0, 224, 14, 0, 224, 14, 225, 238, 28, 127, 195, 240], [1, 192, 30, 1, 224, 30, 0, 224, 15, 0, 240, 7, 224, 127, 7, 127, 241, 252], [0, 224, 14, 0, 224, 14, 0, 224, 14, 0, 224, 14, 240, 255, 15, 127, 225, 248], [0, 224, 14, 0, 224, 14, 0, 224, 14, 0, 224, 15, 240, 247, 15, 127, 225, 252], [0, 224, 14, 0, 224, 14, 0, 240, 15, 0, 240, 15, 112, 247, 15, 121, 225, 252], [0, 224, 15, 0, 240, 15, 0, 240, 15, 0, 240, 15, 224, 255, 15, 127, 225, 248], [0, 240, 15, 0, 240, 15, 0, 240, 14, 0, 224, 14, 224, 239, 14, 127, 227, 248], [0, 112, 7, 0, 240, 15, 0, 240, 15, 0, 240, 15, 240, 255, 14, 127, 227, 252], [0, 96, 7, 0, 112, 6, 0, 96, 14, 0, 224, 14, 224, 238, 14, 121, 227, 248], [0, 112, 7, 0, 112, 7, 0, 112, 6, 0, 100, 14, 224, 230, 30, 127, 225, 248], [0, 112, 7, 0, 96, 14, 0, 224, 14, 0, 224, 14, 224, 230, 14, 127, 193, 240], [1, 192, 30, 1, 224, 30, 0, 224, 14, 0, 224, 14, 240, 255, 15, 127, 225, 248], [0, 240, 15, 0, 240, 15, 0, 240, 15, 0, 240, 15, 240, 247, 15, 127, 225, 252], [0, 112, 15, 0, 240, 15, 0, 240, 15, 0, 240, 15, 224, 255, 15, 127, 243, 252], [0, 112, 7, 0, 112, 7, 0, 224, 14, 0, 230, 14, 224, 238, 30, 127, 225, 248], [0, 112, 7, 0, 112, 7, 0, 112, 15, 0, 230, 14, 224, 239, 30, 127, 225, 248], [0, 112, 7, 0, 112, 14, 0, 224, 14, 0, 230, 14, 224, 239, 30, 127, 193, 248]] }, { symbol: 'K', fingerprints: [[128, 204, 24, 199, 12, 96, 220, 15, 128, 252, 6, 240, 99, 134, 30, 96, 118, 0], [64, 204, 28, 195, 12, 112, 236, 7, 128, 124, 6, 240, 99, 134, 28, 96, 118, 0], [192, 204, 56, 195, 12, 224, 220, 15, 0, 248, 12, 224, 227, 142, 28, 96, 230, 2], [192, 204, 28, 195, 140, 96, 220, 15, 128, 248, 14, 224, 231, 134, 28, 96, 230, 2], [64, 110, 28, 227, 142, 112, 252, 15, 128, 120, 6, 224, 103, 6, 28, 96, 230, 7], [192, 108, 28, 195, 140, 240, 220, 15, 128, 248, 12, 224, 199, 12, 28, 192, 236, 7], [96, 38, 14, 97, 198, 112, 254, 15, 128, 248, 12, 224, 199, 140, 28, 192, 236, 7], [96, 38, 14, 97, 198, 120, 126, 7, 128, 124, 14, 240, 195, 140, 28, 192, 228, 2], [96, 6, 7, 97, 198, 120, 110, 7, 128, 124, 6, 240, 227, 140, 28, 192, 228, 7], [32, 6, 7, 97, 198, 56, 110, 7, 128, 124, 6, 224, 227, 14, 56, 192, 196, 6], [192, 204, 24, 199, 12, 224, 220, 15, 128, 252, 6, 240, 99, 198, 30, 96, 118, 0], [128, 204, 56, 199, 12, 224, 220, 15, 128, 248, 12, 224, 231, 142, 28, 224, 230, 2], [192, 204, 28, 199, 12, 112, 220, 15, 128, 252, 14, 224, 231, 142, 60, 224, 230, 2], [192, 204, 28, 195, 140, 224, 252, 15, 128, 252, 14, 224, 231, 142, 28, 224, 230, 7], [192, 110, 28, 227, 142, 112, 252, 15, 128, 252, 14, 224, 231, 142, 28, 96, 230, 7], [192, 108, 30, 195, 204, 112, 222, 15, 128, 248, 13, 224, 199, 12, 28, 192, 236, 7], [224, 110, 30, 227, 206, 240, 254, 15, 128, 252, 12, 224, 199, 140, 28, 192, 236, 7], [96, 102, 14, 225, 206, 112, 254, 15, 128, 252, 14, 224, 231, 140, 28, 192, 236, 7], [96, 54, 14, 97, 198, 120, 126, 15, 128, 252, 14, 240, 227, 142, 28, 192, 228, 3], [96, 38, 14, 99, 198, 120, 110, 7, 128, 124, 14, 224, 227, 142, 56, 192, 228, 6], [112, 7, 7, 97, 198, 120, 126, 7, 128, 124, 6, 224, 231, 14, 28, 192, 224, 6], [0, 204, 28, 195, 140, 224, 252, 15, 128, 252, 14, 224, 231, 134, 30, 96, 118, 0], [192, 204, 28, 227, 142, 112, 254, 15, 128, 252, 6, 240, 99, 134, 30, 96, 118, 3], [192, 236, 28, 227, 142, 240, 252, 15, 128, 252, 14, 224, 231, 142, 28, 224, 238, 7], [224, 238, 28, 227, 142, 112, 254, 15, 128, 252, 14, 240, 227, 142, 28, 224, 246, 2], [96, 110, 30, 227, 142, 112, 254, 15, 128, 252, 14, 240, 227, 142, 28, 224, 230, 7], [96, 102, 14, 99, 198, 120, 110, 7, 192, 124, 6, 240, 99, 134, 28, 224, 230, 7], [96, 126, 14, 227, 206, 120, 254, 15, 128, 254, 14, 240, 227, 142, 28, 224, 228, 3], [96, 54, 15, 99, 198, 120, 254, 15, 128, 254, 14, 240, 231, 142, 28, 224, 236, 7], [96, 38, 15, 99, 198, 120, 126, 7, 128, 252, 14, 224, 231, 142, 56, 225, 236, 6], [112, 39, 15, 113, 198, 120, 126, 7, 128, 124, 14, 224, 231, 142, 28, 224, 224, 6]] }, { symbol: 'L', fingerprints: [[192, 12, 0, 192, 14, 0, 96, 6, 0, 96, 6, 0, 96, 6, 0, 127, 247, 254], [192, 14, 0, 96, 6, 0, 96, 6, 0, 96, 6, 0, 96, 6, 0, 127, 247, 255], [192, 12, 0, 192, 12, 0, 224, 14, 0, 96, 6, 0, 96, 6, 0, 127, 247, 255], [64, 14, 0, 224, 6, 0, 96, 6, 0, 96, 6, 0, 96, 6, 0, 127, 231, 254], [192, 12, 0, 192, 12, 0, 192, 12, 0, 192, 12, 0, 192, 14, 0, 255, 239, 254], [224, 14, 0, 224, 14, 0, 224, 14, 0, 224, 14, 0, 224, 14, 0, 255, 239, 255], [96, 6, 0, 96, 6, 0, 96, 6, 0, 96, 6, 0, 96, 14, 0, 255, 239, 255], [96, 6, 0, 96, 6, 0, 96, 6, 0, 96, 6, 0, 96, 6, 0, 127, 15, 255], [48, 7, 0, 96, 6, 0, 96, 6, 0, 96, 6, 0, 96, 6, 0, 120, 15, 255], [48, 3, 0, 48, 7, 0, 96, 6, 0, 96, 6, 0, 96, 6, 0, 127, 195, 255], [192, 12, 0, 192, 12, 0, 192, 12, 0, 224, 14, 0, 224, 6, 6, 127, 247, 224], [192, 12, 0, 192, 12, 0, 192, 14, 0, 224, 14, 0, 96, 6, 0, 127, 247, 248], [192, 12, 0, 192, 14, 0, 224, 14, 0, 224, 6, 0, 96, 6, 0, 127, 231, 254], [192, 14, 0, 224, 14, 0, 224, 6, 0, 96, 6, 0, 96, 6, 0, 127, 231, 254], [192, 12, 0, 192, 12, 0, 192, 14, 0, 224, 14, 0, 224, 14, 0, 255, 239, 255], [96, 6, 0, 96, 6, 0, 96, 14, 0, 224, 14, 0, 224, 14, 0, 255, 239, 255], [112, 7, 0, 112, 6, 0, 96, 6, 0, 96, 6, 0, 96, 6, 0, 255, 227, 255], [48, 3, 0, 112, 7, 0, 112, 6, 0, 96, 6, 0, 96, 6, 0, 255, 231, 255], [192, 14, 0, 224, 14, 0, 224, 14, 0, 96, 6, 0, 96, 6, 14, 127, 247, 248], [192, 12, 0, 192, 12, 0, 224, 14, 0, 224, 14, 0, 224, 6, 0, 127, 247, 254], [192, 14, 0, 224, 14, 0, 224, 14, 0, 224, 14, 0, 224, 6, 0, 127, 247, 254], [224, 14, 0, 224, 14, 0, 224, 14, 0, 224, 6, 0, 96, 6, 0, 127, 247, 254], [96, 14, 0, 96, 6, 0, 96, 6, 0, 96, 6, 0, 96, 6, 0, 127, 231, 255], [112, 7, 0, 112, 7, 0, 96, 6, 0, 96, 6, 0, 96, 14, 0, 255, 231, 255], [48, 7, 0, 112, 7, 0, 112, 7, 0, 96, 6, 0, 96, 14, 0, 255, 239, 255]] }, { symbol: 'M', fingerprints: [[225, 239, 30, 243, 111, 182, 219, 108, 246, 206, 108, 103, 224, 62, 3, 96, 54, 0], [225, 239, 30, 249, 237, 182, 223, 108, 246, 206, 126, 99, 224, 54, 3, 96, 54, 2], [225, 239, 30, 243, 109, 182, 223, 108, 230, 206, 108, 102, 192, 108, 6, 192, 124, 2], [241, 239, 30, 241, 237, 182, 223, 108, 246, 206, 108, 102, 192, 108, 7, 192, 124, 2], [240, 239, 30, 249, 237, 190, 223, 108, 246, 206, 108, 103, 192, 124, 7, 192, 124, 3], [240, 255, 159, 217, 253, 191, 207, 124, 247, 206, 124, 103, 192, 124, 7, 192, 124, 3], [112, 247, 143, 121, 247, 219, 239, 62, 243, 231, 62, 99, 224, 60, 3, 192, 52, 3], [240, 239, 159, 249, 253, 191, 223, 108, 246, 206, 108, 102, 192, 108, 6, 192, 108, 6], [112, 247, 143, 249, 255, 155, 207, 60, 247, 206, 108, 102, 192, 108, 6, 192, 96, 6], [120, 103, 143, 121, 247, 219, 239, 190, 243, 207, 124, 103, 192, 108, 6, 192, 104, 6], [120, 7, 143, 124, 246, 219, 109, 182, 243, 231, 60, 103, 192, 108, 6, 192, 108, 6], [241, 239, 62, 251, 109, 182, 255, 110, 246, 102, 118, 103, 96, 54, 3, 96, 54, 0], [225, 239, 30, 251, 237, 190, 223, 108, 247, 239, 126, 103, 224, 62, 3, 96, 54, 3], [113, 239, 30, 249, 253, 191, 223, 126, 247, 239, 126, 99, 224, 54, 3, 96, 54, 3], [241, 239, 30, 251, 237, 182, 223, 108, 246, 206, 108, 230, 192, 124, 7, 192, 124, 3], [241, 239, 30, 249, 237, 191, 223, 124, 247, 207, 124, 103, 192, 124, 7, 224, 124, 7], [240, 255, 159, 249, 255, 159, 255, 126, 247, 239, 126, 103, 224, 126, 7, 224, 126, 7], [120, 255, 159, 249, 255, 219, 239, 190, 243, 239, 62, 103, 224, 126, 7, 224, 124, 3], [120, 255, 159, 249, 255, 223, 239, 252, 247, 206, 124, 103, 192, 108, 6, 192, 108, 6], [120, 119, 143, 121, 247, 219, 239, 190, 247, 239, 124, 103, 192, 124, 6, 192, 108, 6], [120, 103, 143, 124, 246, 219, 111, 190, 243, 239, 62, 103, 192, 124, 6, 192, 96, 6], [1, 239, 62, 251, 239, 182, 255, 110, 247, 239, 118, 103, 96, 118, 7, 96, 54, 2], [241, 239, 30, 251, 239, 190, 223, 126, 247, 239, 126, 103, 224, 126, 3, 224, 54, 3], [241, 239, 31, 249, 255, 191, 255, 254, 247, 239, 126, 103, 224, 62, 3, 224, 54, 3], [225, 239, 30, 251, 239, 190, 223, 109, 246, 206, 124, 231, 192, 126, 7, 224, 126, 7], [241, 239, 159, 251, 253, 191, 223, 124, 247, 239, 126, 103, 224, 126, 7, 224, 124, 2], [240, 239, 159, 249, 255, 191, 223, 124, 247, 207, 124, 231, 192, 108, 6, 192, 108, 6], [248, 255, 159, 249, 255, 223, 255, 254, 247, 207, 124, 103, 192, 124, 6, 192, 108, 6], [120, 247, 143, 253, 255, 219, 239, 254, 247, 239, 126, 103, 192, 124, 7, 192, 108, 6], [120, 231, 159, 125, 246, 255, 239, 126, 247, 238, 110, 102, 192, 108, 6, 192, 224, 6]] }, { symbol: 'N', fingerprints: [[192, 206, 14, 240, 111, 134, 220, 108, 230, 231, 102, 54, 97, 230, 31, 96, 246, 0], [96, 111, 6, 240, 111, 134, 252, 110, 230, 103, 102, 54, 97, 246, 31, 96, 246, 6], [224, 111, 6, 248, 103, 134, 108, 102, 102, 103, 102, 63, 97, 246, 15, 96, 246, 6], [224, 111, 6, 240, 109, 134, 220, 108, 231, 199, 126, 63, 225, 246, 15, 96, 246, 7], [96, 47, 7, 240, 127, 135, 238, 62, 227, 231, 54, 59, 97, 246, 15, 96, 246, 7], [224, 63, 3, 248, 61, 195, 204, 60, 227, 199, 60, 59, 195, 188, 31, 192, 252, 7], [224, 47, 7, 248, 125, 135, 204, 108, 230, 199, 108, 118, 193, 236, 30, 192, 236, 6], [112, 55, 3, 120, 55, 131, 238, 62, 231, 231, 124, 55, 193, 236, 30, 192, 236, 14], [112, 39, 7, 120, 103, 198, 108, 102, 102, 230, 110, 54, 195, 236, 30, 193, 228, 14], [112, 39, 131, 120, 55, 195, 108, 118, 102, 103, 110, 54, 227, 236, 30, 193, 228, 14], [112, 7, 7, 120, 103, 134, 236, 108, 198, 198, 108, 118, 195, 236, 62, 193, 200, 28], [192, 238, 14, 240, 239, 134, 220, 110, 230, 231, 110, 62, 97, 246, 31, 96, 246, 6], [224, 111, 6, 248, 111, 134, 252, 110, 230, 231, 102, 63, 97, 246, 31, 96, 246, 6], [96, 111, 6, 248, 111, 134, 252, 102, 230, 103, 118, 63, 97, 246, 31, 96, 246, 7], [224, 111, 6, 240, 111, 135, 220, 126, 231, 231, 126, 63, 225, 254, 15, 224, 246, 7], [224, 127, 7, 248, 127, 135, 238, 126, 231, 231, 126, 63, 225, 254, 15, 224, 246, 7], [224, 63, 3, 248, 63, 131, 220, 60, 227, 199, 60, 59, 193, 252, 31, 192, 252, 7], [224, 127, 7, 248, 127, 135, 238, 124, 231, 199, 124, 119, 193, 236, 30, 192, 236, 14], [112, 55, 3, 248, 63, 199, 238, 126, 231, 231, 126, 119, 225, 252, 31, 192, 236, 14], [112, 39, 135, 120, 119, 199, 108, 110, 230, 231, 110, 54, 227, 238, 30, 193, 228, 14], [112, 39, 131, 120, 119, 199, 108, 118, 103, 103, 110, 54, 227, 238, 30, 193, 228, 14], [112, 7, 7, 120, 119, 134, 236, 110, 230, 198, 108, 118, 195, 236, 62, 193, 236, 28], [0, 206, 14, 240, 239, 142, 252, 110, 230, 230, 110, 118, 227, 246, 31, 96, 246, 6], [224, 239, 14, 248, 111, 134, 252, 110, 230, 231, 126, 63, 97, 246, 31, 96, 246, 7], [112, 111, 7, 248, 119, 199, 110, 118, 103, 103, 118, 63, 97, 246, 15, 96, 246, 7], [112, 111, 7, 248, 127, 199, 236, 126, 231, 231, 126, 63, 227, 254, 31, 224, 246, 14], [112, 39, 135, 120, 119, 199, 108, 118, 231, 103, 118, 63, 227, 254, 31, 224, 246, 14], [112, 47, 7, 248, 111, 198, 236, 110, 230, 230, 110, 118, 227, 238, 30, 193, 236, 14], [112, 55, 135, 120, 119, 199, 236, 126, 230, 231, 110, 54, 227, 238, 30, 225, 236, 14], [112, 47, 7, 248, 111, 134, 252, 110, 230, 198, 236, 126, 195, 236, 62, 193, 236, 28], [112, 39, 135, 120, 127, 199, 236, 110, 230, 230, 108, 126, 195, 236, 62, 193, 224, 12]] }, { symbol: 'O', fingerprints: [[31, 3, 252, 112, 198, 6, 192, 124, 3, 192, 62, 3, 96, 119, 6, 56, 225, 248], [15, 3, 252, 96, 230, 6, 224, 124, 3, 224, 54, 3, 96, 119, 6, 63, 192, 248], [31, 131, 156, 112, 230, 6, 96, 110, 7, 96, 118, 7, 96, 99, 14, 63, 192, 248], [31, 131, 156, 112, 230, 6, 192, 124, 3, 192, 60, 7, 96, 103, 14, 57, 193, 248], [31, 131, 252, 112, 230, 6, 224, 60, 3, 192, 62, 3, 96, 119, 14, 57, 193, 248], [15, 3, 252, 112, 230, 6, 96, 110, 6, 224, 102, 6, 96, 103, 14, 63, 192, 240], [15, 131, 252, 48, 230, 7, 96, 60, 3, 192, 62, 3, 96, 103, 14, 57, 193, 248], [15, 1, 252, 48, 230, 6, 96, 102, 7, 224, 118, 6, 96, 103, 12, 63, 192, 240], [31, 131, 156, 112, 102, 6, 192, 60, 3, 192, 60, 6, 224, 102, 12, 123, 193, 240], [31, 3, 252, 112, 198, 14, 224, 110, 6, 224, 118, 6, 96, 103, 14, 63, 192, 240], [15, 3, 252, 112, 230, 14, 96, 110, 7, 224, 118, 7, 96, 103, 14, 63, 192, 248], [31, 131, 188, 112, 238, 6, 192, 124, 7, 192, 62, 7, 96, 103, 14, 57, 193, 248], [31, 131, 252, 112, 230, 6, 224, 126, 3, 224, 62, 3, 96, 119, 14, 57, 225, 248], [15, 3, 252, 112, 231, 6, 96, 118, 7, 224, 118, 7, 96, 103, 14, 63, 192, 240], [31, 131, 220, 112, 230, 7, 224, 124, 3, 192, 62, 7, 224, 103, 14, 59, 193, 248], [15, 131, 252, 112, 230, 6, 224, 110, 7, 224, 126, 6, 96, 103, 12, 59, 193, 240], [15, 131, 252, 112, 231, 6, 96, 126, 7, 224, 126, 6, 96, 231, 14, 63, 193, 240], [15, 131, 222, 48, 231, 7, 96, 118, 7, 224, 118, 7, 96, 103, 12, 63, 193, 240], [31, 7, 252, 96, 206, 14, 224, 108, 6, 224, 126, 6, 96, 231, 14, 63, 192, 240], [31, 3, 252, 112, 230, 14, 224, 110, 7, 224, 126, 7, 112, 103, 14, 63, 192, 248], [31, 131, 252, 112, 230, 6, 96, 126, 7, 224, 118, 7, 112, 115, 142, 63, 192, 248], [31, 3, 252, 112, 230, 14, 224, 110, 7, 224, 126, 6, 96, 231, 14, 63, 192, 240], [15, 3, 252, 112, 230, 6, 224, 126, 7, 224, 126, 7, 96, 103, 14, 63, 192, 240], [15, 131, 252, 112, 231, 6, 96, 126, 7, 224, 118, 7, 96, 103, 14, 63, 193, 248], [31, 131, 252, 112, 230, 14, 224, 110, 6, 224, 110, 6, 224, 231, 28, 127, 193, 240], [15, 129, 252, 56, 231, 7, 96, 126, 7, 224, 126, 7, 96, 103, 14, 63, 193, 240]] }, { symbol: 'P', fingerprints: [[255, 207, 14, 192, 110, 7, 96, 103, 252, 127, 134, 0, 96, 6, 0, 96, 6, 0], [255, 207, 158, 96, 118, 3, 96, 119, 254, 127, 134, 0, 96, 6, 0, 96, 6, 0], [255, 207, 254, 192, 124, 3, 224, 119, 254, 127, 198, 0, 96, 6, 0, 96, 6, 0], [255, 206, 14, 96, 118, 3, 96, 103, 254, 127, 134, 0, 96, 6, 0, 96, 6, 0], [255, 204, 30, 192, 124, 3, 192, 127, 254, 255, 140, 0, 224, 14, 0, 224, 14, 0], [255, 142, 30, 224, 110, 7, 224, 110, 30, 255, 142, 0, 224, 14, 0, 224, 6, 0], [127, 135, 254, 96, 118, 3, 96, 118, 14, 127, 198, 0, 96, 6, 0, 224, 6, 0], [255, 143, 254, 224, 124, 3, 192, 63, 254, 255, 204, 0, 192, 12, 0, 192, 12, 0], [127, 7, 254, 96, 102, 3, 224, 127, 254, 255, 204, 0, 192, 12, 0, 192, 12, 0], [127, 134, 62, 96, 118, 3, 96, 119, 142, 255, 204, 0, 192, 12, 0, 192, 12, 0], [127, 134, 126, 96, 102, 7, 96, 102, 14, 127, 206, 0, 192, 12, 0, 192, 12, 0], [255, 199, 222, 96, 118, 7, 96, 103, 254, 127, 135, 0, 112, 3, 0, 48, 3, 0], [255, 207, 254, 224, 118, 3, 96, 119, 254, 127, 198, 0, 96, 6, 0, 112, 7, 0], [255, 143, 254, 224, 110, 7, 224, 111, 254, 255, 198, 0, 96, 6, 0, 96, 6, 0], [255, 206, 14, 224, 126, 7, 96, 119, 254, 127, 134, 0, 96, 6, 0, 96, 6, 0], [255, 206, 30, 192, 124, 3, 224, 127, 254, 255, 206, 0, 224, 14, 0, 224, 14, 0], [255, 207, 254, 224, 110, 7, 224, 111, 254, 255, 206, 0, 224, 14, 0, 224, 14, 0], [127, 135, 254, 96, 118, 3, 96, 119, 254, 255, 206, 0, 224, 14, 0, 224, 6, 0], [127, 135, 254, 96, 230, 7, 96, 103, 254, 127, 198, 0, 96, 14, 0, 224, 6, 0], [127, 7, 254, 112, 246, 3, 96, 119, 254, 127, 230, 0, 96, 6, 0, 224, 6, 0], [127, 135, 254, 96, 102, 7, 96, 103, 14, 255, 206, 0, 224, 12, 0, 192, 12, 0], [255, 199, 254, 96, 102, 7, 96, 119, 254, 127, 198, 0, 112, 7, 0, 112, 7, 0], [255, 199, 254, 96, 102, 7, 96, 231, 252, 127, 134, 0, 96, 6, 0, 96, 6, 0], [127, 135, 254, 96, 230, 7, 96, 119, 254, 127, 206, 0, 224, 14, 0, 224, 14, 0], [127, 7, 252, 96, 230, 7, 224, 111, 254, 255, 206, 0, 224, 12, 0, 192, 12, 0], [127, 7, 254, 97, 230, 7, 96, 127, 222, 255, 238, 112, 224, 14, 0, 192, 12, 0]] }, { symbol: 'Q', fingerprints: [[30, 7, 248, 97, 204, 12, 192, 204, 14, 198, 110, 126, 99, 199, 28, 63, 240, 227], [63, 7, 56, 225, 140, 12, 192, 204, 12, 206, 204, 124, 227, 199, 60, 63, 96, 6], [63, 7, 56, 225, 204, 12, 192, 204, 12, 206, 204, 124, 227, 199, 28, 63, 224, 199], [31, 7, 56, 97, 204, 12, 192, 236, 14, 198, 236, 124, 99, 195, 188, 63, 224, 2], [31, 3, 184, 97, 206, 12, 192, 108, 6, 198, 110, 126, 99, 195, 188, 63, 224, 7], [31, 3, 248, 113, 198, 14, 224, 108, 6, 198, 102, 118, 99, 195, 28, 63, 224, 7], [31, 131, 156, 112, 198, 6, 96, 110, 6, 102, 102, 118, 113, 195, 252, 31, 224, 3], [31, 131, 156, 96, 238, 6, 192, 108, 6, 198, 108, 118, 97, 231, 188, 63, 224, 7], [31, 131, 252, 96, 102, 6, 224, 108, 6, 198, 110, 126, 97, 199, 156, 31, 224, 3], [15, 131, 252, 112, 102, 6, 96, 126, 7, 230, 102, 118, 97, 231, 28, 31, 224, 3], [31, 131, 142, 48, 102, 7, 96, 54, 3, 230, 118, 118, 97, 227, 252, 31, 224, 7], [30, 7, 248, 97, 206, 12, 192, 236, 14, 198, 238, 126, 99, 231, 28, 63, 240, 247], [62, 7, 248, 225, 140, 28, 192, 204, 12, 204, 204, 252, 227, 199, 60, 63, 224, 199], [63, 7, 248, 97, 206, 12, 192, 236, 14, 206, 238, 126, 99, 199, 252, 63, 224, 3], [31, 7, 248, 113, 206, 14, 192, 236, 6, 198, 110, 126, 99, 199, 188, 63, 224, 7], [31, 3, 252, 112, 198, 14, 224, 110, 6, 230, 102, 126, 113, 199, 156, 31, 224, 3], [15, 3, 252, 112, 198, 14, 96, 110, 6, 230, 102, 126, 115, 199, 156, 31, 224, 7], [31, 135, 156, 112, 238, 6, 192, 108, 6, 206, 110, 118, 99, 231, 252, 63, 224, 7], [31, 131, 252, 96, 230, 6, 224, 108, 6, 231, 110, 126, 97, 231, 188, 31, 224, 3], [15, 131, 252, 112, 102, 6, 224, 126, 7, 231, 110, 126, 97, 231, 156, 31, 224, 7], [31, 131, 158, 112, 102, 7, 96, 126, 7, 231, 118, 62, 113, 227, 252, 31, 224, 3], [63, 7, 248, 97, 206, 12, 192, 236, 14, 198, 238, 126, 99, 199, 190, 63, 240, 67], [31, 7, 248, 113, 206, 14, 224, 238, 14, 230, 238, 126, 99, 231, 190, 63, 240, 227], [30, 7, 248, 225, 206, 12, 192, 236, 14, 206, 238, 126, 227, 199, 60, 63, 224, 2], [31, 7, 252, 113, 206, 14, 224, 236, 14, 230, 238, 126, 99, 199, 252, 63, 224, 71], [31, 3, 252, 112, 206, 14, 224, 238, 6, 230, 110, 126, 115, 199, 188, 31, 224, 3], [31, 3, 252, 112, 230, 14, 224, 110, 6, 230, 110, 126, 115, 231, 156, 31, 224, 7], [31, 131, 252, 112, 230, 6, 96, 110, 6, 231, 102, 62, 113, 227, 254, 31, 240, 3], [31, 131, 252, 112, 230, 6, 224, 126, 7, 239, 110, 126, 113, 231, 252, 31, 224, 7], [31, 131, 252, 112, 230, 6, 224, 126, 7, 231, 126, 126, 113, 231, 156, 63, 224, 7], [15, 131, 254, 112, 102, 7, 224, 126, 7, 231, 126, 126, 113, 227, 254, 31, 224, 3]] }, { symbol: 'R', fingerprints: [[255, 143, 28, 96, 230, 6, 96, 231, 252, 127, 134, 24, 96, 199, 6, 48, 115, 0], [255, 143, 254, 192, 110, 6, 96, 103, 252, 127, 134, 56, 97, 198, 6, 96, 118, 2], [255, 143, 254, 96, 102, 6, 96, 103, 252, 127, 134, 56, 97, 198, 6, 96, 118, 3], [255, 204, 30, 192, 108, 7, 224, 239, 254, 255, 6, 56, 97, 198, 14, 96, 118, 3], [255, 206, 30, 96, 118, 3, 96, 119, 254, 127, 134, 56, 97, 198, 14, 96, 118, 3], [255, 142, 62, 192, 236, 6, 192, 238, 62, 255, 140, 112, 193, 140, 28, 192, 236, 7], [255, 143, 254, 224, 238, 3, 224, 111, 254, 255, 204, 112, 193, 204, 14, 192, 236, 2], [127, 7, 254, 96, 246, 3, 96, 119, 254, 255, 206, 48, 225, 204, 14, 192, 236, 7], [127, 134, 30, 96, 102, 7, 96, 103, 252, 127, 134, 56, 225, 140, 28, 192, 228, 6], [127, 134, 62, 96, 118, 3, 96, 119, 254, 127, 198, 56, 225, 142, 28, 192, 228, 6], [63, 135, 126, 96, 118, 3, 96, 119, 254, 127, 198, 56, 97, 142, 28, 192, 228, 6], [255, 143, 252, 224, 198, 14, 96, 199, 248, 127, 6, 56, 113, 199, 14, 112, 99, 2], [255, 143, 252, 224, 238, 14, 224, 231, 252, 127, 134, 120, 97, 198, 14, 96, 102, 2], [255, 142, 30, 224, 110, 6, 224, 239, 252, 255, 142, 56, 227, 198, 30, 96, 102, 6], [255, 142, 62, 224, 110, 6, 224, 239, 254, 255, 134, 56, 99, 198, 30, 96, 102, 7], [255, 143, 254, 192, 236, 7, 192, 239, 254, 255, 140, 120, 193, 204, 14, 192, 236, 2], [255, 143, 254, 224, 254, 7, 224, 127, 254, 255, 206, 120, 225, 206, 14, 192, 236, 7], [127, 135, 254, 96, 246, 3, 224, 127, 254, 255, 206, 120, 225, 206, 14, 224, 236, 7], [127, 135, 254, 96, 102, 7, 96, 119, 254, 255, 142, 56, 227, 206, 28, 224, 228, 6], [127, 135, 254, 96, 118, 3, 96, 119, 254, 127, 134, 56, 225, 206, 28, 224, 224, 6], [255, 135, 252, 96, 230, 14, 96, 231, 252, 127, 135, 56, 113, 199, 14, 112, 99, 2], [255, 135, 252, 96, 230, 6, 96, 231, 252, 127, 198, 120, 97, 198, 14, 96, 230, 7], [255, 207, 254, 224, 110, 6, 224, 239, 252, 255, 142, 56, 225, 206, 14, 224, 102, 2], [255, 207, 254, 224, 238, 7, 224, 239, 254, 255, 206, 120, 225, 206, 30, 224, 236, 7], [127, 135, 254, 224, 110, 7, 224, 111, 254, 255, 142, 56, 227, 206, 28, 224, 228, 6], [127, 7, 252, 112, 231, 7, 96, 103, 254, 127, 206, 112, 227, 142, 28, 224, 192, 6]] }, { symbol: 'S', fingerprints: [[63, 135, 158, 224, 236, 0, 240, 3, 240, 7, 192, 15, 0, 55, 3, 112, 227, 252], [31, 135, 254, 224, 110, 0, 112, 3, 240, 3, 224, 7, 64, 55, 3, 127, 225, 248], [63, 135, 30, 192, 236, 0, 120, 3, 240, 7, 192, 14, 64, 126, 6, 121, 227, 248], [63, 135, 30, 224, 236, 0, 120, 3, 240, 7, 192, 14, 64, 54, 6, 113, 227, 252], [31, 135, 190, 224, 110, 0, 240, 3, 240, 15, 192, 14, 0, 126, 7, 240, 227, 248], [31, 135, 254, 224, 126, 0, 112, 3, 240, 3, 224, 7, 192, 126, 7, 127, 225, 248], [31, 199, 15, 224, 126, 0, 120, 1, 248, 3, 224, 15, 192, 126, 7, 127, 225, 248], [31, 199, 143, 112, 118, 0, 120, 1, 248, 7, 192, 15, 96, 126, 7, 112, 225, 248], [31, 199, 222, 112, 119, 0, 120, 1, 240, 7, 192, 14, 64, 126, 6, 112, 227, 252], [15, 195, 254, 112, 119, 2, 120, 1, 240, 7, 192, 14, 64, 126, 6, 112, 227, 252], [31, 195, 142, 112, 118, 0, 60, 1, 240, 3, 192, 14, 64, 102, 6, 123, 227, 248], [63, 135, 254, 192, 236, 0, 240, 3, 240, 3, 224, 7, 96, 55, 7, 127, 225, 248], [31, 135, 252, 224, 110, 0, 112, 3, 240, 7, 192, 6, 96, 118, 6, 127, 225, 248], [63, 199, 158, 224, 238, 0, 120, 3, 240, 7, 192, 14, 64, 126, 7, 121, 227, 252], [63, 199, 254, 112, 238, 0, 120, 3, 240, 7, 192, 14, 64, 126, 7, 121, 227, 252], [31, 199, 143, 224, 126, 0, 124, 1, 248, 7, 224, 15, 224, 126, 7, 127, 227, 248], [63, 199, 158, 112, 118, 0, 120, 1, 240, 7, 192, 14, 192, 126, 14, 121, 227, 252], [31, 131, 254, 96, 118, 2, 120, 1, 224, 7, 192, 14, 192, 110, 6, 127, 227, 248], [31, 195, 158, 112, 119, 0, 60, 1, 248, 7, 192, 14, 192, 110, 6, 127, 227, 248], [31, 135, 252, 224, 206, 0, 112, 3, 248, 7, 224, 6, 96, 119, 6, 63, 225, 248], [63, 135, 254, 224, 238, 0, 240, 3, 240, 7, 224, 6, 96, 118, 7, 127, 225, 248], [31, 135, 254, 224, 110, 0, 112, 3, 240, 7, 224, 15, 96, 118, 7, 127, 227, 252], [63, 199, 254, 224, 238, 0, 120, 3, 248, 15, 224, 15, 64, 127, 15, 127, 227, 252], [63, 199, 254, 224, 110, 0, 120, 3, 240, 7, 224, 15, 224, 127, 7, 127, 225, 248], [31, 135, 254, 96, 102, 0, 120, 3, 240, 7, 192, 14, 96, 126, 6, 127, 227, 248], [63, 199, 254, 112, 127, 0, 120, 3, 240, 7, 192, 14, 192, 126, 14, 255, 227, 252], [31, 199, 255, 112, 119, 2, 120, 3, 240, 7, 224, 15, 192, 126, 15, 127, 227, 248], [31, 135, 254, 96, 118, 2, 120, 3, 240, 7, 192, 14, 224, 110, 6, 127, 227, 248], [31, 131, 254, 112, 119, 3, 120, 1, 240, 7, 192, 30, 224, 110, 6, 127, 227, 248]] }, { symbol: 'T', fingerprints: [[31, 255, 254, 6, 0, 96, 7, 0, 112, 7, 0, 112, 7, 0, 48, 3, 0, 48], [127, 247, 224, 6, 0, 96, 6, 0, 96, 7, 0, 112, 3, 0, 48, 3, 0, 48], [255, 255, 240, 6, 0, 96, 6, 0, 112, 7, 0, 112, 7, 0, 112, 7, 0, 48], [127, 231, 254, 6, 0, 96, 6, 0, 96, 6, 0, 96, 6, 0, 96, 6, 0, 96], [255, 240, 96, 6, 0, 96, 6, 0, 96, 6, 0, 96, 6, 0, 96, 6, 0, 96], [255, 247, 254, 6, 0, 96, 6, 0, 96, 6, 0, 224, 14, 0, 224, 14, 0, 96], [255, 231, 254, 6, 0, 96, 6, 0, 96, 6, 0, 96, 6, 0, 224, 14, 0, 64], [255, 240, 102, 6, 0, 224, 14, 0, 224, 14, 0, 224, 14, 0, 224, 14, 0, 224], [255, 224, 126, 6, 0, 96, 6, 0, 224, 14, 0, 192, 12, 0, 192, 12, 0, 192], [255, 224, 255, 14, 0, 224, 14, 0, 224, 14, 0, 224, 12, 0, 192, 12, 0, 128], [63, 255, 254, 6, 0, 112, 7, 0, 48, 3, 0, 48, 3, 0, 48, 3, 0, 48], [63, 239, 254, 6, 0, 96, 6, 0, 112, 7, 0, 112, 7, 0, 48, 3, 0, 48], [127, 247, 252, 6, 0, 112, 7, 0, 112, 7, 0, 112, 3, 0, 48, 3, 0, 48], [127, 255, 254, 6, 0, 96, 6, 0, 96, 6, 0, 96, 6, 0, 112, 7, 0, 96], [127, 240, 112, 6, 0, 96, 6, 0, 96, 7, 0, 112, 7, 0, 112, 7, 0, 112], [255, 231, 255, 6, 0, 96, 6, 0, 96, 6, 0, 96, 14, 0, 224, 14, 0, 224], [255, 239, 255, 14, 0, 224, 14, 0, 224, 14, 0, 224, 14, 0, 224, 14, 0, 224], [255, 135, 255, 6, 0, 96, 14, 0, 224, 14, 0, 224, 12, 0, 192, 12, 0, 192], [255, 225, 255, 14, 0, 224, 14, 0, 224, 14, 0, 224, 12, 0, 192, 28, 1, 192], [127, 255, 254, 7, 0, 112, 7, 0, 112, 7, 0, 48, 3, 0, 48, 3, 128, 56], [127, 255, 254, 6, 0, 96, 6, 0, 112, 7, 0, 112, 7, 0, 112, 3, 0, 48], [255, 239, 254, 6, 0, 96, 6, 0, 96, 6, 0, 96, 6, 0, 112, 7, 0, 112], [255, 255, 254, 6, 0, 96, 6, 0, 96, 6, 0, 112, 7, 0, 112, 7, 0, 112], [255, 239, 254, 14, 0, 224, 6, 0, 96, 6, 0, 96, 6, 0, 96, 6, 0, 96], [255, 247, 255, 6, 0, 96, 6, 0, 224, 14, 0, 224, 14, 0, 224, 14, 0, 224], [255, 239, 254, 14, 0, 224, 14, 0, 224, 14, 0, 224, 12, 0, 192, 12, 0, 192], [255, 199, 255, 6, 0, 224, 14, 0, 224, 14, 0, 224, 14, 0, 192, 12, 0, 192], [255, 15, 255, 14, 0, 224, 14, 0, 192, 12, 0, 192, 12, 1, 192, 28, 1, 192]] }, { symbol: 'U', fingerprints: [[64, 110, 6, 224, 102, 6, 96, 102, 6, 96, 118, 3, 96, 55, 7, 56, 225, 252], [64, 108, 6, 192, 108, 6, 224, 118, 3, 96, 54, 3, 96, 54, 7, 63, 225, 248], [64, 110, 7, 224, 118, 3, 96, 54, 3, 96, 54, 3, 96, 55, 7, 57, 225, 252], [192, 108, 6, 192, 108, 6, 192, 108, 6, 224, 110, 7, 96, 118, 6, 113, 225, 248], [64, 110, 7, 224, 126, 7, 224, 118, 7, 96, 118, 3, 96, 54, 6, 112, 227, 252], [192, 60, 3, 192, 60, 3, 192, 60, 3, 192, 60, 3, 192, 54, 6, 127, 225, 248], [224, 62, 3, 224, 60, 3, 192, 60, 3, 192, 60, 3, 192, 54, 7, 125, 225, 252], [96, 54, 3, 96, 54, 3, 96, 126, 7, 224, 126, 6, 192, 102, 6, 113, 227, 248], [96, 54, 3, 96, 54, 3, 96, 54, 3, 96, 62, 7, 224, 102, 6, 112, 227, 252], [96, 38, 3, 96, 62, 7, 192, 108, 6, 192, 108, 6, 192, 108, 6, 127, 193, 248], [96, 6, 3, 96, 54, 3, 96, 62, 7, 192, 108, 6, 192, 108, 6, 121, 195, 248], [64, 110, 6, 224, 102, 6, 96, 102, 7, 96, 118, 3, 112, 55, 7, 63, 224, 248], [64, 108, 6, 192, 110, 7, 224, 126, 7, 96, 54, 3, 96, 54, 7, 63, 225, 248], [64, 110, 6, 224, 110, 6, 96, 102, 6, 96, 102, 7, 96, 118, 6, 63, 225, 248], [192, 108, 6, 192, 108, 6, 224, 110, 7, 224, 126, 7, 224, 118, 6, 121, 227, 252], [192, 110, 7, 224, 126, 7, 224, 126, 7, 224, 126, 7, 96, 118, 7, 112, 227, 252], [224, 126, 7, 224, 126, 7, 224, 126, 6, 224, 110, 6, 224, 110, 6, 127, 227, 248], [96, 54, 3, 96, 126, 7, 224, 126, 7, 224, 126, 7, 224, 110, 6, 121, 227, 248], [96, 38, 7, 96, 118, 6, 96, 102, 6, 224, 110, 6, 224, 102, 14, 113, 195, 248], [96, 38, 3, 96, 118, 7, 96, 118, 6, 96, 110, 6, 224, 102, 14, 127, 193, 248], [96, 6, 7, 96, 102, 6, 224, 110, 6, 224, 108, 6, 192, 238, 14, 127, 195, 248], [0, 110, 6, 224, 110, 6, 96, 118, 7, 96, 118, 7, 112, 119, 7, 63, 224, 248], [192, 236, 14, 224, 110, 6, 224, 110, 6, 224, 102, 7, 96, 118, 6, 127, 225, 248], [64, 110, 6, 224, 110, 6, 224, 110, 6, 96, 118, 7, 96, 119, 7, 127, 225, 248], [96, 110, 6, 96, 102, 7, 96, 118, 7, 96, 118, 7, 96, 119, 7, 127, 225, 252], [224, 126, 7, 224, 126, 7, 224, 126, 7, 224, 126, 7, 224, 118, 7, 127, 225, 248], [96, 62, 7, 224, 126, 7, 224, 126, 7, 224, 126, 7, 96, 118, 7, 127, 225, 252], [224, 46, 7, 224, 126, 7, 224, 126, 7, 224, 126, 7, 224, 110, 6, 127, 227, 248], [96, 62, 7, 224, 126, 7, 224, 126, 7, 224, 126, 7, 224, 126, 6, 127, 227, 252], [96, 102, 7, 96, 118, 7, 224, 110, 6, 224, 110, 6, 224, 110, 14, 127, 193, 248], [96, 54, 7, 96, 118, 7, 96, 118, 7, 224, 110, 6, 224, 110, 14, 127, 193, 248], [96, 38, 7, 96, 126, 6, 224, 110, 6, 224, 108, 14, 192, 238, 14, 127, 195, 248]] }, { symbol: 'V', fingerprints: [[64, 60, 6, 96, 102, 6, 48, 99, 14, 24, 193, 140, 12, 192, 252, 7, 128, 120], [64, 62, 3, 96, 118, 6, 48, 99, 134, 24, 225, 140, 12, 192, 236, 7, 128, 120], [192, 62, 6, 96, 102, 6, 48, 99, 12, 56, 193, 140, 29, 128, 248, 15, 128, 120], [192, 54, 6, 96, 103, 6, 48, 195, 12, 24, 193, 152, 29, 128, 216, 15, 128, 112], [192, 60, 7, 96, 102, 6, 112, 227, 12, 48, 193, 156, 25, 129, 216, 15, 128, 240], [192, 54, 6, 96, 103, 14, 48, 195, 12, 57, 193, 152, 25, 129, 240, 15, 0, 240], [192, 62, 7, 96, 102, 6, 112, 195, 12, 48, 195, 152, 25, 129, 176, 31, 0, 240], [192, 38, 6, 96, 102, 14, 48, 195, 28, 49, 131, 152, 27, 1, 176, 31, 0, 224], [192, 62, 7, 96, 102, 6, 96, 195, 12, 49, 195, 24, 59, 129, 240, 31, 1, 224], [192, 38, 6, 96, 102, 14, 112, 195, 28, 49, 131, 24, 59, 1, 240, 30, 1, 224], [192, 12, 3, 96, 102, 6, 96, 198, 12, 49, 131, 56, 55, 3, 112, 30, 1, 224], [64, 54, 7, 96, 103, 6, 48, 97, 142, 24, 193, 204, 12, 192, 124, 7, 128, 120], [64, 126, 6, 96, 103, 6, 48, 227, 140, 24, 193, 220, 13, 128, 248, 7, 128, 120], [64, 54, 7, 96, 103, 6, 48, 99, 142, 24, 193, 204, 13, 192, 248, 7, 128, 120], [192, 126, 6, 96, 103, 14, 48, 195, 140, 56, 193, 156, 29, 128, 216, 15, 128, 112], [192, 62, 7, 224, 102, 6, 112, 227, 12, 48, 195, 156, 25, 129, 216, 15, 128, 240], [192, 62, 6, 96, 102, 14, 48, 195, 12, 57, 193, 152, 25, 129, 248, 15, 0, 240], [192, 62, 7, 96, 102, 6, 112, 227, 12, 49, 195, 152, 25, 129, 248, 31, 0, 240], [224, 54, 6, 96, 102, 14, 112, 195, 28, 49, 131, 152, 27, 129, 176, 31, 0, 224], [192, 46, 7, 96, 102, 14, 112, 195, 28, 49, 131, 56, 59, 1, 240, 30, 1, 224], [192, 14, 7, 224, 102, 6, 96, 199, 28, 113, 131, 56, 55, 3, 112, 62, 1, 224], [0, 62, 7, 96, 119, 6, 56, 227, 142, 24, 225, 204, 14, 192, 252, 7, 128, 56], [64, 126, 6, 96, 103, 14, 48, 227, 140, 24, 193, 220, 13, 192, 248, 15, 128, 120], [64, 62, 7, 112, 103, 6, 48, 227, 142, 24, 193, 220, 13, 192, 248, 7, 128, 120], [64, 62, 7, 96, 103, 14, 112, 227, 12, 57, 193, 156, 29, 128, 216, 15, 128, 112], [192, 110, 6, 224, 230, 14, 112, 195, 28, 57, 195, 152, 27, 129, 248, 15, 0, 240], [192, 62, 7, 96, 103, 14, 112, 227, 12, 57, 193, 152, 31, 129, 248, 15, 0, 240], [192, 110, 6, 224, 230, 14, 112, 199, 28, 49, 131, 184, 27, 129, 176, 31, 0, 224], [192, 46, 7, 96, 102, 14, 112, 195, 28, 49, 195, 152, 27, 129, 176, 31, 0, 224], [192, 110, 6, 224, 230, 14, 113, 199, 28, 49, 131, 56, 59, 3, 240, 30, 1, 224], [224, 46, 7, 96, 102, 14, 112, 199, 28, 49, 131, 184, 59, 1, 240, 30, 1, 224], [192, 46, 7, 224, 230, 14, 97, 199, 28, 115, 131, 48, 55, 3, 240, 62, 1, 192]] }, { symbol: 'W', fingerprints: [[64, 60, 3, 192, 62, 3, 96, 54, 115, 103, 183, 251, 63, 243, 207, 60, 241, 128], [64, 108, 7, 224, 118, 7, 96, 54, 115, 103, 119, 255, 61, 227, 222, 60, 225, 134], [192, 60, 3, 192, 60, 3, 224, 54, 115, 111, 54, 251, 125, 243, 206, 56, 227, 134], [192, 44, 7, 224, 118, 7, 96, 118, 118, 103, 102, 246, 125, 227, 222, 57, 227, 140], [192, 60, 3, 192, 60, 3, 192, 62, 243, 111, 118, 246, 125, 231, 158, 121, 227, 14], [192, 60, 7, 224, 126, 6, 230, 102, 102, 111, 102, 246, 127, 231, 158, 57, 195, 156], [192, 60, 3, 192, 60, 3, 192, 124, 230, 239, 103, 246, 123, 231, 158, 113, 199, 12], [192, 44, 7, 192, 108, 6, 192, 110, 230, 238, 102, 246, 123, 199, 188, 113, 199, 28], [96, 54, 3, 96, 54, 7, 224, 102, 102, 110, 102, 246, 123, 231, 188, 121, 199, 28], [192, 44, 7, 192, 108, 6, 192, 108, 230, 206, 109, 236, 251, 199, 60, 115, 198, 24], [96, 6, 3, 224, 126, 7, 192, 108, 230, 238, 111, 254, 123, 199, 188, 115, 198, 24], [192, 108, 6, 192, 110, 7, 224, 118, 119, 111, 119, 255, 61, 227, 222, 60, 225, 132], [64, 126, 7, 224, 126, 7, 96, 118, 119, 103, 119, 255, 61, 243, 222, 60, 225, 134], [64, 62, 3, 96, 54, 3, 96, 54, 115, 119, 55, 255, 61, 243, 223, 60, 225, 142], [192, 126, 7, 224, 126, 7, 96, 118, 119, 111, 102, 246, 125, 227, 222, 57, 227, 142], [96, 62, 3, 96, 54, 3, 96, 118, 119, 103, 119, 255, 125, 227, 222, 57, 227, 142], [192, 46, 7, 224, 126, 7, 224, 110, 102, 111, 102, 246, 127, 231, 158, 121, 227, 156], [96, 62, 3, 96, 118, 7, 102, 118, 119, 111, 102, 246, 127, 231, 158, 121, 227, 28], [224, 62, 7, 224, 126, 6, 224, 110, 230, 238, 103, 254, 123, 231, 188, 123, 199, 28], [96, 62, 3, 224, 126, 7, 224, 126, 230, 111, 103, 246, 123, 231, 188, 113, 195, 28], [192, 46, 7, 224, 124, 6, 192, 108, 230, 238, 239, 254, 251, 207, 188, 115, 198, 56], [96, 14, 3, 224, 126, 7, 224, 110, 230, 238, 111, 254, 251, 199, 188, 115, 198, 56], [0, 108, 7, 224, 126, 7, 224, 118, 119, 111, 119, 255, 127, 243, 222, 60, 225, 134], [192, 108, 7, 224, 126, 7, 224, 126, 103, 111, 102, 246, 127, 231, 222, 57, 227, 142], [64, 110, 7, 224, 126, 7, 224, 118, 119, 111, 119, 254, 127, 231, 222, 61, 227, 142], [192, 108, 7, 224, 110, 6, 224, 110, 230, 239, 103, 246, 127, 231, 190, 121, 195, 12], [192, 126, 7, 224, 126, 7, 224, 126, 230, 111, 102, 246, 127, 231, 190, 121, 227, 28], [192, 108, 7, 192, 108, 6, 192, 110, 230, 238, 239, 254, 123, 231, 188, 123, 199, 28], [192, 46, 7, 224, 126, 7, 224, 110, 230, 239, 111, 254, 123, 231, 190, 123, 199, 28], [192, 108, 7, 192, 108, 6, 192, 108, 238, 222, 239, 252, 255, 207, 188, 243, 198, 56], [224, 46, 7, 224, 126, 6, 224, 110, 230, 254, 239, 254, 255, 207, 188, 115, 198, 56], [192, 44, 7, 192, 108, 6, 192, 236, 238, 222, 237, 236, 255, 207, 124, 247, 142, 56]] }, { symbol: 'X', fingerprints: [[64, 206, 28, 113, 131, 184, 31, 0, 224, 15, 1, 248, 25, 195, 142, 48, 102, 0], [64, 198, 12, 49, 131, 152, 31, 0, 224, 15, 1, 248, 25, 195, 140, 48, 102, 2], [192, 102, 12, 113, 195, 152, 31, 0, 224, 15, 1, 184, 57, 195, 14, 112, 102, 2], [64, 102, 12, 112, 195, 152, 31, 0, 240, 15, 1, 248, 25, 195, 14, 112, 102, 2], [192, 102, 14, 113, 195, 152, 31, 128, 224, 15, 1, 248, 57, 199, 14, 96, 108, 3], [224, 102, 14, 57, 195, 152, 31, 128, 240, 15, 1, 248, 57, 199, 14, 96, 108, 7], [96, 55, 6, 56, 225, 156, 31, 128, 112, 15, 1, 248, 57, 199, 14, 96, 100, 3], [96, 39, 6, 48, 225, 156, 15, 128, 240, 15, 1, 248, 57, 135, 12, 96, 236, 6], [96, 51, 6, 56, 225, 156, 15, 128, 240, 15, 1, 152, 49, 199, 12, 96, 100, 6], [48, 35, 6, 24, 193, 156, 15, 128, 240, 15, 1, 240, 57, 135, 28, 96, 196, 6], [48, 3, 7, 24, 225, 204, 15, 128, 112, 15, 1, 240, 57, 131, 28, 96, 196, 6], [192, 206, 28, 113, 131, 184, 31, 0, 224, 15, 1, 248, 25, 195, 142, 48, 118, 2], [64, 206, 12, 113, 131, 184, 31, 0, 240, 15, 1, 248, 25, 195, 142, 48, 102, 2], [64, 110, 12, 113, 195, 24, 31, 128, 240, 15, 1, 248, 57, 195, 12, 112, 102, 2], [192, 102, 14, 113, 195, 152, 31, 128, 240, 15, 1, 248, 57, 195, 14, 112, 102, 3], [192, 110, 14, 113, 195, 188, 31, 128, 224, 15, 1, 248, 57, 199, 14, 96, 108, 7], [64, 38, 6, 57, 195, 156, 31, 128, 240, 31, 1, 248, 57, 199, 14, 96, 108, 3], [96, 103, 6, 48, 225, 156, 31, 128, 240, 15, 1, 248, 57, 199, 12, 96, 236, 6], [96, 51, 7, 56, 225, 156, 15, 128, 240, 15, 1, 152, 57, 199, 12, 224, 228, 6], [112, 35, 6, 24, 193, 220, 15, 128, 240, 15, 1, 248, 57, 135, 28, 224, 196, 6], [48, 3, 135, 24, 225, 220, 15, 128, 112, 15, 1, 248, 57, 135, 28, 224, 192, 6], [0, 206, 28, 113, 131, 184, 31, 0, 224, 15, 1, 248, 25, 195, 142, 112, 118, 2], [64, 238, 28, 113, 195, 184, 31, 0, 240, 15, 1, 248, 25, 195, 142, 112, 118, 2], [64, 102, 14, 49, 195, 152, 31, 128, 240, 15, 1, 248, 25, 195, 142, 48, 102, 3], [64, 110, 14, 113, 195, 152, 31, 128, 240, 15, 1, 248, 57, 195, 14, 112, 118, 2], [96, 103, 14, 57, 195, 156, 31, 128, 240, 15, 129, 216, 57, 195, 14, 112, 118, 2], [224, 118, 6, 121, 227, 156, 31, 128, 240, 31, 129, 248, 57, 199, 158, 224, 124, 3], [96, 55, 7, 56, 227, 156, 31, 128, 248, 15, 129, 248, 57, 199, 158, 224, 108, 7], [96, 39, 7, 56, 225, 156, 31, 128, 240, 15, 1, 248, 57, 199, 12, 224, 228, 6], [112, 35, 7, 56, 225, 220, 15, 128, 240, 15, 1, 248, 57, 135, 28, 224, 196, 14]] }, { symbol: 'Y', fingerprints: [[64, 62, 14, 112, 227, 156, 29, 192, 240, 7, 0, 112, 7, 0, 48, 3, 0, 48], [64, 54, 7, 112, 227, 140, 31, 192, 248, 7, 0, 112, 3, 0, 48, 3, 0, 48], [192, 55, 14, 112, 227, 156, 31, 128, 240, 7, 0, 112, 7, 0, 112, 7, 0, 48], [64, 55, 6, 112, 227, 156, 15, 192, 240, 7, 0, 112, 7, 0, 112, 7, 0, 112], [192, 54, 14, 112, 227, 156, 31, 128, 240, 7, 0, 96, 6, 0, 96, 6, 0, 96], [224, 118, 6, 48, 195, 156, 31, 128, 240, 6, 0, 96, 6, 0, 96, 6, 0, 96], [192, 55, 14, 112, 227, 156, 31, 128, 240, 14, 0, 224, 14, 0, 224, 14, 0, 96], [224, 38, 6, 112, 227, 156, 31, 128, 224, 6, 0, 96, 6, 0, 224, 14, 0, 64], [192, 54, 7, 112, 227, 156, 59, 128, 240, 14, 0, 224, 14, 0, 224, 14, 0, 224], [64, 38, 6, 112, 227, 156, 27, 129, 224, 14, 0, 192, 12, 0, 192, 12, 1, 192], [192, 6, 7, 112, 227, 28, 59, 129, 240, 14, 0, 224, 12, 0, 192, 12, 0, 128], [64, 118, 6, 120, 227, 220, 31, 192, 120, 7, 128, 56, 3, 128, 56, 3, 128, 56], [64, 110, 6, 112, 227, 156, 31, 128, 248, 7, 0, 112, 7, 0, 48, 3, 0, 56], [64, 62, 14, 112, 227, 156, 29, 192, 240, 7, 0, 112, 7, 0, 112, 7, 0, 112], [192, 118, 6, 112, 227, 156, 31, 128, 240, 6, 0, 96, 6, 0, 112, 7, 0, 96], [192, 63, 14, 112, 227, 156, 31, 128, 240, 15, 0, 112, 7, 0, 112, 7, 0, 112], [192, 38, 6, 112, 227, 156, 31, 128, 240, 6, 0, 96, 6, 0, 96, 6, 0, 96], [224, 54, 6, 112, 227, 156, 31, 129, 240, 14, 0, 96, 14, 0, 224, 14, 0, 224], [224, 38, 6, 113, 227, 156, 31, 129, 240, 14, 0, 224, 12, 0, 192, 28, 0, 192], [192, 14, 7, 112, 227, 156, 59, 129, 240, 14, 0, 224, 12, 0, 192, 28, 1, 192], [0, 62, 7, 120, 227, 158, 29, 192, 248, 7, 128, 56, 3, 128, 56, 3, 128, 56], [64, 126, 6, 121, 227, 156, 31, 128, 248, 7, 0, 112, 7, 0, 112, 3, 128, 48], [64, 54, 7, 120, 227, 156, 31, 192, 248, 7, 0, 112, 7, 0, 56, 3, 128, 56], [64, 110, 6, 113, 227, 156, 31, 129, 248, 7, 0, 112, 7, 0, 112, 7, 0, 112], [96, 55, 7, 120, 227, 220, 31, 192, 248, 7, 0, 112, 7, 0, 112, 7, 0, 112], [192, 118, 6, 121, 227, 156, 31, 129, 240, 6, 0, 96, 6, 0, 96, 6, 0, 96], [96, 55, 7, 56, 227, 156, 31, 192, 248, 6, 0, 96, 6, 0, 96, 6, 0, 96], [192, 46, 7, 113, 227, 156, 63, 129, 240, 14, 0, 224, 14, 0, 224, 14, 0, 224], [192, 63, 15, 112, 227, 156, 63, 129, 240, 14, 0, 224, 14, 0, 224, 14, 0, 224], [224, 38, 7, 121, 227, 156, 63, 129, 240, 14, 0, 224, 30, 1, 192, 28, 1, 192], [192, 47, 7, 112, 231, 156, 63, 129, 240, 14, 0, 224, 14, 1, 192, 28, 1, 192]] }, { symbol: 'Z', fingerprints: [[255, 199, 24, 1, 128, 112, 7, 0, 224, 14, 1, 192, 24, 3, 128, 63, 247, 254], [255, 207, 156, 3, 128, 56, 6, 0, 96, 12, 1, 192, 56, 3, 128, 127, 247, 255], [127, 199, 252, 1, 192, 56, 7, 0, 96, 14, 1, 192, 24, 3, 128, 127, 247, 255], [255, 224, 28, 1, 192, 48, 7, 0, 224, 12, 3, 128, 56, 7, 0, 127, 247, 255], [255, 224, 28, 1, 192, 56, 7, 0, 96, 14, 1, 128, 56, 7, 0, 127, 247, 255], [255, 224, 14, 1, 192, 56, 7, 0, 240, 28, 1, 192, 56, 7, 0, 255, 255, 255], [255, 231, 254, 0, 224, 56, 7, 0, 240, 14, 1, 192, 56, 7, 0, 255, 255, 255], [127, 231, 254, 0, 224, 28, 3, 128, 240, 14, 1, 192, 56, 7, 0, 255, 239, 255], [127, 240, 15, 0, 224, 28, 3, 128, 112, 14, 1, 192, 56, 7, 0, 255, 255, 255], [127, 240, 30, 0, 224, 28, 7, 0, 112, 14, 3, 128, 56, 7, 0, 255, 239, 254], [127, 224, 127, 0, 224, 28, 3, 128, 112, 14, 1, 192, 56, 7, 0, 255, 195, 254], [127, 207, 252, 1, 128, 56, 7, 0, 224, 14, 1, 192, 24, 3, 128, 63, 247, 254], [255, 207, 252, 1, 192, 56, 7, 0, 96, 14, 1, 192, 56, 3, 128, 127, 247, 254], [255, 224, 30, 1, 192, 56, 7, 0, 240, 14, 3, 192, 56, 7, 0, 255, 255, 255], [127, 231, 252, 1, 192, 56, 7, 0, 96, 28, 1, 192, 56, 7, 0, 127, 239, 254], [127, 231, 254, 1, 192, 56, 7, 128, 96, 14, 1, 192, 56, 7, 128, 127, 239, 255], [127, 227, 254, 1, 192, 60, 3, 128, 96, 14, 1, 192, 56, 7, 0, 127, 231, 254], [127, 227, 254, 0, 224, 28, 3, 128, 112, 14, 1, 192, 56, 7, 0, 127, 199, 255], [63, 240, 126, 0, 224, 28, 3, 128, 112, 14, 1, 192, 56, 7, 128, 127, 231, 255], [63, 240, 255, 0, 224, 28, 3, 128, 112, 14, 1, 192, 56, 7, 0, 127, 231, 254], [127, 207, 252, 3, 128, 120, 7, 0, 224, 14, 1, 192, 56, 3, 128, 127, 247, 248], [255, 207, 252, 3, 128, 120, 7, 0, 224, 30, 1, 192, 56, 7, 0, 127, 231, 254], [127, 199, 252, 1, 192, 56, 7, 0, 224, 14, 1, 192, 56, 3, 0, 127, 231, 254], [255, 207, 252, 1, 192, 56, 7, 0, 224, 30, 1, 192, 56, 7, 0, 127, 239, 254], [255, 231, 252, 1, 192, 56, 7, 0, 96, 30, 3, 192, 56, 7, 128, 255, 239, 255], [127, 231, 254, 1, 192, 56, 7, 128, 224, 30, 1, 192, 56, 7, 0, 255, 231, 254], [127, 231, 254, 1, 224, 60, 3, 128, 112, 14, 1, 192, 56, 7, 0, 127, 231, 255], [63, 227, 255, 0, 224, 28, 3, 128, 120, 14, 1, 192, 56, 7, 128, 255, 231, 255], [63, 225, 254, 0, 224, 28, 7, 128, 240, 14, 1, 192, 56, 7, 0, 255, 231, 254]] }, { symbol: '<', fingerprints: [[0, 96, 30, 7, 128, 240, 28, 7, 128, 224, 7, 192, 30, 0, 120, 1, 240, 7], [0, 224, 30, 3, 128, 224, 28, 7, 128, 240, 7, 128, 30, 0, 60, 1, 224, 7], [0, 96, 14, 3, 128, 240, 28, 7, 0, 240, 3, 192, 15, 0, 124, 0, 240, 3], [0, 112, 30, 7, 193, 240, 60, 7, 0, 240, 3, 192, 31, 0, 60, 0, 240, 7], [0, 96, 30, 3, 192, 224, 60, 7, 128, 240, 3, 192, 30, 0, 60, 1, 224, 7], [0, 96, 14, 7, 128, 240, 28, 7, 0, 240, 1, 192, 15, 0, 56, 0, 224, 7], [0, 112, 30, 7, 193, 240, 56, 15, 0, 112, 3, 192, 31, 0, 60, 0, 224, 7], [0, 112, 30, 7, 129, 224, 60, 14, 0, 112, 1, 192, 15, 0, 56, 0, 224, 6], [0, 112, 30, 7, 193, 224, 120, 15, 0, 120, 1, 192, 15, 0, 60, 1, 224, 6], [0, 112, 30, 7, 193, 224, 120, 15, 0, 112, 3, 192, 14, 0, 120, 1, 192, 14], [0, 112, 30, 7, 131, 224, 120, 14, 0, 56, 1, 192, 15, 0, 56, 1, 224, 14], [0, 224, 30, 3, 128, 224, 60, 7, 128, 240, 7, 192, 30, 0, 124, 1, 240, 7], [0, 224, 30, 7, 128, 224, 60, 15, 0, 224, 7, 192, 31, 0, 120, 1, 224, 6], [0, 96, 30, 7, 128, 240, 60, 15, 0, 224, 7, 192, 31, 0, 120, 1, 224, 7], [0, 96, 30, 7, 128, 240, 60, 15, 0, 240, 3, 224, 15, 0, 124, 0, 240, 6], [0, 112, 15, 7, 128, 240, 60, 15, 0, 240, 3, 224, 15, 0, 120, 0, 224, 7], [0, 112, 30, 3, 193, 240, 60, 7, 128, 120, 3, 192, 15, 0, 60, 1, 224, 7], [0, 112, 30, 7, 129, 240, 60, 15, 0, 112, 1, 224, 15, 0, 120, 1, 224, 6], [0, 48, 15, 7, 192, 240, 60, 15, 0, 112, 1, 224, 15, 0, 120, 1, 224, 6], [0, 112, 30, 15, 129, 224, 124, 14, 0, 120, 1, 224, 15, 0, 120, 1, 224, 6], [0, 112, 15, 7, 193, 240, 124, 14, 0, 120, 1, 192, 15, 0, 120, 1, 224, 14], [0, 224, 30, 7, 128, 240, 30, 7, 128, 240, 7, 192, 31, 0, 252, 1, 240, 7], [0, 224, 30, 7, 128, 240, 60, 7, 128, 224, 15, 128, 62, 0, 248, 3, 224, 15], [0, 224, 30, 7, 129, 240, 60, 15, 0, 240, 7, 192, 31, 0, 120, 1, 240, 7], [0, 96, 30, 7, 128, 240, 62, 15, 128, 240, 7, 192, 31, 0, 120, 1, 224, 7], [0, 240, 30, 7, 129, 240, 60, 15, 0, 240, 3, 224, 15, 0, 124, 0, 240, 7], [0, 112, 31, 7, 192, 240, 62, 15, 0, 240, 3, 224, 15, 0, 124, 1, 240, 7], [0, 96, 31, 7, 192, 240, 124, 15, 0, 248, 3, 192, 15, 0, 124, 1, 224, 6], [0, 112, 31, 7, 129, 240, 60, 15, 0, 248, 3, 224, 15, 0, 120, 1, 224, 6], [0, 96, 30, 7, 129, 240, 124, 15, 0, 240, 3, 192, 30, 0, 120, 1, 224, 14], [0, 112, 31, 15, 131, 224, 124, 14, 0, 120, 1, 224, 15, 0, 120, 1, 224, 14], [0, 112, 31, 7, 193, 240, 124, 15, 0, 120, 1, 224, 15, 0, 120, 1, 224, 14]] }] }; 12 | 13 | 14 | var dir = 'demo/'; 15 | var files = FS.readdirSync(dir); 16 | 17 | (async function () { 18 | for (let file of files) { 19 | if (file.match(/(passport)/)) { 20 | let image = await IJS.load(dir + file); 21 | image = image.level(); 22 | 23 | var smallImage = image; 24 | if (image.width > 1000 || image.height > 1000) { 25 | if (image.width > image.height) { 26 | smallImage = image.scale({ width: 1000 }); 27 | } else { 28 | smallImage = image.scale({ height: 1000 }); 29 | } 30 | } 31 | 32 | 33 | let options = { 34 | roiOptions: { 35 | minWidth: Math.min(smallImage.width, smallImage.height) / 100, 36 | minHeight: Math.min(smallImage.width, smallImage.height) / 100, 37 | positive: true, 38 | negative: false, 39 | greyThreshold: 0.5 40 | }, 41 | fingerprintOptions: { 42 | height: 12, 43 | width: 12, 44 | minSimilarity: 0.7 45 | } 46 | }; 47 | 48 | var result = getRotation(smallImage, fontFingerprint, options); 49 | console.log(file, ' - Rotation: ', result.rotation, ' Reliability: ', result.reliability); 50 | 51 | // we rotate 52 | 53 | image = image.rotate(result.rotation); 54 | 55 | 56 | options = { 57 | roiOptions: { 58 | minWidth: Math.min(image.width, image.height) / 100, 59 | minHeight: Math.min(image.width, image.height) / 100, 60 | positive: true, 61 | negative: false, 62 | greyThreshold: 0.5 63 | }, 64 | fingerprintOptions: { 65 | height: 12, 66 | width: 12, 67 | minSimilarity: 0.5 68 | } 69 | }; 70 | 71 | 72 | result = runOCR(image, fontFingerprint, options).lines; 73 | if (result.length > 2) { 74 | result = result.slice(result.length - 3, result.length); 75 | } 76 | var mzr = result.map((a) => a.text); 77 | 78 | console.log(mzr.join('\r\n')); 79 | } 80 | } 81 | })(); 82 | 83 | --------------------------------------------------------------------------------