Распознавание текста

Чтобы распознать текст с изображения или из PDF-файла, воспользуйтесь возможностью Распознавание текста.

Для этого в методе batchAnalyze в свойстве type укажите TEXT_DETECTION, а в свойстве textDetectionConfig задайте настройки распознавания.

Примечание

Распознается текст, расположенный горизонтально. Если изображение или текст перевернуты, текст может не распознаться. Если вы отсканировали документ и не знаете, как повернуто изображение, отправьте несколько вариантов изображения с разными углами поворота.

Примеры

Перед началом

Чтобы воспользоваться примерами в этом разделе:

  1. На странице биллинга убедитесь, что платежный аккаунт находится в статусе ACTIVE или TRIAL_ACTIVE. Если платежного аккаунта нет, создайте его.
  2. Убедитесь, что у вас установлена утилита cURL, используемая в примерах.
  3. Получите идентификатор любого каталога, на который у вашего аккаунта есть роль editor или выше.
  4. Получите IAM-токен для своего аккаунта на Яндексе.

Чтобы выполнять эти операции от имени сервисного аккаунта:

  1. Назначьте сервисному аккаунту роль editor или выше на каталог, в котором он был создан.
  2. Не указывайте в запросе идентификатор каталога — сервис использует каталог, в котором был создан сервисный аккаунт.
  3. Выберите способ аутентификации: получите IAM-токен или API-ключ.

Распознать текст с изображения

  1. Подготовьте файл изображения, соответствующий требованиям:

    • Поддерживаемые форматы файлов: JPEG, PNG, PDF.

      MIME-тип файла указывается указывается в свойстве mime_type. По умолчанию image.

    • Максимальный размер файла: 1 МБ.

    • Размер изображения не должен превышать 20 мегапикселей (длина x ширина).

    Примечание

    Нужен пример изображения? Скачайте изображение дорожного знака, предупреждающего о пингвинах.

  2. Кодируйте файл в формат Base64:

    $ base64 -i input.jpg > output.txt
    
    C:> Base64.exe -e input.jpg > output.txt
    
    [Convert]::ToBase64String([IO.File]::ReadAllBytes("./input.jpg")) > output.txt
    
    # Импортируйте библиотеку для кодирования в Base64
    import base64
    
    # Создайте функцию, которая кодирует файл и возвращает результат.
    def encode_file(file):
      file_content = file.read()
      return base64.b64encode(file_content)
    
    // Считайте содержимое файла в память.
    var fs = require('fs');
    var file = fs.readFileSync('/path/to/file');
    
    // Получите содержимое файла в формате Base64.
    var encoded = Buffer.from(file).toString('base64');
    
    // Импортируйте библиотеку для кодирования в Base64.
    import org.apache.commons.codec.binary.Base64;
    
    // Получите содержимое файла в формате Base64.
    byte[] fileData = Base64.encodeBase64(yourFile.getBytes());
    
    import (
        "bufio"
        "encoding/base64"
        "io/ioutil"
        "os"
    )
    
    // Откройте файл
    f, _ := os.Open("/path/to/file")
    
    // Прочитайте содержимое файла.
    reader := bufio.NewReader(f)
    content, _ := ioutil.ReadAll(reader)
    
    // Получите содержимое файла в формате Base64.
    base64.StdEncoding.EncodeToString(content)
    
  3. Создайте файл с телом запроса, например body.json. В свойстве content укажите изображение, кодированное в Base64.

    Чтобы сервис автоматически определил язык текста, укажите в конфигурации свойство "language_codes": ["*"].

    body.json:

    {
        "folderId": "b1gvmob95yysaplct532",
        "analyze_specs": [{
            "content": "iVBORw0KGgo...",
            "features": [{
                "type": "TEXT_DETECTION",
                "text_detection_config": {
                    "language_codes": ["*"]
                }
            }]
        }]
    }
    
  4. Отправьте запрос с помощью метода batchAnalyze и сохраните ответ в файл, например output.json:

    $ export IAM_TOKEN=CggaATEVAgA...
    $ curl -X POST \
        -H "Content-Type: application/json" \
        -H "Authorization: Bearer ${IAM_TOKEN}" \
        -d '@body.json' \
        https://vision.api.cloud.yandex.net/vision/v1/batchAnalyze > output.json
    

    Ответ будет состоять из распознанных блоков текста, строк и слов с указанием их местоположения на изображении:

    {
      "results": [{
        "results": [{
          "textDetection": {
            "pages": [{
              "blocks": [{
                "boundingBox": { ... },
                "lines": [{
                    "boundingBox": { ... },
                    "words": [{
                      "boundingBox": {
                        "vertices": [{
                            "x": "504",
                            "y": "760"
                          },
                          {
                            "x": "504",
                            "y": "836"
                          },
                          {
                            "x": "826",
                            "y": "836"
                          },
                          {
                            "x": "826",
                            "y": "760"
                          }
                        ]
                      },
                      "languages": [{
                        "languageCode": "en",
                        "confidence": 0.9520227313
                      }],
                      "text": "PENGUINS",
                      "confidence": 0.9520227313
                    }],
                    "confidence": 0.9520227313
                  },
                  ...
                ]
              }],
              "width": "1920",
              "height": "1280"
            }]
          }
        }]
      }]
    }
    
  5. Чтобы получить все распознанные слова с изображения, найдите все строки с свойством text, например с помощью grep:

    $ grep -o "\"text\":\s\".*\"" output.json
    "text": "PENGUINS"
    "text": "CROSSING"
    "text": "SLOW"
    

