src: clean up, add test code
This commit is contained in:
parent
bac9a2dcf4
commit
bf74693edb
@ -8,10 +8,6 @@
|
|||||||
"test": "react-scripts test"
|
"test": "react-scripts test"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@testing-library/jest-dom": "^5.11.4",
|
|
||||||
"@testing-library/react": "^11.1.0",
|
|
||||||
"@testing-library/user-event": "^12.1.10",
|
|
||||||
"@types/jest": "^26.0.15",
|
|
||||||
"@types/node": "^12.0.0",
|
"@types/node": "^12.0.0",
|
||||||
"@types/react": "^16.9.53",
|
"@types/react": "^16.9.53",
|
||||||
"@types/react-dom": "^16.9.8",
|
"@types/react-dom": "^16.9.8",
|
||||||
@ -21,8 +17,7 @@
|
|||||||
"react-scripts": "4.0.0",
|
"react-scripts": "4.0.0",
|
||||||
"sass": "^1.29.0",
|
"sass": "^1.29.0",
|
||||||
"tesseract.js": "^2.1.4",
|
"tesseract.js": "^2.1.4",
|
||||||
"typescript": "^4.0.3",
|
"typescript": "^4.0.3"
|
||||||
"web-vitals": "^0.2.4"
|
|
||||||
},
|
},
|
||||||
"eslintConfig": {
|
"eslintConfig": {
|
||||||
"extends": [
|
"extends": [
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
|
import ImageUploader from 'react-images-upload';
|
||||||
|
|
||||||
import Logo from '../Logo/Logo';
|
import Logo from '../Logo/Logo';
|
||||||
import Board from '../Board/Board';
|
import Board from '../Board/Board';
|
||||||
|
|
||||||
import './App.scss';
|
import './App.scss';
|
||||||
|
import {findTextRegions} from "../../helpers/findTextRegions";
|
||||||
|
|
||||||
export type Point = {
|
export type Point = {
|
||||||
x: number;
|
x: number;
|
||||||
@ -35,7 +38,28 @@ export default class App extends React.Component {
|
|||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
const gameId = (Math.trunc(Math.random() * 100) % 2) + 1;
|
const gameId = (Math.trunc(Math.random() * 100) % 2) + 1;
|
||||||
this.game = require(`../../constants/${gameId}.json`)
|
this.game = require(`../../constants/${gameId}.json`);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleTakePhoto(pictures: any[], _: any[]): void {
|
||||||
|
console.log("handleTakePhoto: loading image...")
|
||||||
|
const image = pictures[0];
|
||||||
|
|
||||||
|
const {grid, gridWidth, gridHeight} = findTextRegions(image);
|
||||||
|
console.log(grid, gridWidth, gridHeight);
|
||||||
|
|
||||||
|
if (!grid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
debugger;
|
||||||
|
|
||||||
|
let g = grid[0][0];
|
||||||
|
let ot = document.createElement('canvas');
|
||||||
|
ot.width = g.w;
|
||||||
|
ot.height = g.h;
|
||||||
|
ot.getContext('2d')?.putImageData(g.data, 0, 0);
|
||||||
|
document.body.appendChild(ot);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderAnswers(): Array<JSX.Element> {
|
renderAnswers(): Array<JSX.Element> {
|
||||||
@ -55,7 +79,15 @@ export default class App extends React.Component {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div />
|
<div />
|
||||||
<div />
|
<div style={{paddingLeft: '300px'}}>
|
||||||
|
<ImageUploader
|
||||||
|
withIcon={false}
|
||||||
|
buttonText='Wrzuć zdjęcie!'
|
||||||
|
onChange={this.handleTakePhoto.bind(this)}
|
||||||
|
imgExtension={['.jpg', '.jpeg', '.png']}
|
||||||
|
maxFileSize={5242880 * 5} // 5MB * 5
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<Board
|
<Board
|
||||||
cells={this.game.cells}
|
cells={this.game.cells}
|
||||||
|
@ -22,6 +22,7 @@ export function findTextRegions(image, maxWhiteSpace, maxFontLineWidth, minTextW
|
|||||||
for (let y = 0; y < image.height; y++) {
|
for (let y = 0; y < image.height; y++) {
|
||||||
for (let x = 0; x < image.width; x++) {
|
for (let x = 0; x < image.width; x++) {
|
||||||
let offset = ((y * image.width) + x) * 4;
|
let offset = ((y * image.width) + x) * 4;
|
||||||
|
// noinspection PointlessArithmeticExpressionJS
|
||||||
let r = data.data[offset + 0] * 0.30; // 30%
|
let r = data.data[offset + 0] * 0.30; // 30%
|
||||||
let g = data.data[offset + 1] * 0.59; // 59%
|
let g = data.data[offset + 1] * 0.59; // 59%
|
||||||
let b = data.data[offset + 2] * 0.11; // 11%
|
let b = data.data[offset + 2] * 0.11; // 11%
|
||||||
@ -29,6 +30,7 @@ export function findTextRegions(image, maxWhiteSpace, maxFontLineWidth, minTextW
|
|||||||
|
|
||||||
r = g = b = c < grayScaleThreshold ? 0 : 255;
|
r = g = b = c < grayScaleThreshold ? 0 : 255;
|
||||||
|
|
||||||
|
// noinspection PointlessArithmeticExpressionJS
|
||||||
data.data[offset + 0] = r;
|
data.data[offset + 0] = r;
|
||||||
data.data[offset + 1] = g;
|
data.data[offset + 1] = g;
|
||||||
data.data[offset + 2] = b;
|
data.data[offset + 2] = b;
|
||||||
@ -50,6 +52,7 @@ export function findTextRegions(image, maxWhiteSpace, maxFontLineWidth, minTextW
|
|||||||
|
|
||||||
for (let x = 0; x < image.width; x++) {
|
for (let x = 0; x < image.width; x++) {
|
||||||
let o = (y * image.width + x) * 4;
|
let o = (y * image.width + x) * 4;
|
||||||
|
// noinspection PointlessArithmeticExpressionJS
|
||||||
let r = data.data[o + 0] << 16;
|
let r = data.data[o + 0] << 16;
|
||||||
let g = data.data[o + 1] << 8;
|
let g = data.data[o + 1] << 8;
|
||||||
let b = data.data[o + 2] << 0;
|
let b = data.data[o + 2] << 0;
|
||||||
@ -134,8 +137,8 @@ export function findTextRegions(image, maxWhiteSpace, maxFontLineWidth, minTextW
|
|||||||
const y2 = list[i][3];
|
const y2 = list[i][3];
|
||||||
|
|
||||||
if (x1 !== -1 && y1 !== -1 && x2 !== -1 && y2 !== -1) {
|
if (x1 !== -1 && y1 !== -1 && x2 !== -1 && y2 !== -1) {
|
||||||
let w = (x2 - x1) + 1;
|
const w = (x2 - x1) + 1;
|
||||||
let h = (y2 - y1) + 1;
|
const h = (y2 - y1) + 1;
|
||||||
|
|
||||||
if (w >= minTextWidth && h >= minTextWidth) {
|
if (w >= minTextWidth && h >= minTextWidth) {
|
||||||
foundSegments.push({
|
foundSegments.push({
|
||||||
@ -151,7 +154,7 @@ export function findTextRegions(image, maxWhiteSpace, maxFontLineWidth, minTextW
|
|||||||
|
|
||||||
// hopefully we found at least something
|
// hopefully we found at least something
|
||||||
if (!foundSegments.length) {
|
if (!foundSegments.length) {
|
||||||
console.assert("Error: findTextRegions() did not found anything");
|
console.error("findTextRegions(): Error: findTextRegions() did not found anything");
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,29 +179,28 @@ export function findTextRegions(image, maxWhiteSpace, maxFontLineWidth, minTextW
|
|||||||
|
|
||||||
// hopefully we matched every letter in the grid
|
// hopefully we matched every letter in the grid
|
||||||
if (gridWidth * gridHeight !== segments.length) {
|
if (gridWidth * gridHeight !== segments.length) {
|
||||||
console.assert("Dimentions are not equal to the number of matches");
|
console.warning("findTextRegions(): Dimensions are not equal to the number of matches");
|
||||||
}
|
}
|
||||||
|
|
||||||
// prepare grid for letters
|
// prepare grid for letters
|
||||||
let grid = Array.from(Array(gridHeight), () => new Array(gridWidth));
|
let grid = Array.from(Array(gridHeight), () => new Array(gridWidth));
|
||||||
|
|
||||||
// fill grid with imageData objects (captured cutouts)
|
// fill grid with imageData / captured cutouts
|
||||||
for (let j = 0; j < gridHeight; j++) {
|
for (let j = 0; j < gridHeight; j++) {
|
||||||
const segmentOffset = j * gridWidth;
|
const segmentOffset = j * gridWidth;
|
||||||
const indexMap = foundSegments
|
const indexMap = foundSegments
|
||||||
.slice(segmentOffset, segmentOffset + gridWidth);
|
.slice(segmentOffset, segmentOffset + gridWidth)
|
||||||
const reverseIndexMap = indexMap
|
|
||||||
.map(s => s.x)
|
.map(s => s.x)
|
||||||
.sort((a, b) => a - b)
|
.sort((a, b) => a - b)
|
||||||
.reduce((o, x, i) => (o[x] = i, o), {});
|
.reduce((o, x, i) => {
|
||||||
|
o[x] = i;
|
||||||
|
return o
|
||||||
|
}, {});
|
||||||
|
|
||||||
for (let i = 0; i < gridWidth; i++) {
|
for (let i = 0; i < gridWidth; i++) {
|
||||||
let s = foundSegments[segmentOffset + i];
|
let s = foundSegments[segmentOffset + i];
|
||||||
let croppedData = ctx.getImageData(s.x, s.y, s.w, s.h);
|
let croppedData = ctx.getImageData(s.x, s.y, s.w, s.h);
|
||||||
grid[j][reverseIndexMap[s.x]] = {
|
grid[j][indexMap[s.x]] = {data: croppedData, ...s}
|
||||||
data: croppedData,
|
|
||||||
...s,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,16 +1,23 @@
|
|||||||
|
import {createWorker, ImageLike, PSM} from 'tesseract.js';
|
||||||
|
|
||||||
export function recognise(): string {
|
export function recognizeTextOnImage(image: ImageLike, isColumn: boolean): string {
|
||||||
let out;
|
let out;
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
const {data: {text}} = await Tesseract.recognize(image, 'pol', {
|
const worker = createWorker();
|
||||||
workerPath: 'https://unpkg.com/tesseract.js@v2.0.0/dist/worker.min.js',
|
await worker.load();
|
||||||
langPath: 'https://tessdata.projectnaptha.com/4.0.0',
|
await worker.loadLanguage('pol');
|
||||||
corePath: 'https://unpkg.com/tesseract.js-core@v2.0.0/tesseract-core.wasm.js',
|
await worker.initialize('pol');
|
||||||
cacheMethod: 'none',
|
await worker.setParameters({
|
||||||
|
// @ts-ignore, i don't know why this PSM.... stuff is mad at me
|
||||||
|
tessedit_pageseg_mode: isColumn ? PSM.SINGLE_COLUMN : PSM.SINGLE_CHAR,
|
||||||
|
tessedit_char_whitelist: 'AĄBCĆDEĘFGHIJKLŁMNŃOÓPRSŚTUWXYZŹŻ',
|
||||||
|
tessjs_create_box: '1',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const { data: { text } } = await worker.recognize(image);
|
||||||
out = text;
|
out = text;
|
||||||
console.log("recognised: ", text);
|
await worker.terminate();
|
||||||
})();
|
})();
|
||||||
|
|
||||||
return out || "";
|
return out || "";
|
||||||
|
Loading…
Reference in New Issue
Block a user