как я могу обнаружить весь текст внутри блока с помощью Google Vision Api

Я пытаюсь извлечь текст из изображения с помощью google vision api, это работает. Но я просто хочу обнаружить часть изображения, чтобы получить определенный текст.

это изображение, которое я использовал

Мое изображение

Я просто хочу извлечь весь текст от maybank2u.com до From Account:. Я знаю, что есть несколько руководств по выполнению этого трюка с использованием блока, но эти руководства - разные языки программирования.

Мой код:

<div class="row">
    <div class="col-12">
        <ol>
            <?php foreach ($text as $key => $texts): ?> 
                <li><h6> <?php echo ucfirst($texts->info()['description']) ?></h6><<br><br> 
                </li>
            <?php endforeach ?>
        </ol>
    </div>
</div>

Этот код получит весь текст с изображения

Вывод: введите описание изображения здесь


person Community    schedule 06.09.2019    source источник


Ответы (2)


Код ниже работает для меня. У меня есть один файл php, test.php и один файл изображения /images/UUIPXl.png.

Чтобы получить каждую строку текста, я перебираю текстовые аннотации из Google Vision и создаю массив элементов строки. Каждый из них имеет позицию x и текстовое значение.

Затем я сортирую каждую строку по позиции x и объединяю, чтобы создать строку текста.

Наконец, мы останавливаемся, когда получаем последнюю желаемую строку текста.

Я получаю такой результат:

  • maybank2u.com
  • Открыть БиллПлатеж
  • Статус: успешно
  • Референтный номер: 2950211545
  • Дата сделки: 01 фев 2016 13:09:17
  • Сумма: 100 ринггитов.
  • Со счета 564155051577 WCA

PHP-код:

<?php 

    require 'vendor/autoload.php';
    use Google\Cloud\Vision\VisionClient;

    $config = ["keyFile" => json_decode(file_get_contents("./APIKey.json"), true) ];
    $vision = new VisionClient($config);

    $image = $vision->image(
        fopen('./images/UUIPXl.png', 'r'),
        ['TEXT_DETECTION']
    );

    $textAnnotations = $vision->annotate($image)->text();
    $rows = [];

    // Function used to sort our lines.
    function sortProc($a, $b)
    {
        if ($a["x"] === $b["x"]) {
            return 0;
        }
        return ($a["x"] < $b["x"]) ? -1 : 1;
    }

    // Remove first row (complete text).
    array_shift($textAnnotations);

    // We should calculate this, use a reasonable value to begin with.
    $lineHeight = 8;

    foreach ($textAnnotations as $text) {
        $key = round(((double)($text->info()["boundingPoly"]["vertices"][0]["y"]))/$lineHeight);
        $x = (int)$text->info()["boundingPoly"]["vertices"][0]["x"];
        $value = ["x" => $x, "text" => $text->description()];
        if (!isset($rows[$key])) {
            $rows[$key] = [];
        }
        $rows[$key][] = $value;
    }

    $text = [];
    foreach ($rows as $key => $value) {
        // Sort by x value.
        usort($value, "sortProc");

        // Concatenate each line
        $result = array_reduce($value, function($acc, $elem) {
            $acc .= " " . $elem["text"];
            return $acc;
        }, "");

        $text[] = $result;

        // Stop when we get here!
        if (preg_match("/from account/i", $result)) {
            break;
        }
    }

?>

<div class="row" style="padding: 20px;">
    <div class="col-12">
        <ul>
            <?php foreach ($text as $row): ?> 
                <li><h3> <?php echo ucfirst($row) ?></h3></li>
            <?php endforeach ?>
        </ul>
    </div>
</div>
person Terry Lennox    schedule 09.09.2019
comment
спасибо за попытку, могу я узнать if (preg_match("/from account/i", $result)) что означает i в этой строке? - person ; 09.09.2019
comment
Я попробовал ваш код, он работает, но я могу получить : в строке Reference number: 2950211545 и From Account 564155051577 WCA - person ; 09.09.2019
comment
О, завершающий /i предназначен для совпадения без учета регистра. Я думаю, что в PHP это часто делается как #from account#i. - person Terry Lennox; 09.09.2019
comment
Строка с номером ссылки должна включать символ :, строка From Account кажется немного проблематичной, я думаю, что символ : просто не распознается. - person Terry Lennox; 09.09.2019
comment
Изображение действительно имеет относительно низкое разрешение (541 x 466), этим можно объяснить тот факт, что текст не является на 100% точным. - person Terry Lennox; 09.09.2019

Если вы хотите ограничить вывод и каждый раз одну и ту же строку, которая должна остановить выполнение, выполните следующие действия:

<div class="row">
    <div class="col-12">
        <ol>
            <?php foreach ($text as $key => $texts): ?> 
                <?php if (strpos($texts->info()['description'], 'From Account') !== false) break; ?>
                <li><h6> <?php echo ucfirst($texts->info()['description']) ?></h6><<br><br> 
                </li>
            <?php endforeach ?>
        </ol>
    </div>