Распознайте текст из PDF-файла

  1. В PDF-файле должно быть не больше 8 страниц. Если страниц больше, разбейте его на файлы по 8 страниц.

  2. Кодируйте PDF-файл в формат Base64.

    $ base64 -i input.jpg > output.txt
    
    C:> Base64.exe -e input.jpg > output.txt
    
    [Convert]::ToBase64String([IO.File]::ReadAllBytes("./input.jpg")) > output.txt
    
    # Импортируйте библиотеку для кодирования в Base64
    import base64
    
    # Создайте функцию, которая кодирует файл и возвращает результат.
    def encode_file(file):
      file_content = file.read()
      return base64.b64encode(file_content)
    
    // Считайте содержимое файла в память.
    var fs = require('fs');
    var file = fs.readFileSync('/path/to/file');
    
    // Получите содержимое файла в формате Base64.
    var encoded = Buffer.from(file).toString('base64');
    
    // Импортируйте библиотеку для кодирования в Base64.
    import org.apache.commons.codec.binary.Base64;
    
    // Получите содержимое файла в формате Base64.
    byte[] fileData = Base64.encodeBase64(yourFile.getBytes());
    
    import (
        "bufio"
        "encoding/base64"
        "io/ioutil"
        "os"
    )
    
    // Откройте файл
    f, _ := os.Open("/path/to/file")
    
    // Прочитайте содержимое файла.
    reader := bufio.NewReader(f)
    content, _ := ioutil.ReadAll(reader)
    
    // Получите содержимое файла в формате Base64.
    base64.StdEncoding.EncodeToString(content)
    
  3. Создайте файл с телом запроса, например body.json.

    В теле запроса укажите MIME-тип application/pdf, а в свойстве content укажите PDF-файл, кодированный в Base64.

    body.json:

    {
        "folderId": "b1gvmob95yysaplct532",
        "analyze_specs": [{
            "content": "iVBORw0KGgo...",
            "mime_type": "application/pdf",
            "features": [{
                "type": "TEXT_DETECTION",
                "text_detection_config": {
                    "language_codes": ["*"]
                }
            }]
        }]
    }
    
  4. Отправьте запрос с помощью метода batchAnalyze и сохраните ответ в файл, например output.json:

    $ export IAM_TOKEN=CggaATEVAgA...
    $ curl -X POST \
        -H "Content-Type: application/json" \
        -H "Authorization: Bearer ${IAM_TOKEN}" \
        -d '@body.json' \
        https://vision.api.cloud.yandex.net/vision/v1/batchAnalyze > output.json
    

