Извлечение текста и сведений из изображений в обогащении ИИ

Благодаря обогащению ИИ Поиск Azure предоставляет несколько вариантов создания и извлечения текста, доступного для поиска, из изображений, включая:

  • OCR для оптического распознавания символов текста и цифр
  • Анализ изображений, описывающий изображения с помощью визуальных функций
  • Пользовательские навыки для вызова любой обработки внешних изображений, которые требуется предоставить

С помощью OCR можно извлечь текст из фотографий или рисунков, содержащих буквенно-цифровой текст, например слово STOP в знаке остановки. С помощью анализа изображений можно создать текстовое представление изображения, например "одуванчик" для фотографии одуванчика или цвета "желтый". Также можно извлечь такие метаданные изображения, как его размер.

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

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

  • Исходные файлы, содержащие изображения
  • Индексатор поиска, настроенный для действий с изображением
  • Набор навыков со встроенными или настраиваемыми навыками, которые вызывают анализ OCR или изображения
  • Индекс поиска с полями для получения проанализированных текстовых выходных данных, а также сопоставления полей выходных данных в индексаторе, устанавливающего связь.

При необходимости можно определить проекции для приема выходных данных, проанализированных с помощью изображения, в хранилище знаний для сценариев интеллектуального анализа данных.

Настройка исходных файлов

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

  • Анализ изображений поддерживает JPEG, PNG, GIF и BMP
  • OCR поддерживает JPEG, PNG, BMP и TIF

Изображения — это автономные двоичные файлы или внедренные в документы (PDF, RTF и файлы приложений Майкрософт). Из данного документа можно извлечь не более 1000 изображений. Если в документе более 1000 изображений, извлекаются первые 1000, а затем создается предупреждение.

Хранилище BLOB-объектов Azure является наиболее часто используемым хранилищем для обработки изображений в поиске ИИ Azure. Существует три основных задачи, связанные с извлечением изображений из контейнера BLOB-объектов:

Настройка индексаторов для обработки изображений

После настройки исходных файлов включите нормализацию изображений, задав imageAction параметр в конфигурации индексатора. Нормализация изображений помогает сделать изображения более универсальными для последующей обработки. Нормализация изображений включает следующие операции:

  • Большие изображения изменяются до максимальной высоты и ширины, чтобы сделать их универсальными.
  • Для изображений, имеющих метаданные в ориентации, поворот изображения настраивается для вертикальной загрузки.

Изменения метаданных записываются в сложном типе, создаваемом для каждого изображения. Вы не можете отказаться от требования нормализации изображений. Навыки, которые итерируют изображения, такие как OCR и анализ изображений, ожидают нормализованных изображений.

  1. Создайте или обновите индексатор , чтобы задать свойства конфигурации:

    {
      "parameters":
      {
        "configuration": 
        {
           "dataToExtract": "contentAndMetadata",
           "parsingMode": "default",
           "imageAction": "generateNormalizedImages"
        }
      }
    }
    
  2. Задайте значение dataToExtractcontentAndMetadata (обязательно).

  3. Убедитесь, что parsingMode задано значение по умолчанию (обязательно).

    Этот параметр определяет степень детализации документов поиска, созданных в индексе. Режим по умолчанию настраивает одно-одно соответствие таким образом, чтобы один большой двоичный объект был выполнен в одном документе поиска. Если документы большие или если навыки требуют меньших фрагментов текста, можно добавить навык разделения текста, который подразделяет документ на разбиение на разбиение на страницах для целей обработки. Но для сценариев поиска требуется один большой двоичный объект для каждого документа, если обогащение включает обработку изображений.

  4. Установите для imageAction включения узла normalized_images в дереве обогащения (обязательно):

    • generateNormalizedImages для создания массива нормализованных изображений в рамках взлома документов.

    • generateNormalizedImagePerPage (применяется только к PDF-файлу) для создания массива нормализованных изображений, где каждая страница в PDF-файле отображается на одном выходном изображении. Для файлов, отличных от PDF, поведение этого параметра аналогично тому, как если бы вы установили "generateNormalizedImages". Однако обратите внимание, что параметр "GenerateNormalizedImagePerPage" может сделать операцию индексирования менее производительной по проектированию (особенно для больших документов), так как несколько образов должны быть созданы.

  5. При необходимости настройте ширину или высоту созданных нормализованных изображений:

    • normalizedImageMaxWidth (в пикселях). Значение по умолчанию — 2000. Максимальное значение равно 10000.

    • normalizedImageMaxHeight (в пикселях). Значение по умолчанию — 2000. Максимальное значение равно 10000.

    По умолчанию навыками OCR и анализа изображений поддерживаются нормализованные изображения с максимальными шириной и высотой в 2000 пикселей. Навык OCR поддерживает максимальную ширину и высоту 4200 для языков, отличных от английского, и 10 000 для английского языка. Если увеличить максимальные пределы, то обработка может завершиться сбоем на больших изображениях в зависимости от определения набора навыков и языка документов.

  • При необходимости задайте критерии типа файла, если рабочая нагрузка нацелена на определенный тип файла. Конфигурация индексатора BLOB-объектов включает в себя параметры включения файлов и исключений. Вы можете отфильтровать файлы, которые вы не хотите.

    {
      "parameters" : { 
          "configuration" : { 
              "indexedFileNameExtensions" : ".pdf, .docx",
              "excludedFileNameExtensions" : ".png, .jpeg" 
          } 
      }
    }
    