</div>

Объяснение:
Если $texts->info()['description'] содержит текст From Account, выполнение цикла foreach завершается до break. Если вам нужно проверить несколько ключевых слов прочитайте это.

Альтернативным решением было бы обрезать изображение с помощью imagecrop() перед отправкой на API. Но для этого нужно быть уверенным, что он никогда не меняет размер/положение текстов.

P.S. вы уверены, что все должны видеть эти личные данные на вашем скриншоте?

Update1
Как вы и просили. Это будет тот же код, но с использованием альтернативного синтаксиса для управляющих структур:

<div class="row">
    <div class="col-12">
        <ol>
            <?php foreach ($text as $key => $texts): ?> 
                <?php if (strpos($texts->info()['description'], 'From Account') !== false): ?>
                <?php break; ?>
                <?php endif; ?>
                <li><h6> <?php echo ucfirst($texts->info()['description']) ?></h6><<br><br> 
                </li>
            <?php endforeach ?>
        </ol>
    </div>
</div>

Возможно, это решит вашу проблему, поскольку на той же странице есть это примечание:

Смешивание синтаксисов в одном блоке управления не поддерживается.

Обновление 2

После того, как вы обновили свой вопрос, теперь он более понятен. Вывод не содержит ни одного элемента на текстовую строку. Вместо этого он содержит несколько строк текста. Из-за этого мой первый код ничего не выводил, так как находил From Account в самом первом элементе массива.

Из-за этого нам нужно найти строку From Account и вырезать текстовую строку:

<div class="row">
    <div class="col-12">
        <ol>
            <?php foreach ($text as $key => $texts): ?> 
                <?php
                $text = $texts->info()['description'];
                // search for string
                $pos = strpos($texts->info()['description'], 'From Account');
                if ($pos !== false) {
                    // if the string was found cut the text
                    $text = substr($text, 0, $pos);
                }
                ?>
                <li><h6> <?php echo $text ?></h6><<br><br> 
                </li>
            <?php endforeach ?>
        </ol>
    </div>
</div>

При желании вы можете добавить это перед <?php endforeach ?>, чтобы пропустить все следующие элементы массива:

                <?php
                if ($pos !== false) {
                    break;
                }
                ?>

Примечание. @TerryLennox использует preg_match, чтобы найти From Account. Нет никакой разницы между этим и использованием strpos (большинство предпочитает избегать регулярных выражений). Но его ответ содержит еще один хороший совет. Он использует информацию о позиции текста, чтобы добавить текст построчно в новый массив. Это может быть действительно полезно в зависимости от ваших целей, как отображать/хранить текст.

person mgutt    schedule 06.09.2019
comment
спасибо, но код не работает, все еще получаю весь текст с изображения - person ; 06.09.2019
comment
изображение, которое я только что скачал с гугла, так что это не личные данные, ха-ха - person ; 06.09.2019
comment
@overflowstack Содержит ли $texts->info()['description'] текст From Account, или строка была разделена, или пробел не является пробелом? Или, может быть, вам нужно использовать stripos для преодоления чувствительности к регистру: php.net/manual/function. stripos.php - person mgutt; 07.09.2019
comment
Здесь видно, что код работает: sandbox.onlinephpfunctions.com/code/ - person mgutt; 07.09.2019
comment
я обновил свой вопрос и добавил вывод, пожалуйста, посмотрите на это - person ; 09.09.2019
comment
я знаю, что код должен работать, но когда я использую ваш код, я получаю пустой результат, он не извлекает никакого текста, но когда я изменяю ваш код на From Account:, он получает весь текст, включая текст ниже, чем From account - person ; 09.09.2019
comment
если он пустой, может быть, он содержит строку в первом результате?! Используйте print_r($texts->info()['description']) для проверки содержимого вашего массива. Или страница действительно пуста без html-кода? Это означает, что у вас есть ошибка PHP. Затем вы должны включить отчеты об ошибках. - person mgutt; 09.09.2019
comment
я попробовал print_r, и содержимое совпадает с первым результатом - person ; 09.09.2019
comment
нет, страница не пустая с html-кодом или без него, кстати, почему у вас нет <?php endif?>? - person ; 09.09.2019
comment
@overflowstack endif — это альтернативный синтаксис для записи условия if. Я использовал общий способ или, если быть точным, я использовал сокращение общего способа написания условия if. Вы можете попробовать альтернативу, опубликованную как update1 в моем ответе, но я не думаю, что это что-то изменит. - person mgutt; 09.09.2019
comment
@overflowstack Хорошо, посмотрите на проблему после проверки вашего обновленного вопроса и вывода. Проблема в том, что вы получаете полный текст только как один элемент массива. Я обновлю свой ответ. Дождитесь обновления 2. - person mgutt; 09.09.2019