Improve OCR preprocessing and normalize merchant names
This commit is contained in:
+1
-1
@@ -78,7 +78,7 @@ export function parseStoreHeaderText(text) {
|
||||
|
||||
return {
|
||||
side: match[1].toLowerCase(),
|
||||
merchant: match[2].trim(),
|
||||
merchant: match[2].replace(/\s+/g, ""),
|
||||
rawText: normalized,
|
||||
};
|
||||
}
|
||||
|
||||
+27
-1
@@ -4,6 +4,16 @@ import { normalizeOcrText } from "./parser.js";
|
||||
let cvPromise;
|
||||
let workerPromise;
|
||||
let progressListener = () => {};
|
||||
const WHITE_TEXT_MIN_CHANNEL = 150;
|
||||
const WHITE_TEXT_MAX_SPREAD = 55;
|
||||
|
||||
export function isWhiteTextPixel(red, green, blue, alpha = 255) {
|
||||
return (
|
||||
alpha >= 128 &&
|
||||
Math.min(red, green, blue) >= WHITE_TEXT_MIN_CHANNEL &&
|
||||
Math.max(red, green, blue) - Math.min(red, green, blue) <= WHITE_TEXT_MAX_SPREAD
|
||||
);
|
||||
}
|
||||
|
||||
export function onOcrProgress(listener) {
|
||||
progressListener = listener;
|
||||
@@ -79,7 +89,6 @@ function prepareOcrCrop(sourceCanvas, rect) {
|
||||
|
||||
const context = canvas.getContext("2d", { willReadFrequently: true });
|
||||
context.imageSmoothingEnabled = false;
|
||||
context.filter = "grayscale(1) contrast(2)";
|
||||
context.drawImage(
|
||||
sourceCanvas,
|
||||
rect.x,
|
||||
@@ -92,6 +101,23 @@ function prepareOcrCrop(sourceCanvas, rect) {
|
||||
canvas.height,
|
||||
);
|
||||
|
||||
const image = context.getImageData(0, 0, canvas.width, canvas.height);
|
||||
for (let index = 0; index < image.data.length; index += 4) {
|
||||
const value = isWhiteTextPixel(
|
||||
image.data[index],
|
||||
image.data[index + 1],
|
||||
image.data[index + 2],
|
||||
image.data[index + 3],
|
||||
)
|
||||
? 0
|
||||
: 255;
|
||||
image.data[index] = value;
|
||||
image.data[index + 1] = value;
|
||||
image.data[index + 2] = value;
|
||||
image.data[index + 3] = 255;
|
||||
}
|
||||
context.putImageData(image, 0, 0);
|
||||
|
||||
return canvas;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,13 @@ import {
|
||||
rectFromPoints,
|
||||
resolveFieldRect,
|
||||
} from "../src/parser.js";
|
||||
import { isWhiteTextPixel } from "../src/vision.js";
|
||||
|
||||
test("keeps white text pixels and removes colored or dark pixels", () => {
|
||||
assert.equal(isWhiteTextPixel(220, 215, 195), true);
|
||||
assert.equal(isWhiteTextPixel(210, 165, 80), false);
|
||||
assert.equal(isWhiteTextPixel(120, 120, 120), false);
|
||||
});
|
||||
|
||||
test("keeps only letters, digits and spaces in OCR item names", () => {
|
||||
assert.equal(cleanItemName(" ~~ Soulshot: S-grade ` "), "Soulshot S grade");
|
||||
@@ -139,5 +146,6 @@ test("parses trade side and merchant from the store header", () => {
|
||||
merchant: "Dwa",
|
||||
rawText: "Private Store({Sell) - Dwa",
|
||||
});
|
||||
assert.equal(parseStoreHeaderText("Private Store(Buy) - Hik vision")?.merchant, "Hikvision");
|
||||
assert.equal(parseStoreHeaderText("Items on Sale"), null);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user