finished easyocr and pipeline
This commit is contained in:
parent
735b6f7157
commit
cf5d944fd1
8 changed files with 252 additions and 51 deletions
|
|
@ -8,7 +8,7 @@ import { logger } from '../util/logger.js';
|
|||
import { sleep } from '../util/sleep.js';
|
||||
import type { BotController } from './BotController.js';
|
||||
import type { ScreenReader } from '../game/ScreenReader.js';
|
||||
import type { OcrEngine } from '../game/OcrDaemon.js';
|
||||
import type { OcrEngine, OcrPreprocess } from '../game/OcrDaemon.js';
|
||||
import { GRID_LAYOUTS } from '../game/GridReader.js';
|
||||
import type { GameController } from '../game/GameController.js';
|
||||
|
||||
|
|
@ -131,8 +131,8 @@ export class DashboardServer {
|
|||
this.app.post('/api/debug/ocr-engine', (req, res) => {
|
||||
if (!this.debug) { res.status(503).json({ error: 'Debug not available' }); return; }
|
||||
const { engine } = req.body as { engine: string };
|
||||
if (!['tesseract', 'easyocr'].includes(engine)) {
|
||||
res.status(400).json({ error: 'Invalid engine. Must be tesseract or easyocr.' });
|
||||
if (!['tesseract', 'easyocr', 'paddleocr'].includes(engine)) {
|
||||
res.status(400).json({ error: 'Invalid engine. Must be tesseract, easyocr, or paddleocr.' });
|
||||
return;
|
||||
}
|
||||
this.debug.screenReader.debugOcrEngine = engine as OcrEngine;
|
||||
|
|
@ -140,6 +140,24 @@ export class DashboardServer {
|
|||
res.json({ ok: true });
|
||||
});
|
||||
|
||||
// OCR preprocess selection
|
||||
this.app.get('/api/debug/ocr-preprocess', (_req, res) => {
|
||||
if (!this.debug) { res.status(503).json({ error: 'Debug not available' }); return; }
|
||||
res.json({ ok: true, preprocess: this.debug.screenReader.debugPreprocess });
|
||||
});
|
||||
|
||||
this.app.post('/api/debug/ocr-preprocess', (req, res) => {
|
||||
if (!this.debug) { res.status(503).json({ error: 'Debug not available' }); return; }
|
||||
const { preprocess } = req.body as { preprocess: string };
|
||||
if (!['none', 'bgsub', 'tophat'].includes(preprocess)) {
|
||||
res.status(400).json({ error: 'Invalid preprocess. Must be none, bgsub, or tophat.' });
|
||||
return;
|
||||
}
|
||||
this.debug.screenReader.debugPreprocess = preprocess as OcrPreprocess;
|
||||
this.broadcastLog('info', `OCR preprocess set to: ${preprocess}`);
|
||||
res.json({ ok: true });
|
||||
});
|
||||
|
||||
this.app.post('/api/debug/ocr', async (_req, res) => {
|
||||
if (!this.debug) { res.status(503).json({ error: 'Debug not available' }); return; }
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -455,6 +455,12 @@
|
|||
<select id="ocrEngineSelect" onchange="setOcrEngine(this.value)" style="padding:6px 10px;background:#0d1117;border:1px solid #30363d;border-radius:6px;color:#e6edf3;font-size:13px">
|
||||
<option value="tesseract">Tesseract</option>
|
||||
<option value="easyocr">EasyOCR</option>
|
||||
<option value="paddleocr">PaddleOCR</option>
|
||||
</select>
|
||||
<select id="ocrPreprocessSelect" onchange="setOcrPreprocess(this.value)" style="padding:6px 10px;background:#0d1117;border:1px solid #30363d;border-radius:6px;color:#e6edf3;font-size:13px">
|
||||
<option value="none">No Preprocess</option>
|
||||
<option value="bgsub" selected>BgSub</option>
|
||||
<option value="tophat">TopHat</option>
|
||||
</select>
|
||||
<button onclick="debugScreenshot()">Screenshot</button>
|
||||
<button onclick="debugOcr()">OCR Screen</button>
|
||||
|
|
@ -1004,8 +1010,27 @@
|
|||
} catch {}
|
||||
}
|
||||
|
||||
async function setOcrPreprocess(preprocess) {
|
||||
await fetch('/api/debug/ocr-preprocess', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ preprocess }),
|
||||
});
|
||||
}
|
||||
|
||||
async function loadOcrPreprocess() {
|
||||
try {
|
||||
const res = await fetch('/api/debug/ocr-preprocess');
|
||||
const data = await res.json();
|
||||
if (data.ok && data.preprocess) {
|
||||
document.getElementById('ocrPreprocessSelect').value = data.preprocess;
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
|
||||
connect();
|
||||
loadOcrEngine();
|
||||
loadOcrPreprocess();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -67,7 +67,9 @@ export interface TemplateMatchResult {
|
|||
confidence: number;
|
||||
}
|
||||
|
||||
export type OcrEngine = 'tesseract' | 'easyocr';
|
||||
export type OcrEngine = 'tesseract' | 'easyocr' | 'paddleocr';
|
||||
|
||||
export type OcrPreprocess = 'none' | 'bgsub' | 'tophat';
|
||||
|
||||
interface DaemonRequest {
|
||||
cmd: string;
|
||||
|
|
@ -79,6 +81,7 @@ interface DaemonRequest {
|
|||
minCellSize?: number;
|
||||
maxCellSize?: number;
|
||||
engine?: string;
|
||||
preprocess?: string;
|
||||
}
|
||||
|
||||
interface DaemonResponse {
|
||||
|
|
@ -133,10 +136,11 @@ export class OcrDaemon {
|
|||
|
||||
// ── Public API ──────────────────────────────────────────────────────────
|
||||
|
||||
async ocr(region?: Region, engine?: OcrEngine): Promise<OcrResponse> {
|
||||
async ocr(region?: Region, engine?: OcrEngine, preprocess?: OcrPreprocess): Promise<OcrResponse> {
|
||||
const req: DaemonRequest = { cmd: 'ocr' };
|
||||
if (region) req.region = region;
|
||||
if (engine && engine !== 'tesseract') req.engine = engine;
|
||||
if (preprocess && preprocess !== 'none') req.preprocess = preprocess;
|
||||
// Python engines need longer timeout for first model load + download
|
||||
const timeout = (engine && engine !== 'tesseract') ? 120_000 : CAPTURE_TIMEOUT;
|
||||
const resp = await this.sendWithRetry(req, timeout);
|
||||
|
|
@ -182,11 +186,12 @@ export class OcrDaemon {
|
|||
await this.sendWithRetry({ cmd: 'snapshot' }, REQUEST_TIMEOUT);
|
||||
}
|
||||
|
||||
async diffOcr(savePath?: string, region?: Region, engine?: OcrEngine): Promise<DiffOcrResponse> {
|
||||
async diffOcr(savePath?: string, region?: Region, engine?: OcrEngine, preprocess?: OcrPreprocess): Promise<DiffOcrResponse> {
|
||||
const req: DaemonRequest = { cmd: 'diff-ocr' };
|
||||
if (savePath) req.path = savePath;
|
||||
if (region) req.region = region;
|
||||
if (engine && engine !== 'tesseract') req.engine = engine;
|
||||
if (preprocess) req.preprocess = preprocess;
|
||||
const timeout = (engine && engine !== 'tesseract') ? 120_000 : CAPTURE_TIMEOUT;
|
||||
const resp = await this.sendWithRetry(req, timeout);
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { mkdir } from 'fs/promises';
|
||||
import { join } from 'path';
|
||||
import { logger } from '../util/logger.js';
|
||||
import { OcrDaemon, type OcrResponse, type OcrEngine, type DiffOcrResponse, type TemplateMatchResult } from './OcrDaemon.js';
|
||||
import { OcrDaemon, type OcrResponse, type OcrEngine, type OcrPreprocess, type DiffOcrResponse, type TemplateMatchResult } from './OcrDaemon.js';
|
||||
import { GridReader, type GridLayout, type CellCoord } from './GridReader.js';
|
||||
import type { Region } from '../types.js';
|
||||
|
||||
|
|
@ -13,6 +13,7 @@ export class ScreenReader {
|
|||
private daemon = new OcrDaemon();
|
||||
readonly grid = new GridReader(this.daemon);
|
||||
debugOcrEngine: OcrEngine = 'tesseract';
|
||||
debugPreprocess: OcrPreprocess = 'bgsub';
|
||||
|
||||
// ── Screenshot capture ──────────────────────────────────────────────
|
||||
|
||||
|
|
@ -241,20 +242,20 @@ export class ScreenReader {
|
|||
|
||||
async debugDiffOcr(savePath?: string, region?: Region): Promise<DiffOcrResponse> {
|
||||
const t = performance.now();
|
||||
const result = await this.daemon.diffOcr(savePath, region, this.debugOcrEngine);
|
||||
logger.info({ engine: this.debugOcrEngine, ms: elapsed(t) }, 'debugDiffOcr');
|
||||
const result = await this.daemon.diffOcr(savePath, region, this.debugOcrEngine, this.debugPreprocess);
|
||||
logger.info({ engine: this.debugOcrEngine, preprocess: this.debugPreprocess, ms: elapsed(t) }, 'debugDiffOcr');
|
||||
return result;
|
||||
}
|
||||
|
||||
async debugOcr(region?: Region): Promise<OcrResponse> {
|
||||
const t = performance.now();
|
||||
const result = await this.daemon.ocr(region, this.debugOcrEngine);
|
||||
logger.info({ engine: this.debugOcrEngine, ms: elapsed(t) }, 'debugOcr');
|
||||
const result = await this.daemon.ocr(region, this.debugOcrEngine, this.debugPreprocess);
|
||||
logger.info({ engine: this.debugOcrEngine, preprocess: this.debugPreprocess, ms: elapsed(t) }, 'debugOcr');
|
||||
return result;
|
||||
}
|
||||
|
||||
async debugReadFullScreen(): Promise<string> {
|
||||
const result = await this.daemon.ocr(undefined, this.debugOcrEngine);
|
||||
const result = await this.daemon.ocr(undefined, this.debugOcrEngine, this.debugPreprocess);
|
||||
return result.text;
|
||||
}
|
||||
|
||||
|
|
@ -263,13 +264,13 @@ export class ScreenReader {
|
|||
fuzzy: boolean = false,
|
||||
): Promise<{ x: number; y: number } | null> {
|
||||
const t = performance.now();
|
||||
const result = await this.daemon.ocr(undefined, this.debugOcrEngine);
|
||||
const result = await this.daemon.ocr(undefined, this.debugOcrEngine, this.debugPreprocess);
|
||||
const pos = this.findWordInOcrResult(result, searchText, fuzzy);
|
||||
|
||||
if (pos) {
|
||||
logger.info({ searchText, engine: this.debugOcrEngine, x: pos.x, y: pos.y, totalMs: elapsed(t) }, 'debugFindText found');
|
||||
logger.info({ searchText, engine: this.debugOcrEngine, preprocess: this.debugPreprocess, x: pos.x, y: pos.y, totalMs: elapsed(t) }, 'debugFindText found');
|
||||
} else {
|
||||
logger.info({ searchText, engine: this.debugOcrEngine, totalMs: elapsed(t) }, 'debugFindText not found');
|
||||
logger.info({ searchText, engine: this.debugOcrEngine, preprocess: this.debugPreprocess, totalMs: elapsed(t) }, 'debugFindText not found');
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue