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
f611639532
commit
d58100083f
@ -11,34 +11,37 @@
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
// Возвращает путь, который надо передавать в `TessBaseAPI::Init`, либо пустую
|
// Кэш байт rus.traineddata. Грузим файл через Qt (Unicode-aware пути) и
|
||||||
// строку, если ни в одной из ожидаемых раскладок rus.traineddata не найден.
|
// отдаём Tesseract в виде in-memory blob через Init(data, size, lang, ...).
|
||||||
// На Windows (vcpkg) Tesseract 5 без подкаталога `tessdata/` иногда падает
|
// Это обходит проблему, что на Windows Tesseract открывает traineddata через
|
||||||
// молча — пробуем оба варианта и логируем результат.
|
// `fopen`, который использует ANSI-кодировку (cp1251 на русской системе).
|
||||||
QString resolveTessdataPath() {
|
// Если путь к exe содержит кириллицу (например, OneDrive\Рабочий стол) —
|
||||||
static QString cached;
|
// fopen не находит файл и Init возвращает -1. Memory-init не зависит от пути.
|
||||||
static bool resolved = false;
|
const QByteArray &tessdataBytes() {
|
||||||
if (resolved) return cached;
|
static QByteArray bytes;
|
||||||
resolved = true;
|
static bool tried = false;
|
||||||
|
if (tried) return bytes;
|
||||||
|
tried = true;
|
||||||
|
|
||||||
const QString appDir = QCoreApplication::applicationDirPath();
|
const QString appDir = QCoreApplication::applicationDirPath();
|
||||||
const QStringList candidates = {
|
const QStringList candidates = {
|
||||||
appDir + "/tessdata", // канонический путь
|
appDir + "/tessdata/rus.traineddata", // канонический путь
|
||||||
appDir, // legacy: traineddata лежат рядом с exe
|
appDir + "/rus.traineddata", // legacy: рядом с exe
|
||||||
};
|
};
|
||||||
for (const QString &dir : candidates) {
|
for (const QString &path : candidates) {
|
||||||
const QString file = dir + "/rus.traineddata";
|
QFile f(path);
|
||||||
if (QFile::exists(file)) {
|
if (!f.open(QIODevice::ReadOnly)) continue;
|
||||||
// Tesseract принимает datapath как РОДИТЕЛЯ tessdata-каталога,
|
bytes = f.readAll();
|
||||||
// но также понимает каталог, где лежат сами .traineddata.
|
f.close();
|
||||||
cached = QDir::toNativeSeparators(dir);
|
if (!bytes.isEmpty()) {
|
||||||
qDebug() << "[OcrUtils] tessdata located at" << cached;
|
qDebug() << "[OcrUtils] loaded rus.traineddata from" << path
|
||||||
return cached;
|
<< "(" << bytes.size() << "bytes)";
|
||||||
|
return bytes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
qWarning() << "[OcrUtils] rus.traineddata NOT FOUND. Checked:" << candidates
|
qWarning() << "[OcrUtils] rus.traineddata NOT FOUND. Checked:" << candidates
|
||||||
<< "— OCR будет работать в fallback-режиме без поиска текста.";
|
<< "— OCR будет работать в fallback-режиме без поиска текста.";
|
||||||
return {};
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -128,17 +131,20 @@ QPoint findTextCenter(const QByteArray &png,
|
|||||||
if (inverted) prepared = inverted;
|
if (inverted) prepared = inverted;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString tessdata = resolveTessdataPath();
|
const QByteArray &td = tessdataBytes();
|
||||||
if (tessdata.isEmpty()) {
|
if (td.isEmpty()) {
|
||||||
if (inverted) pixDestroy(&inverted);
|
if (inverted) pixDestroy(&inverted);
|
||||||
pixDestroy(&gray);
|
pixDestroy(&gray);
|
||||||
return {-1, -1};
|
return {-1, -1};
|
||||||
}
|
}
|
||||||
auto *api = new tesseract::TessBaseAPI();
|
auto *api = new tesseract::TessBaseAPI();
|
||||||
if (api->Init(tessdata.toUtf8().constData(), "rus")) {
|
// Init(data, size, lang, ...) — грузим traineddata из памяти, чтобы
|
||||||
qWarning() << "[OcrUtils] Tesseract init failed for datapath" << tessdata
|
// обойти fopen на путях с кириллицей (Windows ANSI-API).
|
||||||
<< "— rus.traineddata присутствует, но не загрузился"
|
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;
|
delete api;
|
||||||
if (inverted) pixDestroy(&inverted);
|
if (inverted) pixDestroy(&inverted);
|
||||||
pixDestroy(&gray);
|
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