Я пытаюсь получить координаты x и y определенного текста на изображении, таком как это. На этом изображении я пытаюсь определить, где находится X:input Y:input, что может быть где угодно на будущих изображениях. В этом случае я ожидаю, что это будет около 714, 164, 125, 32 (x, y, ширина, высота).
Я пытался использовать Tesseract и Jimp
const worker = await Tesseract.createWorker();
await worker.loadLanguage("eng");
await worker.initialize("eng");
const convertedImage = await image
.grayscale()
.getBufferAsync(Jimp.MIME_PNG);
await worker.setParameters({ tessedit_char_whitelist: "XY012345678" });
const { data } = await worker.recognize(convertedImage);
Но я не уверен, что что-то в data позволяет мне получить желаемый результат. Я не знаю других библиотек, которые могли бы мне помочь
Мой вклад X:323 Y:528. Этот текст виден на изображении, и я хотел бы программно получить координаты этого текста внутри изображения. Когда я открываю изображение в таком инструменте, как IrfanView, и выбираю текст, я вижу что-то вроде 714, 164, 125, 32, что примерно соответствует ожидаемому результату кода.
Даже при контрасте 20% текст все равно не читался. Установка на 10% сработала.
import path from "path";
import Jimp from "jimp";
import { createWorker, PSM } from "tesseract.js";
const __dirname = path.resolve();
const main = async () => {
const imagePath = path.join(__dirname, "image.png");
const bounds = await getBoundingBox(imagePath, "X323Y528", "XY012345689");
console.info("Bounds:", bounds); // { x: 719, y: 173, width: 116, height: 16 }
};
const getBoundingBox = async (imagePath, searchText, allowedCharacters) => {
const worker = await createWorker();
await worker.loadLanguage("eng");
await worker.initialize("eng");
await worker.setParameters({
tessedit_char_whitelist: allowedCharacters,
tessedit_pageseg_mode: PSM.SPARSE_TEXT,
});
const image = await Jimp.read(imagePath);
const imageBuffer = await image
.color([{ apply: "desaturate", params: [90] }])
.contrast(0.1)
.invert()
.write("processed.jpg")
.getBufferAsync(Jimp.MIME_PNG);
const { data } = await worker.recognize(imageBuffer);
const bounds = data.blocks
?.filter(({ text }) => text.trim() === searchText)
.map(({ bbox }) => ({
x: bbox.x0,
y: bbox.y0,
width: bbox.x1 - bbox.x0,
height: bbox.y1 - bbox.y0,
}))
.at(0);
await worker.terminate();
return bounds;
};
(async () => {
await main();
})();
Вам нужно будет вырезать текст из изображения.
Изображение слишком шумное, даже если вы преобразуете его в оттенки серого.
Кроме того, вы можете установить tessedit_pageseg_mode на PSM.SINGLE_LINE.
import path from "path";
import Jimp from "jimp";
import { createWorker, PSM } from "tesseract.js";
const __dirname = path.resolve();
const main = async () => {
const position = await getPosition(
path.join(__dirname, "image.png"),
700,
160,
150,
40
);
console.info(position); // { x: 323, y: 528 }
};
const getPosition = async (imagePath, xOffset, yOffset, width, height) => {
const worker = await createWorker({
logger: (m) => {
// console.info(m);
},
});
await worker.loadLanguage("eng");
await worker.initialize("eng");
await worker.setParameters({
tessedit_char_whitelist: "XY012345678:",
tessedit_pageseg_mode: PSM.SINGLE_LINE,
});
const image = await Jimp.read(imagePath);
const convertedImage = image
.grayscale()
.contrast(0.3)
.crop(
xOffset ?? 0,
yOffset ?? 0,
width ?? image.bitmap.width,
height ?? image.bitmap.height
)
.write("greyscale.jpg");
const base64 = await convertedImage.getBase64Async(Jimp.AUTO);
const {
data: { text },
} = await worker.recognize(base64);
let [x, y] = text
.match(/X:(\d+)Y:(\d+)/)
?.slice(1)
?.map((v) => parseInt(v, 10)) || [-1, -1];
await worker.terminate();
return { x, y };
};
(async () => {
await main();
})();
Пожалуйста, уточните вашу конкретную проблему или предоставьте дополнительную информацию, чтобы выделить именно то, что вам нужно. Как сейчас написано, трудно точно сказать, о чем вы спрашиваете.