1
0
forked from BRT/arc

Restrict OCR search area to the lower half of the confirm sheet in PayByPhoneScript and PayByCardScript to reduce false positives. Adjust minimum word length for substring matching in OcrUtils to improve tap accuracy.

This commit is contained in:
trnsmkot 2026-05-21 16:12:20 +05:00
parent 0dc091ea17
commit 8f7bc16090
3 changed files with 21 additions and 5 deletions

View File

@ -382,10 +382,14 @@ void PayByCardScript::makePayment(
// отдельного узла "Подтверждаю" в дампе нет — координаты берём OCR-ом
// по скриншоту. Если OCR не нашёл — fallback на геометрию (центр
// нижней четверти sheet, выше системного nav-бара).
// Compose отдаёт sheet как одну ноду на весь экран ([0,0][720,1640]),
// поэтому confirmNode.y1/y2 не сужают поиск — OCR сканирует весь
// скриншот и ловит ложные совпадения. Ограничиваем нижней половиной.
const int ocrYMin = (confirmNode.y1() + confirmNode.y2()) / 2;
const QByteArray screen = AdbUtils::captureScreenshotBytes(deviceId);
QPoint tap = OcrUtils::findTextCenter(screen,
QString::fromUtf8("Подтверждаю"),
confirmNode.y1(), confirmNode.y2());
ocrYMin, confirmNode.y2());
if (tap.x() < 0) {
const int tapY = confirmNode.y2() - qMax(150, height / 14);
tap = QPoint(confirmNode.x(), tapY);
@ -478,10 +482,11 @@ void PayByCardScript::makePayment(
++confirmRetries;
qDebug() << "[Dushanbe::PayByCard] Confirm sheet still visible, re-tap"
<< confirmRetries << "/" << maxConfirmRetries;
const int ocrYMin = (retryConfirm.y1() + retryConfirm.y2()) / 2;
const QByteArray screen = AdbUtils::captureScreenshotBytes(deviceId);
QPoint tap = OcrUtils::findTextCenter(screen,
QString::fromUtf8("Подтверждаю"),
retryConfirm.y1(), retryConfirm.y2());
ocrYMin, retryConfirm.y2());
if (tap.x() < 0) {
// Варьируем Y: первый retry — выше fallback на 100px,
// второй — ещё на 100px выше. Compose-кнопка действия

View File

@ -378,10 +378,15 @@ void PayByPhoneScript::makePayment(
// отдельного узла "Подтверждаю" в дампе нет — координаты берём OCR-ом
// по скриншоту. Если OCR не нашёл — fallback на геометрию (центр
// нижней четверти sheet, выше системного nav-бара).
// Compose отдаёт sheet как одну ноду на весь экран ([0,0][720,1640]),
// поэтому confirmNode.y1/y2 не сужают поиск — OCR сканирует весь
// скриншот и ловит ложные совпадения (буква "в" в шапке).
// Ограничиваем нижней половиной — действие-кнопка всегда внизу sheet'a.
const int ocrYMin = (confirmNode.y1() + confirmNode.y2()) / 2;
const QByteArray screen = AdbUtils::captureScreenshotBytes(deviceId);
QPoint tap = OcrUtils::findTextCenter(screen,
QString::fromUtf8("Подтверждаю"),
confirmNode.y1(), confirmNode.y2());
ocrYMin, confirmNode.y2());
if (tap.x() < 0) {
const int tapY = confirmNode.y2() - qMax(150, height / 14);
tap = QPoint(confirmNode.x(), tapY);
@ -470,10 +475,11 @@ void PayByPhoneScript::makePayment(
++confirmRetries;
qDebug() << "[Dushanbe::PayByPhone] Confirm sheet still visible, re-tap"
<< confirmRetries << "/" << maxConfirmRetries;
const int ocrYMin = (retryConfirm.y1() + retryConfirm.y2()) / 2;
const QByteArray screen = AdbUtils::captureScreenshotBytes(deviceId);
QPoint tap = OcrUtils::findTextCenter(screen,
QString::fromUtf8("Подтверждаю"),
retryConfirm.y1(), retryConfirm.y2());
ocrYMin, retryConfirm.y2());
if (tap.x() < 0) {
// Варьируем Y: первый retry — выше fallback на 100px,
// второй — ещё на 100px выше. Compose-кнопка действия

View File

@ -70,7 +70,12 @@ bool fuzzyMatch(const QString &word, const QString &needle) {
if (word.isEmpty() || needle.isEmpty()) return false;
const QString w = word.toLower();
const QString n = needle.toLower();
if (w.contains(n) || n.contains(w)) return true;
// Substring-ветка работает только если word достаточно длинный.
// Иначе любая одиночная буква, входящая в needle (для «подтверждаю»:
// п/о/д/т/в/е/р/ж/а/ю), даст ложный матч на случайный текст экрана —
// ровно так бот тапал в (620,302) по букве «в» где-то в шапке sheet'a.
const int minLen = qMax(qMin(n.size(), 3), n.size() * 3 / 5);
if (w.size() >= minLen && (w.contains(n) || n.contains(w))) return true;
// Допускаем до 20% ошибок (но не меньше 1) — Tesseract на «Подтверждаю» иногда
// даёт «Подтверждак»/«Подтверждак)» из-за оранжевого фона и сглаживания.
const int tolerance = qMax(1, n.size() / 5);