Сведения о нормализованных изображениях

Если imageAction задано значение, отличное от "none", новое поле normalized_images содержит массив изображений. Каждое изображение представляет сложный тип со следующими элементами:

Элемент изображения Description
data Строка нормализованного изображения в формате JPEG в кодировке Base64.
width Ширина нормализованного изображения в пикселях.
высота Высота нормализованного изображения в пикселях.
originalWidth Исходная ширина изображения перед нормализацией.
originalHeight Исходная высота изображения перед нормализацией.
rotationFromOriginal Поворот против часовой стрелки (в градусах), выполняемый для создания нормализованного изображения. Значение от 0 до 360 градусов. На этом этапе считываются метаданные изображения, созданного камерой или сканером. Обычно поворот выполняется несколько раз на 90 градусов.
contentOffset Смещение символов в поле содержимого, откуда было извлечено изображение. Это поле используется только для файлов с внедренными изображениями. СодержимоеOffset для изображений, извлеченных из PDF-документов, всегда находится в конце текста на странице, из нее было извлечено из документа. Это означает, что изображения отображаются после всего текста на этой странице независимо от исходного расположения изображения на странице.
pageNumber Если изображение было извлечено или визуализировано из PDF-документа, это поле содержит номер страницы в PDF-файле, из которого оно было извлечено или отрисовано, начиная с 1. Если изображение не из PDF-файла, это поле равно 0.

Пример значения normalized_images:

[
  {
    "data": "BASE64 ENCODED STRING OF A JPEG IMAGE",
    "width": 500,
    "height": 300,
    "originalWidth": 5000,  
    "originalHeight": 3000,
    "rotationFromOriginal": 90,
    "contentOffset": 500,
    "pageNumber": 2
  }
]

Определение наборов навыков для обработки изображений

Этот раздел дополняет справочные статьи о навыках, предоставляя контекст для работы с входными данными навыка, выходными данными и шаблонами, так как они относятся к обработке изображений.

  1. Создайте или обновите набор навыков для добавления навыков.

  2. Добавьте шаблоны для OCR и анализа изображений на портале или скопируйте определения из справочной документации по навыку. Вставьте их в массив навыков определения набора навыков.

  3. При необходимости включите ключ с несколькими службами в свойство служб искусственного интеллекта Azure набора навыков. Поиск ИИ Azure выполняет вызовы оплачиваемого ресурса служб ИИ Azure для OCR и анализа изображений для транзакций, превышающих бесплатный лимит (20 на индексатор в день). Службы ИИ Azure должны находиться в том же регионе, что и служба поиска.

  4. Если исходные изображения внедрены в PDF-файлы или файлы приложений, например PPTX или DOCX, необходимо добавить навык слияния текста, если вы хотите, чтобы выходные данные изображения и текстовые выходные данные были вместе. Работа с внедренными изображениями рассматривается далее в этой статье.

