Как получить координаты текста на изображении с помощью Node.js?

Я пытаюсь получить координаты 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 позволяет мне получить желаемый результат. Я не знаю других библиотек, которые могли бы мне помочь

Пожалуйста, уточните вашу конкретную проблему или предоставьте дополнительную информацию, чтобы выделить именно то, что вам нужно. Как сейчас написано, трудно точно сказать, о чем вы спрашиваете.

Community 21.02.2023 22:00

Мой вклад X:323 Y:528. Этот текст виден на изображении, и я хотел бы программно получить координаты этого текста внутри изображения. Когда я открываю изображение в таком инструменте, как IrfanView, и выбираю текст, я вижу что-то вроде 714, 164, 125, 32, что примерно соответствует ожидаемому результату кода.

Daniell 21.02.2023 22:05
Руководство для начинающих по веб-разработке на React.js
Руководство для начинающих по веб-разработке на React.js
Веб-разработка - это захватывающая и постоянно меняющаяся область, которая постоянно развивается благодаря новым технологиям и тенденциям. Одним из...
Калькулятор CGPA 12 для семестра
Калькулятор CGPA 12 для семестра
Чтобы запустить этот код и рассчитать CGPA, необходимо сохранить код как HTML-файл, а затем открыть его в веб-браузере. Для этого выполните следующие...
Как собрать/развернуть часть вашего приложения Angular
Как собрать/развернуть часть вашего приложения Angular
Вам когда-нибудь требовалось собрать/развернуть только часть вашего приложения Angular или, возможно, скрыть некоторые маршруты в определенных средах?
Оптимизация React Context шаг за шагом в 4 примерах
Оптимизация React Context шаг за шагом в 4 примерах
При использовании компонентов React в сочетании с Context вы можете оптимизировать рендеринг, обернув ваш компонент React в React.memo сразу после...
Интервьюер: Почему '[] instanceof Object' возвращает "true"?
Интервьюер: Почему '[] instanceof Object' возвращает "true"?
Все мы знаем, что [] instanceof Array возвращает true, но почему [] instanceof Object тоже возвращает true?
Абстрактное синтаксическое дерево (AST) и как оно работает с ReactJS
Абстрактное синтаксическое дерево (AST) и как оно работает с ReactJS
Абстрактное синтаксическое дерево (AST) - это древовидная структура данных, которая представляет структуру и иерархию исходного кода на языке...
1
2
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Обновленный ответ

Даже при контрасте 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();
})();

Оригинальный ответ

Вам нужно будет вырезать текст из изображения.

  • Позиция: (700, 160)
  • Размеры: 150×40

Изображение слишком шумное, даже если вы преобразуете его в оттенки серого.

Кроме того, вы можете установить 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();
})();

Другие вопросы по теме