Указать язык текста в запросе

Если вы знаете язык текста, укажите его в запросе, чтобы повысить качество распознавания:

  1. Кодируйте файл в формат Base64:

    $ base64 -i input.jpg > output.txt
    
    C:> Base64.exe -e input.jpg > output.txt
    
    [Convert]::ToBase64String([IO.File]::ReadAllBytes("./input.jpg")) > output.txt
    
    # Импортируйте библиотеку для кодирования в Base64
    import base64
    
    # Создайте функцию, которая кодирует файл и возвращает результат.
    def encode_file(file):
      file_content = file.read()
      return base64.b64encode(file_content)
    
    // Считайте содержимое файла в память.
    var fs = require('fs');
    var file = fs.readFileSync('/path/to/file');
    
    // Получите содержимое файла в формате Base64.
    var encoded = Buffer.from(file).toString('base64');
    
    // Импортируйте библиотеку для кодирования в Base64.
    import org.apache.commons.codec.binary.Base64;
    
    // Получите содержимое файла в формате Base64.
    byte[] fileData = Base64.encodeBase64(yourFile.getBytes());
    
    import (
        "bufio"
        "encoding/base64"
        "io/ioutil"
        "os"
    )
    
    // Откройте файл
    f, _ := os.Open("/path/to/file")
    
    // Прочитайте содержимое файла.
    reader := bufio.NewReader(f)
    content, _ := ioutil.ReadAll(reader)
    
    // Получите содержимое файла в формате Base64.
    base64.StdEncoding.EncodeToString(content)
    
  2. Создайте файл с телом запроса, например body.json. В свойстве content укажите изображение, кодированное в Base64.

    body.json:

    {
        "folderId": "b1gvmob95yysaplct532",
        "analyze_specs": [{
            "content": "iVBORw0KGgo...",
            ...
    
  3. Выберите языки для распознавания текста и соответствующие им модели распознавания:

    • Если все языки входят в одну модель, то укажите их в конфигурации запроса. Можно указать до 8 языков. Например, французский и немецкий:

      body.json:

      {
          "folderId": "b1gvmob95yysaplct532",
          "analyze_specs": [{
              "content": "iVBORw0KGgo...",
              "features": [{
                  "type": "TEXT_DETECTION",
                  "text_detection_config": {
                      "language_codes": ["fr", "de"]
                  }
              }]
          }]
      }
      
    • Если языки из разных моделей, задайте несколько конфигураций в свойстве features. Например, распознайте изображение на иврите, арабском и английском языках:

      body.json:

      {
          "folderId": "b1gvmob95yysaplct532",
          "analyze_specs": [{
              "content": "iVBORw0KGgo...",
              "features": [{
                  "type": "TEXT_DETECTION",
                  "text_detection_config": {
                      "language_codes": ["he","en"]
                  }
              },{
                  "type": "TEXT_DETECTION",
                  "text_detection_config": {
                      "language_codes": ["ar","en"]
                  }
              }]
          }]
      }
      
  4. Отправьте запрос с помощью метода batchAnalyze и сохраните ответ в файл, например output.json:

    $ export IAM_TOKEN=CggaATEVAgA...
    $ curl -X POST \
        -H "Content-Type: application/json" \
        -H "Authorization: Bearer ${IAM_TOKEN}" \
        -d '@body.json' \
        https://vision.api.cloud.yandex.net/vision/v1/batchAnalyze > output.json
    

Готовая функция для отправки запросов в bash

  1. Если у вас еще нет интерфейса командной строки Яндекс.Облака, установите и инициализируйте его.

  2. Скопируйте в терминал функцию:

    vision_text_detection() {
        if [[ $2 ]]; then MIME_TYPE=$2 ; else MIME_TYPE=image; fi
        curl -H "Authorization: Bearer `yc iam create-token`" \
        "https://vision.api.cloud.yandex.net/vision/v1/batchAnalyze" \
        -d @<(cat << EOF
    {
        "folderId": "`yc config get folder-id`",
        "analyze_specs": [{
            "content": "`base64 -i $1`",
            "features": [{
                "type": "TEXT_DETECTION",
                "text_detection_config": {
                    "language_codes": ["*"]
                }
            }],
            "mime_type": "$MIME_TYPE"
        }]
    }
    EOF
    )
    }
    

    Пояснения:

    • yc iam create-token — получить IAM-токен.
    • -d @<(cat << EOF ... EOF) — сформировать тело запроса.
    • yc config get folder-id — получить ID каталога, выбранного по умолчанию в CLI.
    • base64 -i $1 — кодировать в Base64 изображение, переданное в аргументах функции.
  3. Теперь вы можете вызывать эту функцию, передав путь к файлу в аргументах:

    vision_text_detection path/to/image.jpg
    

    Вторым аргументом вы можете передать MIME-тип. Например, чтобы распознать PDF-файл, вызовите:

    vision_text_detection path/to/document.pdf application/pdf
    

Примеры кода

В примерах ниже показан код скрипта для распознавания текста. Аутентификация реализована для аккаунта на Яндексе с помощью OAuth-токена (подробнее о способах аутентификации).

Создайте файл скрипта, например text_detection.go и скопируйте в него следующий код:

package main

import (
    "bytes"
    "encoding/base64"
    "encoding/json"
    "errors"
    "flag"
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
)

// Функция возвращает IAM-токен для аккаунта на Яндексе.
func GetIamToken(iamURL, oauthToken string) (string, error) {
    body, err := json.Marshal(&IamTokenRequest{YandexPassportOauthToken: oauthToken})
    if err != nil {
        return "", err
    }

    resp, err := http.Post(iamURL, "application/json", bytes.NewReader(body))
    if err != nil {
        return "", errors.New("Failed to obtain IAM token by oAuth token: " + err.Error())
    }

    if resp.StatusCode != http.StatusOK {
        return "", fmt.Errorf("Auth service returned status %d", resp.StatusCode)
    }

    defer func() {
        err := resp.Body.Close()
        if err != nil {
            log.Fatal(err)
        }
    }()

    respBody, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return "", err
    }

    iamTokenResponse := &IamTokenResponse{}
    err = json.Unmarshal(respBody, iamTokenResponse)
    if err != nil {
        return "", err
    }

    return iamTokenResponse.IamToken, nil
}

type IamTokenRequest struct {
    YandexPassportOauthToken string `json:"yandexPassportOauthToken"`
}

type IamTokenResponse struct {
    IamToken string
}

// Функция отправляет на сервер запрос на распознавание изображения и возвращает ответ сервера.
func RequestAnalyze(visionURL, iamToken, folderID, imageBase64 string) (string, error) {
    request := BatchAnalyzeRequest{
        FolderID: folderID,
        AnalyzeSpecs: []AnalyzeSpec{
            {
                Content: imageBase64,
                Features: []Feature{
                    {
                        Type: "TEXT_DETECTION",
                        TextDetectionConfig: TextDetectionConfig{
                            LanguageCodes: []string{
                                "en",
                                "ru",
                            },
                        },
                    },
                },
            },
        },
    }

    body, err := json.Marshal(&request)
    if err != nil {
        return "", err
    }

    req, err := http.NewRequest("POST", visionURL, bytes.NewReader(body))
    if err != nil {
        return "", errors.New("Failed to prepare request: " + err.Error())
    }
    req.Header.Set("Content-Type", "application/json")
    req.Header.Set("Authorization", "Bearer "+iamToken)

    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        return "", errors.New("Failed to process request: " + err.Error())
    }

    if resp.StatusCode != http.StatusOK {
        return "", fmt.Errorf("Service returned status %d", resp.StatusCode)
    }

    defer func() {
        err := resp.Body.Close()
        if err != nil {
            log.Panic(err)
        }
    }()

    respBody, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return "", err
    }

    return string(respBody), nil
}