После создания базовой платформы набора навыков и настройки служб ИИ Azure можно сосредоточиться на каждом навыке изображения, определении входных данных и контексте источника и сопоставлении выходных данных с полями в индексе или хранилище знаний.

Примечание.

См . руководство по REST: использование REST и ИИ для создания содержимого с возможностью поиска из больших двоичных объектов Azure для примера набора навыков, объединяющего обработку изображений с нижестоящей обработкой естественного языка. В нем показано, как передавать выходные данные изображения навыка в распознавание сущностей и извлечение ключевых фраз.

Сведения о входных данных для обработки изображений

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

  • /document/normalized_images/* предназначен для документов, которые обрабатываются целиком.

  • /document/normalized_images/*/pages предназначен для документов, обрабатываемых в блоках (страницах).

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

    {
      "@odata.type": "#Microsoft.Skills.Vision.OcrSkill",
      "context": "/document/normalized_images/*",
      "detectOrientation": true,
      "inputs": [
        {
          "name": "image",
          "source": "/document/normalized_images/*"
        }
      ],
      "outputs": [ ]
    },
    {
      "@odata.type": "#Microsoft.Skills.Vision.ImageAnalysisSkill",
      "context": "/document/normalized_images/*",
      "visualFeatures": [ "tags", "description" ],
      "inputs": [
        {
          "name": "image",
          "source": "/document/normalized_images/*"
        }
      ],
      "outputs": [ ]
    }

Сопоставление выходных данных с полями поиска

В наборе навыков выходные данные навыка анализа изображений и навыка OCR всегда являются текстом. Выходной текст представлен как узлы во внутреннем обогащенном дереве документов, и каждый узел должен быть сопоставлен с полями в индексе поиска или проекциями в хранилище знаний, чтобы сделать содержимое доступным в приложении.

  1. В наборе навыков просмотрите outputs раздел каждого навыка, чтобы определить, какие узлы существуют в обогащенном документе:

    {
      "@odata.type": "#Microsoft.Skills.Vision.OcrSkill",
      "context": "/document/normalized_images/*",
      "detectOrientation": true,
      "inputs": [ ],
      "outputs": [
        {
          "name": "text",
          "targetName": "text"
        },
        {
          "name": "layoutText",
          "targetName": "layoutText"
        }
      ]
    }
    
  2. Создайте или обновите индекс поиска, чтобы добавить поля для принятия выходных данных навыка.

    В следующем примере коллекции полей "content" — это содержимое BLOB-объектов. "Metadata_storage_name" содержит имя файла (убедитесь, что он является "извлекаемым"). "Metadata_storage_path" является уникальным путем большого двоичного объекта и является ключом документа по умолчанию. "Merged_content" выводится из слияния текста (полезно при внедрении изображений).

    "Text" и "layoutText" являются выходными данными навыка OCR и должны быть строковой коллекцией для записи всех созданных OCR выходных данных для всего документа.

      "fields": [
        {
          "name": "content",
          "type": "Edm.String",
          "filterable": false,
          "retrievable": true,
          "searchable": true,
          "sortable": false
        },
        {
          "name": "metadata_storage_name",
          "type": "Edm.String",
          "filterable": true,
          "retrievable": true,
          "searchable": true,
          "sortable": false
        },
        {
          "name": "metadata_storage_path",
          "type": "Edm.String",
          "filterable": false,
          "key": true,
          "retrievable": true,
          "searchable": false,
          "sortable": false
        },
        {
          "name": "merged_content",
          "type": "Edm.String",
          "filterable": false,
          "retrievable": true,
          "searchable": true,
          "sortable": false
        },
        {
          "name": "text",
          "type": "Collection(Edm.String)",
          "filterable": false,
          "retrievable": true,
          "searchable": true
        },
        {
          "name": "layoutText",
          "type": "Collection(Edm.String)",
          "filterable": false,
          "retrievable": true,
          "searchable": true
        }
      ],
    
  3. Обновите индексатор , чтобы сопоставить выходные данные набора навыков (узлы в дереве обогащения) с полями индекса.

    Обогащенные документы являются внутренними. Чтобы инициализировать узлы в обогащенном дереве документов, настройте сопоставление полей вывода, указывающее, какое поле индекса получает содержимое узла. Обогащенные данные получают доступ к приложению через поле индекса. В следующем примере показан "текстовый" узел (выходные данные OCR) в обогащенном документе, сопоставленном с полем "text" в индексе поиска.

      "outputFieldMappings": [
        {
          "sourceFieldName": "/document/normalized_images/*/text",
          "targetFieldName": "text"
        },
        {
          "sourceFieldName": "/document/normalized_images/*/layoutText",
          "targetFieldName": "layoutText"
        }
      ]
    
  4. Запустите индексатор, чтобы вызвать извлечение исходного документа, обработку изображений и индексирование.

