Switch Tesseract initialization to memory-based loading of rus.traineddata to fix issues with paths containing Cyrillic characters (Windows).
This commit is contained in:
parent
714132382b
commit
55d989258b
@ -11,34 +11,37 @@
|
||||
|
||||
namespace {
|
||||
|
||||
// Возвращает путь, который надо передавать в `TessBaseAPI::Init`, либо пустую
|
||||
// строку, если ни в одной из ожидаемых раскладок rus.traineddata не найден.
|
||||
// На Windows (vcpkg) Tesseract 5 без подкаталога `tessdata/` иногда падает
|
||||
// молча — пробуем оба варианта и логируем результат.
|
||||
QString resolveTessdataPath() {
|
||||
static QString cached;
|
||||
static bool resolved = false;
|
||||
if (resolved) return cached;
|
||||
resolved = true;
|
||||
// Кэш байт rus.traineddata. Грузим файл через Qt (Unicode-aware пути) и
|
||||
// отдаём Tesseract в виде in-memory blob через Init(data, size, lang, ...).
|
||||
// Это обходит проблему, что на Windows Tesseract открывает traineddata через
|
||||
// `fopen`, который использует ANSI-кодировку (cp1251 на русской системе).
|
||||
// Если путь к exe содержит кириллицу (например, OneDrive\Рабочий стол) —
|
||||
// fopen не находит файл и Init возвращает -1. Memory-init не зависит от пути.
|
||||
const QByteArray &tessdataBytes() {
|
||||
static QByteArray bytes;
|
||||
static bool tried = false;
|
||||
if (tried) return bytes;
|
||||
tried = true;
|
||||
|
||||
const QString appDir = QCoreApplication::applicationDirPath();
|
||||
const QStringList candidates = {
|
||||
appDir + "/tessdata", // канонический путь
|
||||
appDir, // legacy: traineddata лежат рядом с exe
|
||||
appDir + "/tessdata/rus.traineddata", // канонический путь
|
||||
appDir + "/rus.traineddata", // legacy: рядом с exe
|
||||
};
|
||||
for (const QString &dir : candidates) {
|
||||
const QString file = dir + "/rus.traineddata";
|
||||
if (QFile::exists(file)) {
|
||||
// Tesseract принимает datapath как РОДИТЕЛЯ tessdata-каталога,
|
||||
// но также понимает каталог, где лежат сами .traineddata.
|
||||
cached = QDir::toNativeSeparators(dir);
|
||||
qDebug() << "[OcrUtils] tessdata located at" << cached;
|
||||
return cached;
|
||||
for (const QString &path : candidates) {
|
||||
QFile f(path);
|
||||
if (!f.open(QIODevice::ReadOnly)) continue;
|
||||
bytes = f.readAll();
|
||||
f.close();
|
||||
if (!bytes.isEmpty()) {
|
||||
qDebug() << "[OcrUtils] loaded rus.traineddata from" << path
|
||||
<< "(" << bytes.size() << "bytes)";
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
qWarning() << "[OcrUtils] rus.traineddata NOT FOUND. Checked:" << candidates
|
||||
<< "— OCR будет работать в fallback-режиме без поиска текста.";
|
||||
return {};
|
||||
return bytes;
|
||||
}
|
||||
|
||||
|
||||
@ -128,17 +131,20 @@ QPoint findTextCenter(const QByteArray &png,
|
||||
if (inverted) prepared = inverted;
|
||||
}
|
||||
|
||||
const QString tessdata = resolveTessdataPath();
|
||||
if (tessdata.isEmpty()) {
|
||||
const QByteArray &td = tessdataBytes();
|
||||
if (td.isEmpty()) {
|
||||
if (inverted) pixDestroy(&inverted);
|
||||
pixDestroy(&gray);
|
||||
return {-1, -1};
|
||||
}
|
||||
auto *api = new tesseract::TessBaseAPI();
|
||||
if (api->Init(tessdata.toUtf8().constData(), "rus")) {
|
||||
qWarning() << "[OcrUtils] Tesseract init failed for datapath" << tessdata
|
||||
<< "— rus.traineddata присутствует, но не загрузился"
|
||||
<< "(возможно, повреждён или несовместимая версия)";
|
||||
// Init(data, size, lang, ...) — грузим traineddata из памяти, чтобы
|
||||
// обойти fopen на путях с кириллицей (Windows ANSI-API).
|
||||
if (api->Init(td.constData(), td.size(), "rus",
|
||||
tesseract::OEM_DEFAULT,
|
||||
nullptr, 0, nullptr, nullptr, false, nullptr)) {
|
||||
qWarning() << "[OcrUtils] Tesseract Init(memory) failed —"
|
||||
<< "traineddata повреждён или несовместимая версия";
|
||||
delete api;
|
||||
if (inverted) pixDestroy(&inverted);
|
||||
pixDestroy(&gray);
|
||||
|
||||
BIN
tessdata/eng.traineddata
Normal file
BIN
tessdata/eng.traineddata
Normal file
Binary file not shown.
BIN
tessdata/rus.traineddata
Normal file
BIN
tessdata/rus.traineddata
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user