type BatchAnalyzeRequest struct {
    FolderID     string        `json:"folderId"`
    AnalyzeSpecs []AnalyzeSpec `json:"analyzeSpecs"`
}

type AnalyzeSpec struct {
    Content  string    `json:"content"`
    Features []Feature `json:"features"`
}

type Feature struct {
    Type                string `json:"type"`
    TextDetectionConfig `json:"textDetectionConfig"`
}

type TextDetectionConfig struct {
    LanguageCodes []string `json:"languageCodes"`
}

func main() {
    iamURL := "https://iam.api.cloud.yandex.net/iam/v1/tokens"
    visionURL := "https://vision.api.cloud.yandex.net/vision/v1/batchAnalyze"

    oauthToken := flag.String("oauth-token", "", "oAuth token to obtain IAM token")
    folderID := flag.String("folder-id", "", "Folder ID")
    imagePath := flag.String("image-path", "", "Path to image to recognize")
    flag.Parse()

    iamToken, err := GetIamToken(iamURL, *oauthToken)
    if err != nil {
        log.Panic(err)
    }

    imageData, err := ioutil.ReadFile(*imagePath)
    if err != nil {
        log.Panic(err)
    }
    imageBase64 := base64.StdEncoding.EncodeToString(imageData)

    responseText, err := RequestAnalyze(visionURL, iamToken, *folderID, imageBase64)
    if err != nil {
        log.Panic(err)
    }
    fmt.Print(responseText)
}