проверите результаты;

Выполните запрос к индексу, чтобы проверка результаты обработки изображений. Используйте Обозреватель поиска в качестве клиента поиска или любого средства, отправляющего HTTP-запросы. Следующий запрос выбирает поля, содержащие выходные данные обработки изображений.

POST /indexes/[index name]/docs/search?api-version=[api-version]
{
    "search": "*",
    "select": "metadata_storage_name, text, layoutText, imageCaption, imageTags"
}

OCR распознает текст в файлах изображений. Это означает, что поля OCR ("text" и "layoutText") пусты, если исходные документы являются чистыми текстовыми или чистыми изображениями. Аналогичным образом поля анализа изображений ("imageCaption" и "imageTags") пусты, если входные данные исходного документа являются строго текстовыми. Выполнение индексатора выдает предупреждения, если входные данные изображения пусты. Такие предупреждения должны ожидаться, когда узлы не заполнены в обогащенном документе. Помните, что индексирование BLOB-объектов позволяет включать или исключать типы файлов, если вы хотите работать с типами контента в изоляции. Эти параметры можно использовать для уменьшения шума во время выполнения индексатора.

Альтернативный запрос к результатам проверка может включать поля content и merged_content. Обратите внимание, что эти поля включают содержимое для любого файла BLOB-объектов, даже тех, где не выполнялась обработка изображений.

Сведения о выходных данных навыка

Выходные данные навыка включают "text" (OCR), "layoutText" (OCR), "merged_content", "подпись" (анализ изображений), "теги" (анализ изображений):

  • Текст сохраняет выходные данные, созданные OCR. Этот узел должен быть сопоставлен с полем типа Collection(Edm.String). Существует одно поле "text" для каждого документа поиска, состоящего из строк с разделителями-запятыми для документов, содержащих несколько изображений. На следующем рисунке показаны выходные данные OCR для трех документов. Сначала это документ, содержащий файл без изображений. Второй — это документ (файл изображения), содержащий одно слово "Майкрософт". Третий — это документ, содержащий несколько изображений, некоторые без текста ("",).

    "value": [
        {
            "@search.score": 1,
            "metadata_storage_name": "facts-about-microsoft.html",
            "text": []
        },
        {
            "@search.score": 1,
            "metadata_storage_name": "guthrie.jpg",
            "text": [ "Microsoft" ]
        },
        {
            "@search.score": 1,
            "metadata_storage_name": "Azure AI services and Content Intelligence.pptx",
            "text": [
                "",
                "Microsoft",
                "",
                "",
                "",
                "Azure AI Search and Augmentation Combining Microsoft Azure AI services and Azure Search"
            ]
        }
    ]
    
  • "layoutText" хранит сведения о расположении текста на странице, созданном OCR, как описано с точки зрения ограничивающих прямоугольников и координат нормализованного изображения. Этот узел должен быть сопоставлен с полем типа Collection(Edm.String). В документе поиска есть одно поле layoutText, состоящее из строк с разделителями-запятыми.

  • "merged_content" сохраняет выходные данные навыка слияния текста, и оно должно быть одним большим полем типа Edm.String , содержащего необработанный текст из исходного документа, с внедренным "текстом" вместо изображения. Если файлы доступны только для текста, то анализ текста и изображения не имеют ничего общего, и "merged_content" совпадает с "content" (свойство BLOB-объекта, содержащее содержимое большого двоичного объекта).

  • ImageCaption записывает описание изображения в виде тегов отдельных лиц и более длинного текстового описания.

  • "ImageTags" сохраняет теги о изображении в виде коллекции ключевое слово, одной коллекции для всех изображений в исходном документе.