Выполните скрипт из командной строки. В аргументах передайте OAuth-токен, идентификатор каталога и путь к файлу изображения:

$ export TOKEN=AgAAAAAMTH...
$ export FOLDER_ID=b1gvmob95yysaplct532
$ go run text_detection.go -folder-id $FOLDER_ID -oauth-token $TOKEN -image-path input.jpg

Создайте файл скрипта, например text_detection.py и скопируйте в него следующий код:

# coding: utf-8
from requests import post
import json
import argparse
import base64

# Функция возвращает IAM-токен для аккаунта на Яндексе.
def get_iam_token(iam_url, oauth_token):
    response = post(iam_url, json={"yandexPassportOauthToken": oauth_token})
    json_data = json.loads(response.text)
    if json_data is not None and 'iamToken' in json_data:
        return json_data['iamToken']
    return None

# Функция отправляет на сервер запрос на распознавание изображения и возвращает ответ сервера.
def request_analyze(vision_url, iam_token, folder_id, image_data):
    response = post(vision_url, headers={'Authorization': 'Bearer '+iam_token}, json={
        'folderId': folder_id,
        'analyzeSpecs': [
            {
                'content': image_data,
                'features': [
                    {
                        'type': 'TEXT_DETECTION',
                        'textDetectionConfig': {'languageCodes': ['en', 'ru']}
                    }
                ],
            }
        ]})
    return response.text


def main():
    parser = argparse.ArgumentParser()

    parser.add_argument('--folder-id', required=True)
    parser.add_argument('--oauth-token', required=True)
    parser.add_argument('--image-path', required=True)
    args = parser.parse_args()

    iam_url = 'https://iam.api.cloud.yandex.net/iam/v1/tokens'
    vision_url = 'https://vision.api.cloud.yandex.net/vision/v1/batchAnalyze'

    iam_token = get_iam_token(iam_url, args.oauth_token)
    with open(args.image_path, "rb") as f:
        image_data = base64.b64encode(f.read()).decode('utf-8')
    response_text = request_analyze(vision_url, iam_token, args.folder_id, image_data)
    print(response_text)


if __name__ == '__main__':
    main()

Выполните скрипт из командной строки. В аргументах передайте OAuth-токен, идентификатор каталога и путь к файлу изображения:

$ export TOKEN=AgAAAAAMTH...
$ export FOLDER_ID=b1gvmob95yysaplct532
$ python text_detection.py --folder-id=$FOLDER_ID --oauth-token=$TOKEN --image-path=input.jpg