На следующем снимках экрана показана иллюстрация PDF-файла, включающего текст и внедренные изображения. В документе трещины обнаружены три внедренных изображения: стая чайок, карты, орла. Другой текст в примере (включая заголовки, заголовки и текст текста) был извлечен как текст и исключен из обработки изображений.

Screenshot of three images in a PDF

Выходные данные анализа изображений иллюстрируются в формате JSON ниже (результат поиска). Определение навыка позволяет указать, какие визуальные функции являются интересующими. В этом примере были созданы теги и описания, но есть больше выходных данных для выбора.

  • Выходные данные imageCaption — это массив описаний, по одному на изображение, обозначаемый "тегами", состоящими из отдельных слов и более длинных фраз, описывающих изображение. Обратите внимание, что теги, состоящие из "стаи морских гулей плавают в воде", или "близко к птице".

  • Выходные данные imageTags — это массив отдельных тегов, указанных в порядке создания. Обратите внимание, что теги повторялись. Нет агрегирования или группировки.

 "imageCaption": [
      "{\"tags\":[\"bird\",\"outdoor\",\"water\",\"flock\",\"many\",\"lot\",\"bunch\",\"group\",\"several\",\"gathered\",\"pond\",\"lake\",\"different\",\"family\",\"flying\",\"standing\",\"little\",\"air\",\"beach\",\"swimming\",\"large\",\"dog\",\"landing\",\"jumping\",\"playing\"],\"captions\":[{\"text\":\"a flock of seagulls are swimming in the water\",\"confidence\":0.70419257326275686}]}",
      "{\"tags\":[\"map\"],\"captions\":[{\"text\":\"map\",\"confidence\":0.99942880868911743}]}",
      "{\"tags\":[\"animal\",\"bird\",\"raptor\",\"eagle\",\"sitting\",\"table\"],\"captions\":[{\"text\":\"a close up of a bird\",\"confidence\":0.89643581933539462}]}",
    . . .

 "imageTags": [
    "bird",
    "outdoor",
    "water",
    "flock",
    "animal",
    "bunch",
    "group",
    "several",
    "drink",
    "gathered",
    "pond",
    "different",
    "family",
    "same",
    "map",
    "text",
    "animal",
    "bird",
    "bird of prey",
    "eagle"
    . . .

Сценарий. Внедренные образы в PDF-файлах

Когда изображения, которые нужно обработать, внедряются в другие файлы, например PDF или DOCX, конвейер обогащения извлекает только изображения, а затем передает их в OCR или анализ изображений для обработки. Извлечение изображений происходит на этапе взлома документа, и после разделения изображений они остаются отдельными, если вы явно не объединяете обработанные выходные данные обратно в исходный текст.

Слияние текста используется для размещения выходных данных обработки изображений обратно в документ. Хотя слияние текста не является жестким требованием, он часто вызывается таким образом, чтобы выходные данные изображения (текст OCR, макет OCR, теги изображений, изображения подпись) можно повторно вводить в документ. В зависимости от навыка выходные данные изображения заменяют внедренное двоичное изображение эквивалентом текста на месте. Выходные данные анализа изображений можно объединить в расположении изображения. Выходные данные OCR всегда отображаются в конце каждой страницы.

Следующий рабочий процесс описывает процесс извлечения изображений, анализа, объединения и расширения конвейера для отправки выходных данных, обработанных изображением, в другие навыки на основе текста, такие как распознавание сущностей или преобразование текста.

  1. После подключения к источнику данных индексатор загружает и разбивает исходные документы, извлекает изображения и текст, а также очереди каждого типа контента для обработки. Обогащенный документ, состоящий только из корневого узла ("document") создается.

  2. Изображения в очереди нормализуются и передаются в обогащенные документы в виде "document/normalized_images" узла.

  3. Обогащения изображений выполняются "/document/normalized_images" в качестве входных данных.

  4. Выходные данные изображения передаются в обогащенное дерево документов с каждым выходом в виде отдельного узла. Выходные данные зависят от навыка (текст и макетText для OCR, тегов и подпись для анализа изображений).

  5. Необязательно, но рекомендуется, если вы хотите, чтобы документы поиска включали текст и текст источника изображения вместе, выполняется слияние текста, сочетая текстовое представление этих изображений с необработанным текстом, извлеченным из файла. Фрагменты текста объединяются в одну большую строку, где текст вставляется сначала в строку, а затем выходные данные текста OCR или теги изображений и подпись.

    Выходные данные слияния текста теперь являются окончательным текстом для анализа всех подчиненных навыков, выполняющих обработку текста. Например, если набор навыков включает как распознавание объектов, так и распознавание сущностей, то входные данные распознавания сущностей должны быть "document/merged_text" (целевое имя выходных данных навыка слияния текста).

  6. После выполнения всех навыков обогащенный документ будет завершен. На последнем шаге индексаторы ссылаются на сопоставления полей вывода для отправки обогащенного содержимого отдельным полям в индексе поиска.

В следующем примере набора навыков создается "merged_text" поле, содержащее исходный текст документа с внедренным текстом OCRed вместо внедренных изображений. Он также включает навык распознавания сущностей, который используется "merged_text" в качестве входных данных.

Синтаксис текста запроса

{
  "description": "Extract text from images and merge with content text to produce merged_text",
  "skills":
  [
    {
        "description": "Extract text (plain and structured) from image.",
        "@odata.type": "#Microsoft.Skills.Vision.OcrSkill",
        "context": "/document/normalized_images/*",
        "defaultLanguageCode": "en",
        "detectOrientation": true,
        "inputs": [
          {
            "name": "image",
            "source": "/document/normalized_images/*"
          }
        ],
        "outputs": [
          {
            "name": "text"
          }
        ]
    },
    {
      "@odata.type": "#Microsoft.Skills.Text.MergeSkill",
      "description": "Create merged_text, which includes all the textual representation of each image inserted at the right location in the content field.",
      "context": "/document",
      "insertPreTag": " ",
      "insertPostTag": " ",
      "inputs": [
        {
          "name":"text", "source": "/document/content"
        },
        {
          "name": "itemsToInsert", "source": "/document/normalized_images/*/text"
        },
        {
          "name":"offsets", "source": "/document/normalized_images/*/contentOffset" 
        }
      ],
      "outputs": [
        {
          "name": "mergedText", "targetName" : "merged_text"
        }
      ]
    },
    {
      "@odata.type": "#Microsoft.Skills.Text.V3.EntityRecognitionSkill",
      "context": "/document",
      "categories": [ "Person"],
      "defaultLanguageCode": "en", 
      "minimumPrecision": 0.5, 
      "inputs": [
        {
            "name": "text", "source": "/document/merged_text"
        }
      ],
      "outputs": [
        {
            "name": "persons", "targetName": "people"
        }
      ]
    }
  ]
}

Теперь, когда у вас есть поле merged_text, его можно сопоставить как поле с возможностью поиска в определении индексатора. Все содержимое файлов, включая текст изображений, будет доступно для поиска.

Сценарий: визуализация ограничивающих прямоугольник

Другой распространенный сценарий — визуализация сведений о макете результатов поиска. Например, можно выделить участок с обнаруженным в изображении фрагментом текста как часть результатов поиска.

Так как шаг OCR выполняется на нормализованных изображениях, координаты макета находятся в нормализованном пространстве изображения, но если необходимо отобразить исходное изображение, преобразуйте точки координат в макет в исходную систему координат изображения.

Следующий алгоритм иллюстрирует шаблон:

/// <summary>
///  Converts a point in the normalized coordinate space to the original coordinate space.
///  This method assumes the rotation angles are multiples of 90 degrees.
/// </summary>
public static Point GetOriginalCoordinates(Point normalized,
                            int originalWidth,
                            int originalHeight,
                            int width,
                            int height,
                            double rotationFromOriginal)
{
    Point original = new Point();
    double angle = rotationFromOriginal % 360;

    if (angle == 0 )
    {
        original.X = normalized.X;
        original.Y = normalized.Y;
    } else if (angle == 90)
    {
        original.X = normalized.Y;
        original.Y = (width - normalized.X);
    } else if (angle == 180)
    {
        original.X = (width -  normalized.X);
        original.Y = (height - normalized.Y);
    } else if (angle == 270)
    {
        original.X = height - normalized.Y;
        original.Y = normalized.X;
    }

    double scalingFactor = (angle % 180 == 0) ? originalHeight / height : originalHeight / width;
    original.X = (int) (original.X * scalingFactor);
    original.Y = (int)(original.Y * scalingFactor);

    return original;
}

Сценарий: навыки пользовательского образа

Изображения также могут передаваться в пользовательские навыки и возвращаться из них. Набор навыков base64 кодирует изображение, передаваемое в пользовательский навык. Чтобы использовать изображение в пользовательском навыке, задайте "/document/normalized_images/*/data" в качестве входных данных для пользовательского навыка. В коде пользовательского навыка декодируйте строку из Base64 перед ее преобразованием в изображение. Чтобы вернуть изображение в набор навыков, сначала закодируйте его в Base64.

Изображение возвращается в виде объекта со следующими свойствами.

 { 
  "$type": "file", 
  "data": "base64String" 
 }

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

Передача изображений в пользовательские навыки

В сценариях, где для работы с изображениями требуется пользовательский навык, можно передавать изображения в пользовательский навык и возвращать текст или изображения. Следующий набор навыков представлен в примере.

Следующий набор навыков принимает нормализованное изображение (полученное во время распознавания документа) и выводит срезы изображения.

Пример набора навыков

{
  "description": "Extract text from images and merge with content text to produce merged_text",
  "skills":
  [
    {
          "@odata.type": "#Microsoft.Skills.Custom.WebApiSkill",
          "name": "ImageSkill",
          "description": "Segment Images",
          "context": "/document/normalized_images/*",
          "uri": "https://your.custom.skill.url",
          "httpMethod": "POST",
          "timeout": "PT30S",
          "batchSize": 100,
          "degreeOfParallelism": 1,
          "inputs": [
            {
              "name": "image",
              "source": "/document/normalized_images/*"
            }
          ],
          "outputs": [
            {
              "name": "slices",
              "targetName": "slices"
            }
          ],
          "httpHeaders": {}
        }
  ]
}

Пример пользовательского навыка

Пользовательский навык находится за пределами набора навыков. В этом случае это код Python, который сначала циклит пакет записей запросов в пользовательском формате навыка, а затем преобразует строку в кодировке Base64 в изображение.

# deserialize the request, for each item in the batch
for value in values:
  data = value['data']
  base64String = data["image"]["data"]
  base64Bytes = base64String.encode('utf-8')
  inputBytes = base64.b64decode(base64Bytes)
  # Use numpy to convert the string to an image
  jpg_as_np = np.frombuffer(inputBytes, dtype=np.uint8)
  # you now have an image to work with

Аналогично возврату изображения следует возвращать строку в кодировке Base64 в объекте JSON со свойством $type, равным file.

def base64EncodeImage(image):
    is_success, im_buf_arr = cv2.imencode(".jpg", image)
    byte_im = im_buf_arr.tobytes()
    base64Bytes = base64.b64encode(byte_im)
    base64String = base64Bytes.decode('utf-8')
    return base64String

 base64String = base64EncodeImage(jpg_as_np)
 result = { 
  "$type": "file", 
  "data": base64String 
}

См. также